Skip to content

Commit ab59a92

Browse files
committed
chain, graph: Thread the spec version into declared call parsing
The code was using the ABI version before, which is wrong
1 parent ad2f476 commit ab59a92

9 files changed

Lines changed: 65 additions & 52 deletions

File tree

chain/ethereum/src/data_source.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,7 @@ impl blockchain::UnresolvedDataSource<Chain> for UnresolvedDataSource {
12001200
resolver: &Arc<dyn LinkResolver>,
12011201
logger: &Logger,
12021202
manifest_idx: u32,
1203+
spec_version: &semver::Version,
12031204
) -> Result<DataSource, anyhow::Error> {
12041205
let UnresolvedDataSource {
12051206
kind,
@@ -1210,7 +1211,7 @@ impl blockchain::UnresolvedDataSource<Chain> for UnresolvedDataSource {
12101211
context,
12111212
} = self;
12121213

1213-
let mapping = mapping.resolve(resolver, logger).await.with_context(|| {
1214+
let mapping = mapping.resolve(resolver, logger, spec_version).await.with_context(|| {
12141215
format!(
12151216
"failed to resolve data source {} with source_address {:?} and source_start_block {}",
12161217
name, source.address, source.start_block
@@ -1247,6 +1248,7 @@ impl blockchain::UnresolvedDataSourceTemplate<Chain> for UnresolvedDataSourceTem
12471248
resolver: &Arc<dyn LinkResolver>,
12481249
logger: &Logger,
12491250
manifest_idx: u32,
1251+
spec_version: &semver::Version,
12501252
) -> Result<DataSourceTemplate, anyhow::Error> {
12511253
let UnresolvedDataSourceTemplate {
12521254
kind,
@@ -1257,7 +1259,7 @@ impl blockchain::UnresolvedDataSourceTemplate<Chain> for UnresolvedDataSourceTem
12571259
} = self;
12581260

12591261
let mapping = mapping
1260-
.resolve(resolver, logger)
1262+
.resolve(resolver, logger, spec_version)
12611263
.await
12621264
.with_context(|| format!("failed to resolve data source template {}", name))?;
12631265

@@ -1357,6 +1359,7 @@ impl UnresolvedMapping {
13571359
self,
13581360
resolver: &Arc<dyn LinkResolver>,
13591361
logger: &Logger,
1362+
spec_version: &semver::Version,
13601363
) -> Result<Mapping, anyhow::Error> {
13611364
let UnresolvedMapping {
13621365
kind,
@@ -1403,7 +1406,7 @@ impl UnresolvedMapping {
14031406
)
14041407
})?;
14051408

1406-
unresolved_handler.resolve(event_abi, Some(&api_version))
1409+
unresolved_handler.resolve(event_abi, &spec_version)
14071410
})
14081411
.collect::<Result<Vec<_>, anyhow::Error>>()?;
14091412

@@ -1480,7 +1483,7 @@ impl UnresolvedMappingEventHandler {
14801483
pub fn resolve(
14811484
self,
14821485
mapping: &MappingABI,
1483-
spec_version: Option<&semver::Version>,
1486+
spec_version: &semver::Version,
14841487
) -> Result<MappingEventHandler, anyhow::Error> {
14851488
let resolved_calls = self
14861489
.calls

chain/near/src/data_source.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ impl blockchain::UnresolvedDataSource<Chain> for UnresolvedDataSource {
333333
resolver: &Arc<dyn LinkResolver>,
334334
logger: &Logger,
335335
_manifest_idx: u32,
336+
_spec_version: &semver::Version,
336337
) -> Result<DataSource, Error> {
337338
let UnresolvedDataSource {
338339
kind,
@@ -372,6 +373,7 @@ impl blockchain::UnresolvedDataSourceTemplate<Chain> for UnresolvedDataSourceTem
372373
resolver: &Arc<dyn LinkResolver>,
373374
logger: &Logger,
374375
_manifest_idx: u32,
376+
_spec_version: &semver::Version,
375377
) -> Result<DataSourceTemplate, Error> {
376378
let UnresolvedDataSourceTemplate {
377379
kind,

chain/substreams/src/data_source.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ impl blockchain::UnresolvedDataSource<Chain> for UnresolvedDataSource {
187187
resolver: &Arc<dyn LinkResolver>,
188188
logger: &Logger,
189189
_manifest_idx: u32,
190+
_spec_version: &semver::Version,
190191
) -> Result<DataSource, Error> {
191192
let content = resolver.cat(logger, &self.source.package.file).await?;
192193

@@ -317,6 +318,7 @@ impl blockchain::UnresolvedDataSourceTemplate<Chain> for NoopDataSourceTemplate
317318
_resolver: &Arc<dyn LinkResolver>,
318319
_logger: &Logger,
319320
_manifest_idx: u32,
321+
_spec_version: &semver::Version,
320322
) -> Result<NoopDataSourceTemplate, anyhow::Error> {
321323
unimplemented!("{}", TEMPLATE_ERROR)
322324
}
@@ -330,7 +332,7 @@ mod test {
330332
use graph::{
331333
blockchain::{DataSource as _, UnresolvedDataSource as _},
332334
components::link_resolver::LinkResolver,
333-
data::subgraph::LATEST_VERSION,
335+
data::subgraph::{LATEST_VERSION, SPEC_VERSION_1_2_0},
334336
prelude::{async_trait, serde_yaml, JsonValueStream, Link},
335337
slog::{o, Discard, Logger},
336338
substreams::{
@@ -433,7 +435,10 @@ mod test {
433435
let ds: UnresolvedDataSource = serde_yaml::from_str(TEMPLATE_DATA_SOURCE).unwrap();
434436
let link_resolver: Arc<dyn LinkResolver> = Arc::new(NoopLinkResolver {});
435437
let logger = Logger::root(Discard, o!());
436-
let ds: DataSource = ds.resolve(&link_resolver, &logger, 0).await.unwrap();
438+
let ds: DataSource = ds
439+
.resolve(&link_resolver, &logger, 0, &SPEC_VERSION_1_2_0)
440+
.await
441+
.unwrap();
437442
let expected = DataSource {
438443
kind: SUBSTREAMS_KIND.into(),
439444
network: Some("mainnet".into()),
@@ -470,7 +475,10 @@ mod test {
470475
serde_yaml::from_str(TEMPLATE_DATA_SOURCE_WITH_PARAMS).unwrap();
471476
let link_resolver: Arc<dyn LinkResolver> = Arc::new(NoopLinkResolver {});
472477
let logger = Logger::root(Discard, o!());
473-
let ds: DataSource = ds.resolve(&link_resolver, &logger, 0).await.unwrap();
478+
let ds: DataSource = ds
479+
.resolve(&link_resolver, &logger, 0, &SPEC_VERSION_1_2_0)
480+
.await
481+
.unwrap();
474482
let expected = DataSource {
475483
kind: SUBSTREAMS_KIND.into(),
476484
network: Some("mainnet".into()),

graph/src/blockchain/mock.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ impl<C: Blockchain> UnresolvedDataSource<C> for MockUnresolvedDataSource {
193193
_resolver: &Arc<dyn LinkResolver>,
194194
_logger: &slog::Logger,
195195
_manifest_idx: u32,
196+
_spec_version: &semver::Version,
196197
) -> Result<C::DataSource, anyhow::Error> {
197198
todo!()
198199
}
@@ -243,6 +244,7 @@ impl<C: Blockchain> UnresolvedDataSourceTemplate<C> for MockUnresolvedDataSource
243244
_resolver: &Arc<dyn LinkResolver>,
244245
_logger: &slog::Logger,
245246
_manifest_idx: u32,
247+
_spec_version: &semver::Version,
246248
) -> Result<C::DataSourceTemplate, anyhow::Error> {
247249
todo!()
248250
}

graph/src/blockchain/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ pub trait UnresolvedDataSourceTemplate<C: Blockchain>:
378378
resolver: &Arc<dyn LinkResolver>,
379379
logger: &Logger,
380380
manifest_idx: u32,
381+
spec_version: &semver::Version,
381382
) -> Result<C::DataSourceTemplate, anyhow::Error>;
382383
}
383384

@@ -407,6 +408,7 @@ pub trait UnresolvedDataSource<C: Blockchain>:
407408
resolver: &Arc<dyn LinkResolver>,
408409
logger: &Logger,
409410
manifest_idx: u32,
411+
spec_version: &semver::Version,
410412
) -> Result<C::DataSource, anyhow::Error>;
411413
}
412414

graph/src/data/subgraph/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,14 +1074,20 @@ impl<C: Blockchain> UnresolvedSubgraphManifest<C> {
10741074
data_sources
10751075
.into_iter()
10761076
.enumerate()
1077-
.map(|(idx, ds)| ds.resolve(resolver, logger, idx as u32))
1077+
.map(|(idx, ds)| ds.resolve(resolver, logger, idx as u32, &spec_version))
10781078
.collect::<FuturesOrdered<_>>()
10791079
.try_collect::<Vec<_>>(),
10801080
templates
10811081
.into_iter()
10821082
.enumerate()
10831083
.map(|(idx, template)| {
1084-
template.resolve(resolver, &schema, logger, ds_count as u32 + idx as u32)
1084+
template.resolve(
1085+
resolver,
1086+
&schema,
1087+
logger,
1088+
ds_count as u32 + idx as u32,
1089+
&spec_version,
1090+
)
10851091
})
10861092
.collect::<FuturesOrdered<_>>()
10871093
.try_collect::<Vec<_>>(),

graph/src/data_source/common.rs

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ impl UnresolvedCallDecls {
618618
self,
619619
mapping: &MappingABI,
620620
event_name: Option<&str>,
621-
spec_version: Option<&semver::Version>,
621+
spec_version: &semver::Version,
622622
) -> Result<CallDecls, anyhow::Error> {
623623
let decls: Result<Vec<CallDecl>, anyhow::Error> = self
624624
.raw_decls
@@ -630,7 +630,7 @@ impl UnresolvedCallDecls {
630630
expr,
631631
readonly: (),
632632
})
633-
.with_context(|| format!("Error in delcared call '{}':", label))
633+
.with_context(|| format!("Error in declared call '{}':", label))
634634
})
635635
.collect();
636636

@@ -698,7 +698,7 @@ impl CallExpr {
698698
s: &str,
699699
mapping: &MappingABI,
700700
event_name: Option<&str>,
701-
spec_version: Option<&semver::Version>,
701+
spec_version: &semver::Version,
702702
) -> Result<Self, anyhow::Error> {
703703
// Parse the expression manually to inject ABI context for field name resolution
704704
// Format: Contract[address].function(arg1, arg2, ...)
@@ -953,7 +953,7 @@ impl CallArg {
953953
s: &str,
954954
mapping_abi: &MappingABI,
955955
event_name: Option<&str>,
956-
spec_version: Option<&semver::Version>,
956+
spec_version: &semver::Version,
957957
) -> Result<Self, anyhow::Error> {
958958
// Handle hex addresses first
959959
if ADDR_RE.is_match(s) {
@@ -974,16 +974,14 @@ impl CallArg {
974974
} else {
975975
// Struct field access: event.params.foo.bar.0.baz...
976976
// Validate spec version before allowing any struct field access
977-
if let Some(spec_ver) = spec_version {
978-
if spec_ver < &SPEC_VERSION_1_4_0 {
977+
if spec_version < &SPEC_VERSION_1_4_0 {
979978
return Err(anyhow!(
980979
"Struct field access 'event.params.{}.*' in declarative calls is only supported for specVersion >= 1.4.0, current version is {}. Event: '{}'",
981980
param,
982-
spec_ver,
981+
spec_version,
983982
event_name.unwrap_or("unknown")
984983
));
985984
}
986-
}
987985

988986
// Resolve field names to indices using ABI context
989987
let mut field_indices = Vec::new();
@@ -1713,7 +1711,7 @@ mod tests {
17131711
"TestContract[event.params.asset.addr].name()",
17141712
&mapping_abi,
17151713
Some("Transfer"),
1716-
None,
1714+
&SPEC_VERSION_1_4_0,
17171715
)
17181716
.unwrap();
17191717

@@ -1730,7 +1728,7 @@ mod tests {
17301728
"TestContract[event.address].transfer(event.params.asset.amount, event.params.asset.1)",
17311729
&mapping_abi,
17321730
Some("Transfer"),
1733-
None,
1731+
&SPEC_VERSION_1_4_0,
17341732
)
17351733
.unwrap();
17361734

@@ -1755,7 +1753,7 @@ mod tests {
17551753
"TestContract[event.params.asset.invalid].name()",
17561754
&mapping_abi,
17571755
Some("Transfer"),
1758-
None,
1756+
&SPEC_VERSION_1_4_0,
17591757
);
17601758
assert!(result.is_err());
17611759
let error = result.unwrap_err();
@@ -1768,7 +1766,7 @@ mod tests {
17681766
"TestContract[event.params.asset.addr].name()",
17691767
&mapping_abi,
17701768
None, // No event name
1771-
None,
1769+
&SPEC_VERSION_1_4_0,
17721770
);
17731771
assert!(result.is_err());
17741772
let error = result.unwrap_err();
@@ -1850,6 +1848,8 @@ mod tests {
18501848
use ethabi::Contract;
18511849
use std::collections::HashMap;
18521850

1851+
const SV: &semver::Version = &SPEC_VERSION_1_4_0;
1852+
18531853
// Create a minimal ABI for testing
18541854
let abi_json = r#"[{"anonymous": false, "inputs": [], "name": "Test", "type": "event"}]"#;
18551855
let contract = Contract::load(abi_json.as_bytes()).unwrap();
@@ -1860,59 +1860,44 @@ mod tests {
18601860
};
18611861

18621862
// Test 1: Missing opening bracket
1863-
let result = CallExpr::parse(
1864-
"TestContract event.address].test()",
1865-
&mapping_abi,
1866-
None,
1867-
None,
1868-
);
1863+
let result = CallExpr::parse("TestContract event.address].test()", &mapping_abi, None, SV);
18691864
assert!(result.is_err());
18701865
let error_msg = result.unwrap_err().to_string();
18711866
assert!(error_msg.contains("Invalid call expression"));
18721867
assert!(error_msg.contains("missing '[' after contract name"));
18731868

18741869
// Test 2: Missing closing bracket
1875-
let result = CallExpr::parse(
1876-
"TestContract[event.address.test()",
1877-
&mapping_abi,
1878-
None,
1879-
None,
1880-
);
1870+
let result = CallExpr::parse("TestContract[event.address.test()", &mapping_abi, None, SV);
18811871
assert!(result.is_err());
18821872
let error_msg = result.unwrap_err().to_string();
18831873
assert!(error_msg.contains("missing ']' to close address"));
18841874

18851875
// Test 3: Empty contract name
1886-
let result = CallExpr::parse("[event.address].test()", &mapping_abi, None, None);
1876+
let result = CallExpr::parse("[event.address].test()", &mapping_abi, None, SV);
18871877
assert!(result.is_err());
18881878
let error_msg = result.unwrap_err().to_string();
18891879
assert!(error_msg.contains("missing contract name before '['"));
18901880

18911881
// Test 4: Empty address
1892-
let result = CallExpr::parse("TestContract[].test()", &mapping_abi, None, None);
1882+
let result = CallExpr::parse("TestContract[].test()", &mapping_abi, None, SV);
18931883
assert!(result.is_err());
18941884
let error_msg = result.unwrap_err().to_string();
18951885
assert!(error_msg.contains("empty address"));
18961886

18971887
// Test 5: Missing function name
1898-
let result = CallExpr::parse("TestContract[event.address].()", &mapping_abi, None, None);
1888+
let result = CallExpr::parse("TestContract[event.address].()", &mapping_abi, None, SV);
18991889
assert!(result.is_err());
19001890
let error_msg = result.unwrap_err().to_string();
19011891
assert!(error_msg.contains("missing function name"));
19021892

19031893
// Test 6: Missing opening parenthesis
1904-
let result = CallExpr::parse("TestContract[event.address].test", &mapping_abi, None, None);
1894+
let result = CallExpr::parse("TestContract[event.address].test", &mapping_abi, None, SV);
19051895
assert!(result.is_err());
19061896
let error_msg = result.unwrap_err().to_string();
19071897
assert!(error_msg.contains("missing '(' to start function arguments"));
19081898

19091899
// Test 7: Missing closing parenthesis
1910-
let result = CallExpr::parse(
1911-
"TestContract[event.address].test(",
1912-
&mapping_abi,
1913-
None,
1914-
None,
1915-
);
1900+
let result = CallExpr::parse("TestContract[event.address].test(", &mapping_abi, None, SV);
19161901
assert!(result.is_err());
19171902
let error_msg = result.unwrap_err().to_string();
19181903
assert!(error_msg.contains("missing ')' to close function arguments"));
@@ -1922,7 +1907,7 @@ mod tests {
19221907
"TestContract[event.address].test(invalid.arg)",
19231908
&mapping_abi,
19241909
None,
1925-
None,
1910+
SV,
19261911
);
19271912
assert!(result.is_err());
19281913
let error_msg = result.unwrap_err().to_string();

graph/src/data_source/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,14 +332,15 @@ impl<C: Blockchain> UnresolvedDataSource<C> {
332332
resolver: &Arc<dyn LinkResolver>,
333333
logger: &Logger,
334334
manifest_idx: u32,
335+
spec_version: &semver::Version,
335336
) -> Result<DataSource<C>, anyhow::Error> {
336337
match self {
337338
Self::Onchain(unresolved) => unresolved
338-
.resolve(resolver, logger, manifest_idx)
339+
.resolve(resolver, logger, manifest_idx, spec_version)
339340
.await
340341
.map(DataSource::Onchain),
341342
Self::Subgraph(unresolved) => unresolved
342-
.resolve::<C>(resolver, logger, manifest_idx)
343+
.resolve::<C>(resolver, logger, manifest_idx, spec_version)
343344
.await
344345
.map(DataSource::Subgraph),
345346
Self::Offchain(_unresolved) => {
@@ -462,18 +463,19 @@ impl<C: Blockchain> UnresolvedDataSourceTemplate<C> {
462463
schema: &InputSchema,
463464
logger: &Logger,
464465
manifest_idx: u32,
466+
spec_version: &semver::Version,
465467
) -> Result<DataSourceTemplate<C>, Error> {
466468
match self {
467469
Self::Onchain(ds) => ds
468-
.resolve(resolver, logger, manifest_idx)
470+
.resolve(resolver, logger, manifest_idx, spec_version)
469471
.await
470472
.map(|ti| DataSourceTemplate::Onchain(ti)),
471473
Self::Offchain(ds) => ds
472474
.resolve(resolver, logger, manifest_idx, schema)
473475
.await
474476
.map(DataSourceTemplate::Offchain),
475477
Self::Subgraph(ds) => ds
476-
.resolve(resolver, logger, manifest_idx)
478+
.resolve(resolver, logger, manifest_idx, spec_version)
477479
.await
478480
.map(DataSourceTemplate::Subgraph),
479481
}

0 commit comments

Comments
 (0)