Skip to content

Commit 7114453

Browse files
Merge branch 'main' into version-0.6.0
2 parents bff5035 + 88d5b57 commit 7114453

File tree

4 files changed

+108
-71
lines changed

4 files changed

+108
-71
lines changed

Diff for: src/context/mod.rs

+42-49
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ pub struct MatchstickInstanceContext<C: Blockchain> {
106106
pub meta_tests: Vec<(String, bool, u32, String)>,
107107
/// Holding the parent entity type, parent virtual field and a tuple of the derived entity type and derived entity field it points to
108108
/// The example below is taken from a schema.graphql file and will fill the map in the following way:
109-
/// {"GraphAccount": {"nameSignalTransactions", ("NameSignalTransaction", "signer")}}
109+
/// {"GraphAccount": {"nameSignalTransactions", [("NameSignalTransaction", "signer")]}}
110110
/// ```
111111
/// type GraphAccount @entity {
112112
/// id: ID!
@@ -117,11 +117,10 @@ pub struct MatchstickInstanceContext<C: Blockchain> {
117117
/// signer: GraphAccount!
118118
/// }
119119
/// ```
120-
pub(crate) derived: HashMap<String, HashMap<String, (String, String)>>,
120+
pub(crate) derived: HashMap<String, HashMap<String, Vec<(String, String)>>>,
121121
/// Holds the graphql schema for easier access
122122
schema: HashMap<String, graphql_parser::schema::ObjectType<'static, String>>,
123-
/// Gives guarantee that all derived relations are in order when true
124-
store_updated: bool,
123+
interface_to_entities: HashMap<String, Vec<String>>,
125124
/// Holds the mocked return values of `dataSource.address()`, `dataSource.network()` and `dataSource.context()` in that order
126125
data_source_return_value: (
127126
Option<String>,
@@ -146,7 +145,7 @@ impl<C: Blockchain> MatchstickInstanceContext<C> {
146145
meta_tests: Vec::new(),
147146
derived: HashMap::new(),
148147
schema: HashMap::new(),
149-
store_updated: true,
148+
interface_to_entities: HashMap::new(),
150149
data_source_return_value: (None, None, None),
151150
ipfs: HashMap::new(),
152151
templates: HashMap::new(),
@@ -310,7 +309,6 @@ impl<C: Blockchain> MatchstickInstanceContext<C> {
310309
/// function clearStore(): void
311310
pub fn clear_store(&mut self, _gas: &GasCounter) -> Result<(), HostExportError> {
312311
self.store.clear();
313-
self.store_updated = true;
314312
Ok(())
315313
}
316314

@@ -738,45 +736,47 @@ impl<C: Blockchain> MatchstickInstanceContext<C> {
738736
) -> Vec<StoreEntity> {
739737
let mut related_entities: Vec<StoreEntity> = Vec::new();
740738

741-
// gets the derived entity type and derived entity field associated with the parent entity
742-
let derived_from_entity = self
739+
// Gets the derived entity type and derived entity field associated with the parent entity
740+
let derived_from = self
743741
.derived
744742
.get(entity_type)
745743
.and_then(|fields| fields.get(entity_virtual_field));
746744

747-
if let Some((derived_from_entity_type, derived_from_entity_field)) = derived_from_entity {
748-
let derived_entities = self.store.get(derived_from_entity_type);
749-
750-
if let Some(derived_entities) = derived_entities {
751-
// loop through all derived entities from the store to find a relation with the parent entity
752-
// if relation is found, it adds the whole entity to the related entities result
753-
for (derived_entity_id, derived_entity) in derived_entities.iter() {
754-
if !derived_entity.contains_key(derived_from_entity_field) {
755-
continue;
756-
}
757-
758-
// derived field value could be a single ID or list of IDs
759-
let derived_field_value = derived_entity
760-
.get(derived_from_entity_field)
761-
.unwrap()
762-
.clone();
763-
764-
// converts different value types(string, bytes, list) to a single vector
765-
// that way it would be easier to find relation by entity id
766-
let derived_entity_ids: Vec<Value> = match derived_field_value {
767-
Value::Bytes(id) => vec![Value::from(id)],
768-
Value::String(id) => vec![Value::from(id)],
769-
Value::List(ids) => ids,
770-
_ => vec![],
771-
};
772-
773-
let relation_found: bool = derived_entity_ids
774-
.iter()
775-
.any(|derived_id| derived_id.to_string().eq(entity_id));
776-
777-
if relation_found {
778-
related_entities
779-
.push(derived_entities.get(derived_entity_id).unwrap().clone());
745+
if let Some(entities) = derived_from {
746+
for (derived_from_entity_type, derived_from_entity_field) in entities.iter() {
747+
let derived_entities = self.store.get(derived_from_entity_type);
748+
749+
if let Some(derived_entities) = derived_entities {
750+
// loop through all derived entities from the store to find a relation with the parent entity
751+
// if relation is found, it adds the whole entity to the related entities result
752+
for (derived_entity_id, derived_entity) in derived_entities.iter() {
753+
if !derived_entity.contains_key(derived_from_entity_field) {
754+
continue;
755+
}
756+
757+
// derived field value could be a single ID or list of IDs
758+
let derived_field_value = derived_entity
759+
.get(derived_from_entity_field)
760+
.unwrap()
761+
.clone();
762+
763+
// converts different value types(string, bytes, list) to a single vector
764+
// that way it would be easier to find relation by entity id
765+
let derived_entity_ids: Vec<Value> = match derived_field_value {
766+
Value::Bytes(id) => vec![Value::from(id)],
767+
Value::String(id) => vec![Value::from(id)],
768+
Value::List(ids) => ids,
769+
_ => vec![],
770+
};
771+
772+
let relation_found: bool = derived_entity_ids
773+
.iter()
774+
.any(|derived_id| derived_id.to_string().eq(entity_id));
775+
776+
if relation_found {
777+
related_entities
778+
.push(derived_entities.get(derived_entity_id).unwrap().clone());
779+
}
780780
}
781781
}
782782
}
@@ -888,13 +888,7 @@ impl<C: Blockchain> MatchstickInstanceContext<C> {
888888
id_ptr: AscPtr<AscString>,
889889
data_ptr: AscPtr<AscEntity>,
890890
) -> Result<(), HostExportError> {
891-
let result = self.update_store(StoreScope::Global, entity_type_ptr, id_ptr, data_ptr, _gas);
892-
893-
if result.is_ok() {
894-
self.store_updated = false;
895-
}
896-
897-
result
891+
self.update_store(StoreScope::Global, entity_type_ptr, id_ptr, data_ptr, _gas)
898892
}
899893

900894
/// function mockInBlockStore(entityType: string, id: string, data: map): void
@@ -925,7 +919,6 @@ impl<C: Blockchain> MatchstickInstanceContext<C> {
925919
entity_type_store.remove(&id);
926920

927921
self.store.insert(entity_type, entity_type_store);
928-
self.store_updated = false;
929922
} else {
930923
return Err(anyhow!(
931924
"(store.remove) Entity with type '{}' and id '{}' does not exist.",

Diff for: src/context/schema.rs

+55-18
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,35 @@ pub(crate) fn populate_schema_definitions<C: graph::blockchain::Blockchain>(
3535
let schema_document = load_schema_document();
3636

3737
schema_document.definitions.iter().for_each(|def| {
38+
if let schema::Definition::TypeDefinition(schema::TypeDefinition::Interface(entity_def)) =
39+
def
40+
{
41+
// initiate all interfaces defined in the schema
42+
// to be easier to check if a given entity is an interface or not
43+
if !context.interface_to_entities.contains_key(&entity_def.name) {
44+
context
45+
.interface_to_entities
46+
.insert(entity_def.name.clone(), Vec::new());
47+
}
48+
}
49+
3850
if let schema::Definition::TypeDefinition(schema::TypeDefinition::Object(entity_def)) = def
3951
{
52+
// map current entity to its interfaces
53+
if !entity_def.implements_interfaces.is_empty() {
54+
entity_def
55+
.implements_interfaces
56+
.iter()
57+
.for_each(|interface_name| {
58+
let entities = context
59+
.interface_to_entities
60+
.entry(interface_name.to_string())
61+
.or_insert(Vec::new());
62+
63+
entities.push(entity_def.name.clone());
64+
});
65+
}
66+
4067
context
4168
.schema
4269
.insert(entity_def.name.clone(), entity_def.clone());
@@ -54,6 +81,7 @@ pub(crate) fn populate_derived_fields<C: graph::blockchain::Blockchain>(
5481
let derived_fields = entity_object.fields.iter().filter(|&f| f.is_derived());
5582
for virtual_field in derived_fields {
5683
// field type is received as: '[ExampleClass!]!' and needs to be reduced to a class string
84+
// it could be an entity or interface
5785
let derived_from_entity_type = virtual_field
5886
.field_type
5987
.to_string()
@@ -68,26 +96,35 @@ pub(crate) fn populate_derived_fields<C: graph::blockchain::Blockchain>(
6896
.to_string()
6997
.replace('\"', "");
7098

71-
if context.derived.contains_key(entity_type) {
72-
let entity_virtual_fields = context.derived.get_mut(entity_type).unwrap();
99+
let mut derived_from_entities = vec![(
100+
derived_from_entity_type.clone(),
101+
derived_from_entity_field.clone(),
102+
)];
73103

74-
if !entity_virtual_fields.contains_key(&virtual_field.name) {
75-
entity_virtual_fields.insert(
76-
virtual_field.name.clone(),
77-
(derived_from_entity_type, derived_from_entity_field.clone()),
78-
);
79-
}
80-
} else {
81-
let mut entity_virtual_fields: HashMap<String, (String, String)> =
82-
HashMap::new();
83-
entity_virtual_fields.insert(
84-
virtual_field.name.clone(),
85-
(derived_from_entity_type, derived_from_entity_field.clone()),
86-
);
87-
context
88-
.derived
89-
.insert(entity_type.to_string(), entity_virtual_fields);
104+
// checks whether the derived entity is an interface
105+
// and maps all entities that implements it
106+
if context
107+
.interface_to_entities
108+
.contains_key(&derived_from_entity_type)
109+
{
110+
derived_from_entities = context
111+
.interface_to_entities
112+
.get(&derived_from_entity_type)
113+
.unwrap()
114+
.iter()
115+
.map(|entity_name| (entity_name.clone(), derived_from_entity_field.clone()))
116+
.collect();
90117
}
118+
119+
let default_entity_virtual_fields: HashMap<String, Vec<(String, String)>> =
120+
HashMap::new();
121+
let entity_virtual_fields = context
122+
.derived
123+
.entry(entity_type.clone())
124+
.or_insert(default_entity_virtual_fields);
125+
entity_virtual_fields
126+
.entry(virtual_field.name.clone())
127+
.or_insert(derived_from_entities);
91128
}
92129
});
93130
}

Diff for: src/parser.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,17 @@ pub fn collect_templates(path: &str) -> Vec<(String, String)> {
101101
.filter_map(|template| {
102102
let kind = template.get("kind").unwrap().as_str().unwrap().to_owned();
103103

104-
if kind == "ethereum/contract" || kind == "file/ipfs" {
104+
if ["ethereum", "ethereum/contract", "file/ipfs"]
105+
.iter()
106+
.any(|k| k == &kind)
107+
{
105108
let name = template.get("name").unwrap().as_str().unwrap().to_owned();
106109
Some((name, kind))
107110
} else {
111+
logging::warning!(
112+
"Template with kind `{}` is not supported by matchstick.",
113+
kind
114+
);
108115
None
109116
}
110117
})

Diff for: src/unit_tests.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ mod tests {
691691
let mut parent_entity_relation_map = HashMap::new();
692692
parent_entity_relation_map.insert(
693693
"virtual_field".to_owned(),
694-
("ChildEntity".to_owned(), "parent".to_owned()),
694+
vec![("ChildEntity".to_owned(), "parent".to_owned())],
695695
);
696696
context
697697
.derived
@@ -769,7 +769,7 @@ mod tests {
769769
let mut parent_entity_relation_map = HashMap::new();
770770
parent_entity_relation_map.insert(
771771
"virtual_field".to_owned(),
772-
("ChildEntity".to_owned(), "parent".to_owned()),
772+
vec![("ChildEntity".to_owned(), "parent".to_owned())],
773773
);
774774
context
775775
.derived
@@ -833,7 +833,7 @@ mod tests {
833833
let mut parent_entity_relation_map = HashMap::new();
834834
parent_entity_relation_map.insert(
835835
"virtual_field".to_owned(),
836-
("ChildEntity".to_owned(), "parent".to_owned()),
836+
vec![("ChildEntity".to_owned(), "parent".to_owned())],
837837
);
838838
context
839839
.derived

0 commit comments

Comments
 (0)