Skip to content

Commit 8db1c18

Browse files
committed
graph, chain/ethereum: Move declared call related structs to graph crate
1 parent 1dd59c3 commit 8db1c18

File tree

2 files changed

+233
-232
lines changed

2 files changed

+233
-232
lines changed

chain/ethereum/src/data_source.rs

Lines changed: 1 addition & 228 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,17 @@ use graph::components::metrics::subgraph::SubgraphInstanceMetrics;
55
use graph::components::store::{EthereumCallCache, StoredDynamicDataSource};
66
use graph::components::subgraph::{HostMetrics, InstanceDSTemplateInfo, MappingError};
77
use graph::components::trigger_processor::RunnableTriggers;
8-
use graph::data::value::Word;
9-
use graph::data_source::common::{MappingABI, UnresolvedMappingABI};
8+
use graph::data_source::common::{CallDecls, MappingABI, UnresolvedMappingABI};
109
use graph::data_source::CausalityRegion;
1110
use graph::env::ENV_VARS;
1211
use graph::futures03::future::try_join;
1312
use graph::futures03::stream::FuturesOrdered;
1413
use graph::futures03::TryStreamExt;
1514
use graph::prelude::ethabi::ethereum_types::H160;
1615
use graph::prelude::ethabi::{StateMutability, Token};
17-
use graph::prelude::lazy_static;
18-
use graph::prelude::regex::Regex;
1916
use graph::prelude::{Link, SubgraphManifestValidationError};
2017
use graph::slog::{debug, error, o, trace};
2118
use itertools::Itertools;
22-
use serde::de;
2319
use serde::de::Error as ErrorD;
2420
use serde::{Deserialize, Deserializer};
2521
use std::collections::HashSet;
@@ -31,7 +27,6 @@ use tiny_keccak::{keccak256, Keccak};
3127

