Skip to content

Commit

Permalink
Merge branch 'main' into version-0.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dimitrovmaksim authored Sep 15, 2023
2 parents bff5035 + 88d5b57 commit 7114453
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 71 deletions.
91 changes: 42 additions & 49 deletions src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub struct MatchstickInstanceContext<C: Blockchain> {
pub meta_tests: Vec<(String, bool, u32, String)>,
/// Holding the parent entity type, parent virtual field and a tuple of the derived entity type and derived entity field it points to
/// The example below is taken from a schema.graphql file and will fill the map in the following way:
/// {"GraphAccount": {"nameSignalTransactions", ("NameSignalTransaction", "signer")}}
/// {"GraphAccount": {"nameSignalTransactions", [("NameSignalTransaction", "signer")]}}
/// ```
/// type GraphAccount @entity {
/// id: ID!
Expand All @@ -117,11 +117,10 @@ pub struct MatchstickInstanceContext<C: Blockchain> {
/// signer: GraphAccount!
/// }
/// ```
pub(crate) derived: HashMap<String, HashMap<String, (String, String)>>,
pub(crate) derived: HashMap<String, HashMap<String, Vec<(String, String)>>>,
/// Holds the graphql schema for easier access
schema: HashMap<String, graphql_parser::schema::ObjectType<'static, String>>,
/// Gives guarantee that all derived relations are in order when true
store_updated: bool,
interface_to_entities: HashMap<String, Vec<String>>,
/// Holds the mocked return values of `dataSource.address()`, `dataSource.network()` and `dataSource.context()` in that order
data_source_return_value: (
Option<String>,
Expand All @@ -146,7 +145,7 @@ impl<C: Blockchain> MatchstickInstanceContext<C> {
meta_tests: Vec::new(),
derived: HashMap::new(),
schema: HashMap::new(),
store_updated: true,
interface_to_entities: HashMap::new(),
data_source_return_value: (None, None, None),
ipfs: HashMap::new(),
templates: HashMap::new(),
Expand Down Expand Up @@ -310,7 +309,6 @@ impl<C: Blockchain> MatchstickInstanceContext<C> {
/// function clearStore(): void
pub fn clear_store(&mut self, _gas: &GasCounter) -> Result<(), HostExportError> {
self.store.clear();
self.store_updated = true;
Ok(())
}

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

// gets the derived entity type and derived entity field associated with the parent entity
let derived_from_entity = self
// Gets the derived entity type and derived entity field associated with the parent entity
let derived_from = self
.derived
.get(entity_type)
.and_then(|fields| fields.get(entity_virtual_field));

if let Some((derived_from_entity_type, derived_from_entity_field)) = derived_from_entity {
let derived_entities = self.store.get(derived_from_entity_type);

if let Some(derived_entities) = derived_entities {
// loop through all derived entities from the store to find a relation with the parent entity
// if relation is found, it adds the whole entity to the related entities result
for (derived_entity_id, derived_entity) in derived_entities.iter() {
if !derived_entity.contains_key(derived_from_entity_field) {
continue;
}

// derived field value could be a single ID or list of IDs
let derived_field_value = derived_entity
.get(derived_from_entity_field)
.unwrap()
.clone();

// converts different value types(string, bytes, list) to a single vector
// that way it would be easier to find relation by entity id
let derived_entity_ids: Vec<Value> = match derived_field_value {
Value::Bytes(id) => vec![Value::from(id)],
Value::String(id) => vec![Value::from(id)],
Value::List(ids) => ids,
_ => vec![],
};

let relation_found: bool = derived_entity_ids
.iter()
.any(|derived_id| derived_id.to_string().eq(entity_id));

if relation_found {
related_entities
.push(derived_entities.get(derived_entity_id).unwrap().clone());
if let Some(entities) = derived_from {
for (derived_from_entity_type, derived_from_entity_field) in entities.iter() {
let derived_entities = self.store.get(derived_from_entity_type);

if let Some(derived_entities) = derived_entities {
// loop through all derived entities from the store to find a relation with the parent entity
// if relation is found, it adds the whole entity to the related entities result
for (derived_entity_id, derived_entity) in derived_entities.iter() {
if !derived_entity.contains_key(derived_from_entity_field) {
continue;
}

// derived field value could be a single ID or list of IDs
let derived_field_value = derived_entity
.get(derived_from_entity_field)
.unwrap()
.clone();

// converts different value types(string, bytes, list) to a single vector
// that way it would be easier to find relation by entity id
let derived_entity_ids: Vec<Value> = match derived_field_value {
Value::Bytes(id) => vec![Value::from(id)],
Value::String(id) => vec![Value::from(id)],
Value::List(ids) => ids,
_ => vec![],
};

let relation_found: bool = derived_entity_ids
.iter()
.any(|derived_id| derived_id.to_string().eq(entity_id));

if relation_found {
related_entities
.push(derived_entities.get(derived_entity_id).unwrap().clone());
}
}
}
}
Expand Down Expand Up @@ -888,13 +888,7 @@ impl<C: Blockchain> MatchstickInstanceContext<C> {
id_ptr: AscPtr<AscString>,
data_ptr: AscPtr<AscEntity>,
) -> Result<(), HostExportError> {
let result = self.update_store(StoreScope::Global, entity_type_ptr, id_ptr, data_ptr, _gas);

if result.is_ok() {
self.store_updated = false;
}

result
self.update_store(StoreScope::Global, entity_type_ptr, id_ptr, data_ptr, _gas)
}

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

self.store.insert(entity_type, entity_type_store);
self.store_updated = false;
} else {
return Err(anyhow!(
"(store.remove) Entity with type '{}' and id '{}' does not exist.",
Expand Down
73 changes: 55 additions & 18 deletions src/context/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,35 @@ pub(crate) fn populate_schema_definitions<C: graph::blockchain::Blockchain>(
let schema_document = load_schema_document();

schema_document.definitions.iter().for_each(|def| {
if let schema::Definition::TypeDefinition(schema::TypeDefinition::Interface(entity_def)) =
def
{
// initiate all interfaces defined in the schema
// to be easier to check if a given entity is an interface or not
if !context.interface_to_entities.contains_key(&entity_def.name) {
context
.interface_to_entities
.insert(entity_def.name.clone(), Vec::new());
}
}

if let schema::Definition::TypeDefinition(schema::TypeDefinition::Object(entity_def)) = def
{
// map current entity to its interfaces
if !entity_def.implements_interfaces.is_empty() {
entity_def
.implements_interfaces
.iter()
.for_each(|interface_name| {
let entities = context
.interface_to_entities
.entry(interface_name.to_string())
.or_insert(Vec::new());

entities.push(entity_def.name.clone());
});
}

context
.schema
.insert(entity_def.name.clone(), entity_def.clone());
Expand All @@ -54,6 +81,7 @@ pub(crate) fn populate_derived_fields<C: graph::blockchain::Blockchain>(
let derived_fields = entity_object.fields.iter().filter(|&f| f.is_derived());
for virtual_field in derived_fields {
// field type is received as: '[ExampleClass!]!' and needs to be reduced to a class string
// it could be an entity or interface
let derived_from_entity_type = virtual_field
.field_type
.to_string()
Expand All @@ -68,26 +96,35 @@ pub(crate) fn populate_derived_fields<C: graph::blockchain::Blockchain>(
.to_string()
.replace('\"', "");

if context.derived.contains_key(entity_type) {
let entity_virtual_fields = context.derived.get_mut(entity_type).unwrap();
let mut derived_from_entities = vec![(
derived_from_entity_type.clone(),
derived_from_entity_field.clone(),
)];

if !entity_virtual_fields.contains_key(&virtual_field.name) {
entity_virtual_fields.insert(
virtual_field.name.clone(),
(derived_from_entity_type, derived_from_entity_field.clone()),
);
}
} else {
let mut entity_virtual_fields: HashMap<String, (String, String)> =
HashMap::new();
entity_virtual_fields.insert(
virtual_field.name.clone(),
(derived_from_entity_type, derived_from_entity_field.clone()),
);
context
.derived
.insert(entity_type.to_string(), entity_virtual_fields);
// checks whether the derived entity is an interface
// and maps all entities that implements it
if context
.interface_to_entities
.contains_key(&derived_from_entity_type)
{
derived_from_entities = context
.interface_to_entities
.get(&derived_from_entity_type)
.unwrap()
.iter()
.map(|entity_name| (entity_name.clone(), derived_from_entity_field.clone()))
.collect();
}

let default_entity_virtual_fields: HashMap<String, Vec<(String, String)>> =
HashMap::new();
let entity_virtual_fields = context
.derived
.entry(entity_type.clone())
.or_insert(default_entity_virtual_fields);
entity_virtual_fields
.entry(virtual_field.name.clone())
.or_insert(derived_from_entities);
}
});
}
Expand Down
9 changes: 8 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,17 @@ pub fn collect_templates(path: &str) -> Vec<(String, String)> {
.filter_map(|template| {
let kind = template.get("kind").unwrap().as_str().unwrap().to_owned();

if kind == "ethereum/contract" || kind == "file/ipfs" {
if ["ethereum", "ethereum/contract", "file/ipfs"]
.iter()
.any(|k| k == &kind)
{
let name = template.get("name").unwrap().as_str().unwrap().to_owned();
Some((name, kind))
} else {
logging::warning!(
"Template with kind `{}` is not supported by matchstick.",
kind
);
None
}
})
Expand Down
6 changes: 3 additions & 3 deletions src/unit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ mod tests {
let mut parent_entity_relation_map = HashMap::new();
parent_entity_relation_map.insert(
"virtual_field".to_owned(),
("ChildEntity".to_owned(), "parent".to_owned()),
vec![("ChildEntity".to_owned(), "parent".to_owned())],
);
context
.derived
Expand Down Expand Up @@ -769,7 +769,7 @@ mod tests {
let mut parent_entity_relation_map = HashMap::new();
parent_entity_relation_map.insert(
"virtual_field".to_owned(),
("ChildEntity".to_owned(), "parent".to_owned()),
vec![("ChildEntity".to_owned(), "parent".to_owned())],
);
context
.derived
Expand Down Expand Up @@ -833,7 +833,7 @@ mod tests {
let mut parent_entity_relation_map = HashMap::new();
parent_entity_relation_map.insert(
"virtual_field".to_owned(),
("ChildEntity".to_owned(), "parent".to_owned()),
vec![("ChildEntity".to_owned(), "parent".to_owned())],
);
context
.derived
Expand Down

0 comments on commit 7114453

Please sign in to comment.