substreams_ethereum_abigen/
build.rs

1use std::path::{Path, PathBuf};
2use std::str;
3
4use crate::{generate_abi_code, generate_abi_code_from_bytes, normalize_path};
5use anyhow::Context;
6
7#[derive(Debug, Clone)]
8pub struct Abigen<'a> {
9    /// The path where to find the source of the ABI JSON for the contract whose bindings
10    /// are being generated.
11    abi_path: PathBuf,
12
13    /// The bytes of the ABI for the contract whose bindings are being generated.
14    bytes: Option<&'a [u8]>,
15}
16
17impl<'a> Abigen<'a> {
18    /// Creates a new builder for the given contract name and where the ABI JSON file can be found
19    /// at `path`, which is relative to the your crate's root directory (where `Cargo.toml` file is located).
20    pub fn new<S: AsRef<str>>(_contract_name: S, path: S) -> Result<Self, anyhow::Error> {
21        let path = normalize_path(path.as_ref()).context("normalize path")?;
22
23        Ok(Self {
24            abi_path: path,
25            bytes: None,
26        })
27    }
28
29    /// Creates a new builder for the given contract name and where the ABI bytes can be found
30    /// at 'abi_bytes'.
31    pub fn from_bytes<S: AsRef<str>>(
32        _contract_name: S,
33        abi_bytes: &'a [u8],
34    ) -> Result<Self, anyhow::Error> {
35        Ok(Self {
36            abi_path: "".parse()?,
37            bytes: Some(abi_bytes),
38        })
39    }
40
41    pub fn generate(&self) -> Result<GeneratedBindings, anyhow::Error> {
42        let tokens = match &self.bytes {
43            None => generate_abi_code(self.abi_path.to_string_lossy()),
44            Some(bytes) => generate_abi_code_from_bytes(bytes),
45        }
46        .context("generating abi code")?;
47
48        let file = syn::parse_file(&tokens.to_string()).context("parsing generated code")?;
49
50        let code = vec![
51            "// @generated",
52            "// This file was @generated by `substreams-ethereum-abigen`. Do not edit it by hand.",
53            "",
54        ]
55        .into_iter()
56        .chain(prettyplease::unparse(&file).lines())
57        .collect::<Vec<_>>()
58        .join("\n");
59
60        Ok(GeneratedBindings { code })
61    }
62}
63
64pub struct GeneratedBindings {
65    code: String,
66}
67
68impl GeneratedBindings {
69    pub fn write_to_file<P: AsRef<Path>>(&self, p: P) -> Result<(), anyhow::Error> {
70        let path = normalize_path(p.as_ref()).context("normalize path")?;
71
72        if let Some(parent) = path.parent() {
73            std::fs::create_dir_all(parent)
74                .with_context(|| format!("creating directories for {}", parent.to_string_lossy()))?
75        }
76
77        std::fs::write(path, &self.code)
78            .with_context(|| format!("writing file {}", p.as_ref().to_string_lossy()))
79    }
80}