Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 71 additions & 14 deletions chain/ethereum/src/data_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use graph::components::store::{EthereumCallCache, StoredDynamicDataSource};
use graph::components::subgraph::{HostMetrics, InstanceDSTemplateInfo, MappingError};
use graph::components::trigger_processor::RunnableTriggers;
use graph::data_source::common::{
CallDecls, DeclaredCall, FindMappingABI, MappingABI, UnresolvedMappingABI,
AbiJson, CallDecls, DeclaredCall, FindMappingABI, MappingABI, UnresolvedCallDecls,
UnresolvedMappingABI,
};
use graph::data_source::{CausalityRegion, MappingTrigger as MappingTriggerType};
use graph::env::ENV_VARS;
Expand Down Expand Up @@ -800,7 +801,7 @@ impl DataSource {
"transaction" => format!("{}", &transaction.hash),
});
let handler = event_handler.handler.clone();
let calls = DeclaredCall::from_log_trigger(
let calls = DeclaredCall::from_log_trigger_with_event(
&self.mapping,
&event_handler.calls,
&log,
Expand Down Expand Up @@ -1200,6 +1201,7 @@ impl blockchain::UnresolvedDataSource<Chain> for UnresolvedDataSource {
resolver: &Arc<dyn LinkResolver>,
logger: &Logger,
manifest_idx: u32,
spec_version: &semver::Version,
) -> Result<DataSource, anyhow::Error> {
let UnresolvedDataSource {
kind,
Expand All @@ -1210,7 +1212,7 @@ impl blockchain::UnresolvedDataSource<Chain> for UnresolvedDataSource {
context,
} = self;

let mapping = mapping.resolve(resolver, logger).await.with_context(|| {
let mapping = mapping.resolve(resolver, logger, spec_version).await.with_context(|| {
format!(
"failed to resolve data source {} with source_address {:?} and source_start_block {}",
name, source.address, source.start_block
Expand All @@ -1221,7 +1223,7 @@ impl blockchain::UnresolvedDataSource<Chain> for UnresolvedDataSource {
}
}

#[derive(Clone, Debug, Default, Hash, Eq, PartialEq, Deserialize)]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize)]
pub struct UnresolvedDataSourceTemplate {
pub kind: String,
pub network: Option<String>,
Expand All @@ -1247,6 +1249,7 @@ impl blockchain::UnresolvedDataSourceTemplate<Chain> for UnresolvedDataSourceTem
resolver: &Arc<dyn LinkResolver>,
logger: &Logger,
manifest_idx: u32,
spec_version: &semver::Version,
) -> Result<DataSourceTemplate, anyhow::Error> {
let UnresolvedDataSourceTemplate {
kind,
Expand All @@ -1257,7 +1260,7 @@ impl blockchain::UnresolvedDataSourceTemplate<Chain> for UnresolvedDataSourceTem
} = self;

let mapping = mapping
.resolve(resolver, logger)
.resolve(resolver, logger, spec_version)
.await
.with_context(|| format!("failed to resolve data source template {}", name))?;

Expand Down Expand Up @@ -1294,7 +1297,7 @@ impl blockchain::DataSourceTemplate<Chain> for DataSourceTemplate {
}
}

#[derive(Clone, Debug, Default, Hash, Eq, PartialEq, Deserialize)]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UnresolvedMapping {
pub kind: String,
Expand All @@ -1307,7 +1310,7 @@ pub struct UnresolvedMapping {
#[serde(default)]
pub call_handlers: Vec<MappingCallHandler>,
#[serde(default)]
pub event_handlers: Vec<MappingEventHandler>,
pub event_handlers: Vec<UnresolvedMappingEventHandler>,
pub file: Link,
}

Expand Down Expand Up @@ -1357,6 +1360,7 @@ impl UnresolvedMapping {
self,
resolver: &Arc<dyn LinkResolver>,
logger: &Logger,
spec_version: &semver::Version,
) -> Result<Mapping, anyhow::Error> {
let UnresolvedMapping {
kind,
Expand All @@ -1376,9 +1380,7 @@ impl UnresolvedMapping {
// resolve each abi
abis.into_iter()
.map(|unresolved_abi| async {
Result::<_, Error>::Ok(Arc::new(
unresolved_abi.resolve(resolver, logger).await?,
))
Result::<_, Error>::Ok(unresolved_abi.resolve(resolver, logger).await?)
})
.collect::<FuturesOrdered<_>>()
.try_collect::<Vec<_>>(),
Expand All @@ -1390,15 +1392,35 @@ impl UnresolvedMapping {
.await
.with_context(|| format!("failed to resolve mapping {}", link.link))?;

// Resolve event handlers with ABI context
let resolved_event_handlers = event_handlers
.into_iter()
.map(|unresolved_handler| {
// Find the ABI for this event handler
let (_, abi_json) = abis.first().ok_or_else(|| {
anyhow!(
"No ABI found for event '{}' in event handler '{}'",
unresolved_handler.event,
unresolved_handler.handler
)
})?;

unresolved_handler.resolve(abi_json, &spec_version)
})
.collect::<Result<Vec<_>, anyhow::Error>>()?;

// Extract just the MappingABIs for the final Mapping struct
let mapping_abis = abis.into_iter().map(|(abi, _)| Arc::new(abi)).collect();

Ok(Mapping {
kind,
api_version,
language,
entities,
abis,
abis: mapping_abis,
block_handlers: block_handlers.clone(),
call_handlers: call_handlers.clone(),
event_handlers: event_handlers.clone(),
event_handlers: resolved_event_handlers,
runtime,
link,
})
Expand Down Expand Up @@ -1442,8 +1464,8 @@ pub struct MappingCallHandler {
pub handler: String,
}

#[derive(Clone, Debug, Hash, Eq, PartialEq, Deserialize)]
pub struct MappingEventHandler {
#[derive(Clone, Debug, Eq, PartialEq, Deserialize)]
pub struct UnresolvedMappingEventHandler {
pub event: String,
pub topic0: Option<H256>,
#[serde(deserialize_with = "deserialize_h256_vec", default)]
Expand All @@ -1456,6 +1478,41 @@ pub struct MappingEventHandler {
#[serde(default)]
pub receipt: bool,
#[serde(default)]
pub calls: UnresolvedCallDecls,
}

impl UnresolvedMappingEventHandler {
pub fn resolve(
self,
abi_json: &AbiJson,
spec_version: &semver::Version,
) -> Result<MappingEventHandler, anyhow::Error> {
let resolved_calls = self
.calls
.resolve(abi_json, Some(&self.event), spec_version)?;

Ok(MappingEventHandler {
event: self.event,
topic0: self.topic0,
topic1: self.topic1,
topic2: self.topic2,
topic3: self.topic3,
handler: self.handler,
receipt: self.receipt,
calls: resolved_calls,
})
}
}

#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub struct MappingEventHandler {
pub event: String,
pub topic0: Option<H256>,
pub topic1: Option<Vec<H256>>,
pub topic2: Option<Vec<H256>>,
pub topic3: Option<Vec<H256>>,
pub handler: String,
pub receipt: bool,
pub calls: CallDecls,
}

Expand Down
2 changes: 2 additions & 0 deletions chain/near/src/data_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ impl blockchain::UnresolvedDataSource<Chain> for UnresolvedDataSource {
resolver: &Arc<dyn LinkResolver>,
logger: &Logger,
_manifest_idx: u32,
_spec_version: &semver::Version,
) -> Result<DataSource, Error> {
let UnresolvedDataSource {
kind,
Expand Down Expand Up @@ -372,6 +373,7 @@ impl blockchain::UnresolvedDataSourceTemplate<Chain> for UnresolvedDataSourceTem
resolver: &Arc<dyn LinkResolver>,
logger: &Logger,
_manifest_idx: u32,
_spec_version: &semver::Version,
) -> Result<DataSourceTemplate, Error> {
let UnresolvedDataSourceTemplate {
kind,
Expand Down
14 changes: 11 additions & 3 deletions chain/substreams/src/data_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ impl blockchain::UnresolvedDataSource<Chain> for UnresolvedDataSource {
resolver: &Arc<dyn LinkResolver>,
logger: &Logger,
_manifest_idx: u32,
_spec_version: &semver::Version,
) -> Result<DataSource, Error> {
let content = resolver.cat(logger, &self.source.package.file).await?;

Expand Down Expand Up @@ -317,6 +318,7 @@ impl blockchain::UnresolvedDataSourceTemplate<Chain> for NoopDataSourceTemplate
_resolver: &Arc<dyn LinkResolver>,
_logger: &Logger,
_manifest_idx: u32,
_spec_version: &semver::Version,
) -> Result<NoopDataSourceTemplate, anyhow::Error> {
unimplemented!("{}", TEMPLATE_ERROR)
}
Expand All @@ -330,7 +332,7 @@ mod test {
use graph::{
blockchain::{DataSource as _, UnresolvedDataSource as _},
components::link_resolver::LinkResolver,
data::subgraph::LATEST_VERSION,
data::subgraph::{LATEST_VERSION, SPEC_VERSION_1_2_0},
prelude::{async_trait, serde_yaml, JsonValueStream, Link},
slog::{o, Discard, Logger},
substreams::{
Expand Down Expand Up @@ -433,7 +435,10 @@ mod test {
let ds: UnresolvedDataSource = serde_yaml::from_str(TEMPLATE_DATA_SOURCE).unwrap();
let link_resolver: Arc<dyn LinkResolver> = Arc::new(NoopLinkResolver {});
let logger = Logger::root(Discard, o!());
let ds: DataSource = ds.resolve(&link_resolver, &logger, 0).await.unwrap();
let ds: DataSource = ds
.resolve(&link_resolver, &logger, 0, &SPEC_VERSION_1_2_0)
.await
.unwrap();
let expected = DataSource {
kind: SUBSTREAMS_KIND.into(),
network: Some("mainnet".into()),
Expand Down Expand Up @@ -470,7 +475,10 @@ mod test {
serde_yaml::from_str(TEMPLATE_DATA_SOURCE_WITH_PARAMS).unwrap();
let link_resolver: Arc<dyn LinkResolver> = Arc::new(NoopLinkResolver {});
let logger = Logger::root(Discard, o!());
let ds: DataSource = ds.resolve(&link_resolver, &logger, 0).await.unwrap();
let ds: DataSource = ds
.resolve(&link_resolver, &logger, 0, &SPEC_VERSION_1_2_0)
.await
.unwrap();
let expected = DataSource {
kind: SUBSTREAMS_KIND.into(),
network: Some("mainnet".into()),
Expand Down
14 changes: 12 additions & 2 deletions docs/subgraph-manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ The `mapping` field may be one of the following supported mapping manifests:

### 1.5.3 Declaring calls

_Available from spec version 1.2.0_
_Available from spec version 1.2.0. Struct field access available from spec version 1.4.0_

Declared calls are performed in parallel before the handler is run and can
greatly speed up syncing. Mappings access the call results simply by using
Expand All @@ -118,7 +118,17 @@ Each call is of the form `<ABI>[<address>].<function>(<args>)`:
| **function** | *String* | The name of a view function in the contract |
| **args** | *[Expr]* | The arguments to pass to the function |

The `Expr` can be either `event.address` or `event.params.<name>`.
#### Expression Types

The `Expr` can be one of the following:

| Expression | Description |
| --- | --- |
| **event.address** | The address of the contract that emitted the event |
| **event.params.&lt;name&gt;** | A simple parameter from the event |
| **event.params.&lt;name&gt;.&lt;index&gt;** | A field from a struct parameter by numeric index |
| **event.params.&lt;name&gt;.&lt;fieldName&gt;** | A field from a struct parameter by field name (spec version 1.4.0+) |


## 1.6 Path
A path has one field `path`, which either refers to a path of a file on the local dev machine or an [IPLD link](https://github.com/ipld/specs/).
Expand Down
2 changes: 2 additions & 0 deletions graph/src/blockchain/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ impl<C: Blockchain> UnresolvedDataSource<C> for MockUnresolvedDataSource {
_resolver: &Arc<dyn LinkResolver>,
_logger: &slog::Logger,
_manifest_idx: u32,
_spec_version: &semver::Version,
) -> Result<C::DataSource, anyhow::Error> {
todo!()
}
Expand Down Expand Up @@ -243,6 +244,7 @@ impl<C: Blockchain> UnresolvedDataSourceTemplate<C> for MockUnresolvedDataSource
_resolver: &Arc<dyn LinkResolver>,
_logger: &slog::Logger,
_manifest_idx: u32,
_spec_version: &semver::Version,
) -> Result<C::DataSourceTemplate, anyhow::Error> {
todo!()
}
Expand Down
2 changes: 2 additions & 0 deletions graph/src/blockchain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ pub trait UnresolvedDataSourceTemplate<C: Blockchain>:
resolver: &Arc<dyn LinkResolver>,
logger: &Logger,
manifest_idx: u32,
spec_version: &semver::Version,
) -> Result<C::DataSourceTemplate, anyhow::Error>;
}

Expand Down Expand Up @@ -407,6 +408,7 @@ pub trait UnresolvedDataSource<C: Blockchain>:
resolver: &Arc<dyn LinkResolver>,
logger: &Logger,
manifest_idx: u32,
spec_version: &semver::Version,
) -> Result<C::DataSource, anyhow::Error>;
}

Expand Down
5 changes: 4 additions & 1 deletion graph/src/data/subgraph/api_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ pub const SPEC_VERSION_1_2_0: Version = Version::new(1, 2, 0);
// represents the write order across all entity types in the subgraph.
pub const SPEC_VERSION_1_3_0: Version = Version::new(1, 3, 0);

// Enables struct field access in declarative calls
pub const SPEC_VERSION_1_4_0: Version = Version::new(1, 4, 0);

// The latest spec version available
pub const LATEST_VERSION: &Version = &SPEC_VERSION_1_3_0;
pub const LATEST_VERSION: &Version = &SPEC_VERSION_1_4_0;

pub const MIN_SPEC_VERSION: Version = Version::new(0, 0, 2);

Expand Down
10 changes: 8 additions & 2 deletions graph/src/data/subgraph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1074,14 +1074,20 @@ impl<C: Blockchain> UnresolvedSubgraphManifest<C> {
data_sources
.into_iter()
.enumerate()
.map(|(idx, ds)| ds.resolve(resolver, logger, idx as u32))
.map(|(idx, ds)| ds.resolve(resolver, logger, idx as u32, &spec_version))
.collect::<FuturesOrdered<_>>()
.try_collect::<Vec<_>>(),
templates
.into_iter()
.enumerate()
.map(|(idx, template)| {
template.resolve(resolver, &schema, logger, ds_count as u32 + idx as u32)
template.resolve(
resolver,
&schema,
logger,
ds_count as u32 + idx as u32,
&spec_version,
)
})
.collect::<FuturesOrdered<_>>()
.try_collect::<Vec<_>>(),
Expand Down
Loading