3228
use graph::{
3329
blockchain::{self, Blockchain},
34-
derive::CheapClone,
3530
prelude::{
3631
async_trait,
3732
ethabi::{Address, Event, Function, LogParam, ParamType, RawLog},
@@ -1569,225 +1564,3 @@ fn string_to_h256(s: &str) -> H256 {
15691564
pub struct TemplateSource {
15701565
pub abi: String,
15711566
}
1572-
1573-
/// Internal representation of declared calls. In the manifest that's
1574-
/// written as part of an event handler as
1575-
/// ```yaml
1576-
/// calls:
1577-
/// - myCall1: Contract[address].function(arg1, arg2, ...)
1578-
/// - ..
1579-
/// ```
1580-
///
1581-
/// The `address` and `arg` fields can be either `event.address` or
1582-
/// `event.params.<name>`. Each entry under `calls` gets turned into a
1583-
/// `CallDcl`
1584-
#[derive(Clone, CheapClone, Debug, Default, Hash, Eq, PartialEq)]
1585-
pub struct CallDecls {
1586-
pub decls: Arc<Vec<CallDecl>>,
1587-
readonly: (),
1588-
}
1589-
1590-
/// A single call declaration, like `myCall1:
1591-
/// Contract[address].function(arg1, arg2, ...)`
1592-
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
1593-
pub struct CallDecl {
1594-
/// A user-defined label
1595-
pub label: String,
1596-
/// The call expression
1597-
pub expr: CallExpr,
1598-
readonly: (),
1599-
}
1600-
impl CallDecl {
1601-
fn address(&self, log: &Log, params: &[LogParam]) -> Result<H160, Error> {
1602-
let address = match &self.expr.address {
1603-
CallArg::Address => log.address,
1604-
CallArg::HexAddress(address) => *address,
1605-
CallArg::Param(name) => {
1606-
let value = params
1607-
.iter()
1608-
.find(|param| &param.name == name.as_str())
1609-
.ok_or_else(|| anyhow!("unknown param {name}"))?
1610-
.value
1611-
.clone();
1612-
value
1613-
.into_address()
1614-
.ok_or_else(|| anyhow!("param {name} is not an address"))?
1615-
}
1616-
};
1617-
Ok(address)
1618-
}
1619-
1620-
fn args(&self, log: &Log, params: &[LogParam]) -> Result<Vec<Token>, Error> {
1621-
self.expr
1622-
.args
1623-
.iter()
1624-
.map(|arg| match arg {
1625-
CallArg::Address => Ok(Token::Address(log.address)),
1626-
CallArg::HexAddress(address) => Ok(Token::Address(*address)),
1627-
CallArg::Param(name) => {
1628-
let value = params
1629-
.iter()
1630-
.find(|param| &param.name == name.as_str())
1631-
.ok_or_else(|| anyhow!("unknown param {name}"))?
1632-
.value
1633-
.clone();
1634-
Ok(value)
1635-
}
1636-
})
1637-
.collect()
1638-
}
1639-
}
1640-
1641-
impl<'de> de::Deserialize<'de> for CallDecls {
1642-
fn deserialize<D>(deserializer: D) -> Result<CallDecls, D::Error>
1643-
where
1644-
D: de::Deserializer<'de>,
1645-
{
1646-
let decls: std::collections::HashMap<String, String> =
1647-
de::Deserialize::deserialize(deserializer)?;
1648-
let decls = decls
1649-
.into_iter()
1650-
.map(|(name, expr)| {
1651-
expr.parse::<CallExpr>().map(|expr| CallDecl {
1652-
label: name,
1653-
expr,
1654-
readonly: (),
1655-
})
1656-
})
1657-
.collect::<Result<_, _>>()
1658-
.map(|decls| Arc::new(decls))
1659-
.map_err(de::Error::custom)?;
1660-
Ok(CallDecls {
1661-
decls,
1662-
readonly: (),
1663-
})
1664-
}
1665-
}
1666-
1667-
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
1668-
pub struct CallExpr {
1669-
pub abi: Word,
1670-
pub address: CallArg,
1671-
pub func: Word,
1672-
pub args: Vec<CallArg>,
1673-
readonly: (),
1674-
}
1675-
1676-
/// Parse expressions of the form `Contract[address].function(arg1, arg2,
1677-
/// ...)` where the `address` and the args are either `event.address` or
1678-
/// `event.params.<name>`.
1679-
///
1680-
/// The parser is pretty awful as it generates error messages that aren't
1681-
/// very helpful. We should replace all this with a real parser, most likely
1682-
/// `combine` which is what `graphql_parser` uses
1683-
impl FromStr for CallExpr {
1684-
type Err = anyhow::Error;
1685-
1686-
fn from_str(s: &str) -> Result<Self, Self::Err> {
1687-
lazy_static! {
1688-
static ref RE: Regex = Regex::new(
1689-
r"(?x)
1690-
(?P<abi>[a-zA-Z0-9_]+)\[
1691-
(?P<address>[^]]+)\]
1692-
\.
1693-
(?P<func>[a-zA-Z0-9_]+)\(
1694-
(?P<args>[^)]*)
1695-
\)"
1696-
)
1697-
.unwrap();
1698-
}
1699-
let x = RE
1700-
.captures(s)
1701-
.ok_or_else(|| anyhow!("invalid call expression `{s}`"))?;
1702-
let abi = Word::from(x.name("abi").unwrap().as_str());
1703-
let address = x.name("address").unwrap().as_str().parse()?;
1704-
let func = Word::from(x.name("func").unwrap().as_str());
1705-
let args: Vec<CallArg> = x
1706-
.name("args")
1707-
.unwrap()
1708-
.as_str()
1709-
.split(',')
1710-
.filter(|s| !s.is_empty())
1711-
.map(|s| s.trim().parse::<CallArg>())
1712-
.collect::<Result<_, _>>()?;
1713-
Ok(CallExpr {
1714-
abi,
1715-
address,
1716-
func,
1717-
args,
1718-
readonly: (),
1719-
})
1720-
}
1721-
}
1722-
1723-
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
1724-
pub enum CallArg {
1725-
HexAddress(Address),
1726-
Address,
1727-
Param(Word),
1728-
}
1729-
1730-
lazy_static! {
1731-
// Matches a 40-character hexadecimal string prefixed with '0x', typical for Ethereum addresses
1732-
static ref ADDR_RE: Regex = Regex::new(r"^0x[0-9a-fA-F]{40}$").unwrap();
1733-
}
1734-
1735-
impl FromStr for CallArg {
1736-
type Err = anyhow::Error;
1737-
1738-
fn from_str(s: &str) -> Result<Self, Self::Err> {
1739-
if ADDR_RE.is_match(s) {
1740-
if let Ok(parsed_address) = Address::from_str(s) {
1741-
return Ok(CallArg::HexAddress(parsed_address));
1742-
}
1743-
}
1744-
1745-
let mut parts = s.split('.');
1746-
match (parts.next(), parts.next(), parts.next()) {
1747-
(Some("event"), Some("address"), None) => Ok(CallArg::Address),
1748-
(Some("event"), Some("params"), Some(param)) => Ok(CallArg::Param(Word::from(param))),
1749-
_ => Err(anyhow!("invalid call argument `{}`", s)),
1750-
}
1751-
}
1752-
}
1753-
1754-
#[test]
1755-
fn test_call_expr() {
1756-
let expr: CallExpr = "ERC20[event.address].balanceOf(event.params.token)"
1757-
.parse()
1758-
.unwrap();
1759-
assert_eq!(expr.abi, "ERC20");
1760-
assert_eq!(expr.address, CallArg::Address);
1761-
assert_eq!(expr.func, "balanceOf");
1762-
assert_eq!(expr.args, vec![CallArg::Param("token".into())]);
1763-
1764-
let expr: CallExpr = "Pool[event.params.pool].fees(event.params.token0, event.params.token1)"
1765-
.parse()
1766-
.unwrap();
1767-
assert_eq!(expr.abi, "Pool");
1768-
assert_eq!(expr.address, CallArg::Param("pool".into()));
1769-
assert_eq!(expr.func, "fees");
1770-
assert_eq!(
1771-
expr.args,
1772-
vec![
1773-
CallArg::Param("token0".into()),
1774-
CallArg::Param("token1".into())
1775-
]
1776-
);
1777-
1778-
let expr: CallExpr = "Pool[event.address].growth()".parse().unwrap();
1779-
assert_eq!(expr.abi, "Pool");
1780-
assert_eq!(expr.address, CallArg::Address);
1781-
assert_eq!(expr.func, "growth");
1782-
assert_eq!(expr.args, vec![]);
1783-
1784-
let expr: CallExpr = "Pool[0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF].growth(0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF)"
1785-
.parse()
1786-
.unwrap();
1787-
let call_arg =
1788-
CallArg::HexAddress(H160::from_str("0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF").unwrap());
1789-
assert_eq!(expr.abi, "Pool");
1790-
assert_eq!(expr.address, call_arg);
1791-
assert_eq!(expr.func, "growth");
1792-
assert_eq!(expr.args, vec![call_arg]);
1793-
}

0 commit comments

Comments
 (0)