pub struct MultiBindings { /* private fields */ }
Expand description

Output of the MultiAbigen build process. MultiBindings wraps a group of built contract bindings that have yet to be written to disk.

MultiBindings enables the user to

  1. Write a collection of bindings to a rust module
  2. Write a collection of bindings to a rust lib
  3. Ensure that a collection of bindings matches an on-disk module or lib.

Generally we recommend writing the bindings to a module folder within your rust project. Users seeking to create “official” bindings for some project may instead write an entire library to publish via crates.io.

Rather than using MultiAbigen in a build script, we recommend committing the generated files, and replacing the build script with an integration test. To enable this, we have provided MultiBindings::ensure_consistent_bindings and MultiBindings::ensure_consistent_crate. These functions generate the expected module or library in memory, and check that the on-disk files match the expected files. We recommend running these inside CI.

This has several advantages:

  • No need for downstream users to compile the build script
  • No need for downstream users to run the whole abigen! generation steps
  • The generated code is more usable in an IDE
  • CI will fail if the generated code is out of date (if abigen! or the contract’s ABI itself changed)

Implementations§

source§

impl MultiBindings

source

pub fn len(&self) -> usize

Returns the number of contracts to generate bindings for.

source

pub fn is_empty(&self) -> bool

Returns whether there are any bindings to be generated

source

pub fn format(self, format: bool) -> Self

Specify whether to format the code or not. True by default.

This will use prettyplease, so the resulting formatted code will not be affected by the local rustfmt version or config.

source

pub fn dependencies( self, dependencies: impl IntoIterator<Item = impl Into<String>> ) -> Self

Specify a set of dependencies to use for the generated crate.

By default, this is empty and only the ethers dependency is added.

source

pub fn write_to_module( self, module: impl AsRef<Path>, single_file: bool ) -> Result<()>

Generates all the bindings and writes them to the given module

§Example

Read all json abi files from the ./abi directory

abi
├── ERC20.json
├── Contract1.json
├── Contract2.json
...

and write them to the ./src/contracts location as

src/contracts
├── mod.rs
├── er20.rs
├── contract1.rs
├── contract2.rs
...
let gen = MultiAbigen::from_json_files("./abi").unwrap();
let bindings = gen.build().unwrap();
bindings.write_to_module("./src/contracts", false).unwrap();
source

pub fn write_to_crate( self, name: impl AsRef<str>, version: impl AsRef<str>, lib: impl AsRef<Path>, single_file: bool ) -> Result<()>

Generates all the bindings and writes a library crate containing them to the provided path

§Example

Read all json abi files from the ./abi directory

abi
├── ERC20.json
├── Contract1.json
├── Contract2.json
├── Contract3/
    ├── Contract3.json
...

and write them to the ./bindings location as

bindings
├── Cargo.toml
├── src/
    ├── lib.rs
    ├── er20.rs
    ├── contract1.rs
    ├── contract2.rs
...
let gen = MultiAbigen::from_json_files("./abi").unwrap();
let bindings = gen.build().unwrap();
bindings.write_to_crate(
    "my-crate", "0.0.5", "./bindings", false
).unwrap();
source

pub fn ensure_consistent_crate( self, name: impl AsRef<str>, version: impl AsRef<str>, crate_path: impl AsRef<Path>, single_file: bool, check_cargo_toml: bool ) -> Result<()>

This ensures that the already generated bindings crate matches the output of a fresh new run. Run this in a rust test, to get notified in CI if the newly generated bindings deviate from the already generated ones, and it’s time to generate them again. This could happen if the ABI of a contract or the output that ethers generates changed.

If this functions is run within a test during CI and fails, then it’s time to update all bindings.

§Returns

Ok(()) if the freshly generated bindings match with the existing bindings. Otherwise an Err(_) containing an eyre::Report with more information.

§Example

Check that the generated files are up to date

#[test]
fn generated_bindings_are_fresh() {
 let project_root = std::path::Path::new(&env!("CARGO_MANIFEST_DIR"));
 let abi_dir = project_root.join("abi");
 let gen = MultiAbigen::from_json_files(&abi_dir).unwrap();
 let bindings = gen.build().unwrap();
 bindings.ensure_consistent_crate(
    "my-crate", "0.0.1", project_root.join("src/contracts"), false, true
 ).expect("inconsistent bindings");
}
source

pub fn ensure_consistent_module( self, module: impl AsRef<Path>, single_file: bool ) -> Result<()>

This ensures that the already generated bindings module matches the output of a fresh new run. Run this in a rust test, to get notified in CI if the newly generated bindings deviate from the already generated ones, and it’s time to generate them again. This could happen if the ABI of a contract or the output that ethers generates changed.

If this functions is run within a test during CI and fails, then it’s time to update all bindings.

§Returns

Ok(()) if the freshly generated bindings match with the existing bindings. Otherwise an Err(_) containing an eyre::Report with more information.

§Example

Check that the generated files are up to date

#[test]
fn generated_bindings_are_fresh() {
 let project_root = std::path::Path::new(&env!("CARGO_MANIFEST_DIR"));
 let abi_dir = project_root.join("abi");
 let gen = MultiAbigen::from_json_files(&abi_dir).unwrap();
 let bindings = gen.build().unwrap();
 bindings.ensure_consistent_module(
    project_root.join("src/contracts"), false
 ).expect("inconsistent bindings");
}

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

impl<T> JsonSchemaMaybe for T