#![allow(dead_code)] #![allow(unused_imports)] #![deny(missing_docs, unsafe_code)] //! Module for generating type-safe bindings to Ethereum smart contracts. This //! module is intended to be used either indirectly with the `abigen` procedural //! macro or directly from a build script / CLI #[cfg(test)] #[allow(missing_docs)] #[macro_use] #[path = "test/macros.rs"] mod test_macros; mod contract; use contract::Context; mod rustfmt; mod source; mod util; pub use ethers_core::types::Address; pub use source::Source; pub use util::parse_address; use anyhow::Result; use proc_macro2::TokenStream; use std::collections::HashMap; use std::fs::File; use std::io::Write; use std::path::Path; /// Internal global arguments passed to the generators for each individual /// component that control expansion. pub(crate) struct Args { /// The source of the ABI JSON for the contract whose bindings /// are being generated. abi_source: Source, /// Override the contract name to use for the generated type. contract_name: String, /// The runtime crate name to use. runtime_crate_name: String, /// The visibility modifier to use for the generated module and contract /// re-export. visibility_modifier: Option, /// Override the contract module name that contains the generated code. contract_mod_override: Option, /// Manually specified contract method aliases. method_aliases: HashMap, /// Derives added to event structs and enums. event_derives: Vec, } impl Args { /// Creates a new builder given the path to a contract's truffle artifact /// JSON file. pub fn new(contract_name: &str, abi_source: Source) -> Self { Args { abi_source, contract_name: contract_name.to_owned(), runtime_crate_name: "abigen".to_owned(), visibility_modifier: None, contract_mod_override: None, method_aliases: HashMap::new(), event_derives: Vec::new(), } } } /// Internal output options for controlling how the generated code gets /// serialized to file. struct SerializationOptions { /// Format the code using a locally installed copy of `rustfmt`. rustfmt: bool, } impl Default for SerializationOptions { fn default() -> Self { SerializationOptions { rustfmt: true } } } /// Builder for generating contract code. Note that no code is generated until /// the builder is finalized with `generate` or `output`. pub struct Builder { /// The contract binding generation args. args: Args, /// The serialization options. options: SerializationOptions, } impl Builder { /// Creates a new builder given the contract's ABI JSON string pub fn from_str(name: &str, abi: &str) -> Self { Builder::source(name, Source::String(abi.to_owned())) } /// Creates a new builder given the path to a contract's ABI file pub fn new

(name: &str, path: P) -> Self where P: AsRef, { Builder::source(name, Source::local(path)) } /// Creates a new builder from a source URL. pub fn from_url(name: &str, url: S) -> Result where S: AsRef, { let source = Source::parse(url)?; Ok(Builder::source(name, source)) } /// Creates a new builder with the given ABI JSON source. pub fn source(name: &str, source: Source) -> Self { Builder { args: Args::new(name, source), options: SerializationOptions::default(), } } /// Sets the crate name for the runtime crate. This setting is usually only /// needed if the crate was renamed in the Cargo manifest. pub fn runtime_crate_name(mut self, name: S) -> Self where S: Into, { self.args.runtime_crate_name = name.into(); self } /// Sets an optional visibility modifier for the generated module and /// contract re-export. pub fn visibility_modifier(mut self, vis: Option) -> Self where S: Into, { self.args.visibility_modifier = vis.map(S::into); self } /// Sets the optional contract module name override. pub fn contract_mod_override(mut self, name: Option) -> Self where S: Into, { self.args.contract_mod_override = name.map(S::into); self } /// Manually adds a solidity method alias to specify what the method name /// will be in Rust. For solidity methods without an alias, the snake cased /// method name will be used. pub fn add_method_alias(mut self, signature: S1, alias: S2) -> Self where S1: Into, S2: Into, { self.args .method_aliases .insert(signature.into(), alias.into()); self } /// Specify whether or not to format the code using a locally installed copy /// of `rustfmt`. /// /// Note that in case `rustfmt` does not exist or produces an error, the /// unformatted code will be used. pub fn rustfmt(mut self, rustfmt: bool) -> Self { self.options.rustfmt = rustfmt; self } /// Add a custom derive to the derives for event structs and enums. /// /// This makes it possible to for example derive serde::Serialize and /// serde::Deserialize for events. pub fn add_event_derive(mut self, derive: S) -> Self where S: Into, { self.args.event_derives.push(derive.into()); self } /// Generates the contract bindings. pub fn generate(self) -> Result { let tokens = Context::expand(self.args)?; Ok(ContractBindings { tokens, options: self.options, }) } } /// Type-safe contract bindings generated by a `Builder`. This type can be /// either written to file or into a token stream for use in a procedural macro. pub struct ContractBindings { /// The TokenStream representing the contract bindings. tokens: TokenStream, /// The output options used for serialization. options: SerializationOptions, } impl ContractBindings { /// Writes the bindings to a given `Write`. pub fn write(&self, mut w: W) -> Result<()> where W: Write, { let source = { let raw = self.tokens.to_string(); if self.options.rustfmt { rustfmt::format(&raw).unwrap_or(raw) } else { raw } }; w.write_all(source.as_bytes())?; Ok(()) } /// Writes the bindings to the specified file. pub fn write_to_file

(&self, path: P) -> Result<()> where P: AsRef, { let file = File::create(path)?; self.write(file) } /// Converts the bindings into its underlying token stream. This allows it /// to be used within a procedural macro. pub fn into_tokens(self) -> TokenStream { self.tokens } }