From 65ac765284b0d249cab834545f84672fae521f34 Mon Sep 17 00:00:00 2001 From: Florian Pellissier <111426680+flopell@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:13:08 +0200 Subject: [PATCH] refactor(curve): add utils functions on `ProtocolComponent` --- .../crates/tycho-substreams/src/models.rs | 82 +++++++++++++++++++ substreams/ethereum-curve/src/modules.rs | 30 ++----- 2 files changed, 90 insertions(+), 22 deletions(-) diff --git a/substreams/crates/tycho-substreams/src/models.rs b/substreams/crates/tycho-substreams/src/models.rs index 445baf5..333f172 100644 --- a/substreams/crates/tycho-substreams/src/models.rs +++ b/substreams/crates/tycho-substreams/src/models.rs @@ -300,6 +300,88 @@ impl ProtocolComponent { }); self } + + /// Checks if the instance contains all specified attributes. + /// + /// This function verifies whether the `ProtocolComponent` has all the given static attributes. + /// Each attribute is represented by a tuple containing a name and a value. The function + /// iterates over the provided attributes and checks if they exist in the instance's + /// `static_att`. + /// + /// # Arguments + /// + /// * `attributes` - A slice of tuples where each tuple consists of a `String` representing the + /// attribute name and a `Vec` representing the attribute value. + /// + /// # Returns + /// + /// A boolean indicating whether all specified attributes are present in the instance. + /// + /// # Example + /// + /// ``` + /// let attributes_to_check = vec![ + /// ("attribute1".to_string(), vec![1, 2, 3]), + /// ("attribute2".to_string(), vec![4, 5, 6]), + /// ]; + /// + /// let has_all_attributes = instance.has_attributes(&attributes_to_check); + /// assert!(has_all_attributes); + /// ``` + /// + /// # Notes + /// + /// - The function assumes that the `static_att` collection contains attributes with a + /// `ChangeType` of `Creation` when they are initially added. This is fine because + /// `static_att` can't be updated + pub fn has_attributes(&self, attributes: &[(&str, Vec)]) -> bool { + attributes.iter().all(|(name, value)| { + self.static_att.contains(&Attribute { + name: name.to_string(), + value: value.clone(), + change: ChangeType::Creation.into(), + }) + }) + } + + /// Retrieves the value of a specified attribute by name. + /// + /// This function searches the instance's `static_att` collection for an attribute with the + /// given name. If found, it returns a copy of the attribute's value. If the attribute is + /// not found, it returns `None`. + /// + /// # Arguments + /// + /// * `name` - A string slice that holds the name of the attribute to be searched. + /// + /// # Returns + /// + /// An `Option>` containing the attribute value if found, or `None` if the attribute + /// does not exist. + /// + /// # Example + /// + /// ``` + /// let attribute_name = "attribute1"; + /// if let Some(value) = instance.get_attribute_value(attribute_name) { + /// // Use the attribute value + /// println!("Attribute value: {:?}", value); + /// } else { + /// println!("Attribute not found"); + /// } + /// ``` + /// + /// # Notes + /// + /// - The function performs a search based on the attribute name and returns the first match + /// found. If there are multiple attributes with the same name, only the first one is + /// returned. + pub fn get_attribute_value(&self, name: &str) -> Option> { + self.static_att + .iter() + .find(|attr| attr.name == name) + .map(|attr| attr.value.clone()) + } } /// Same as `EntityChanges` but ensures attributes are unique by name. diff --git a/substreams/ethereum-curve/src/modules.rs b/substreams/ethereum-curve/src/modules.rs index b1d13e6..e2c1531 100644 --- a/substreams/ethereum-curve/src/modules.rs +++ b/substreams/ethereum-curve/src/modules.rs @@ -115,29 +115,15 @@ pub fn store_non_component_accounts(map: BlockTransactionProtocolComponents, sto .iter() .flat_map(|tx_components| &tx_components.components) .for_each(|component| { - // Crypto pool factory creates LP token separated from the pool, we need to index it so we add it to the store if the new protocol component comes from this factory - if component - .static_att - .contains(&Attribute { - name: "pool_type".into(), - value: "crypto_pool".into(), - change: ChangeType::Creation.into(), - }) && - component - .static_att - .contains(&Attribute { - name: "factory_name".into(), - value: "crypto_pool_factory".into(), - change: ChangeType::Creation.into(), - }) - { + // Crypto pool factory creates LP token separated from the pool, we need to index it so + // we add it to the store if the new protocol component comes from this factory + if component.has_attributes(&[ + ("pool_type", "crypto_pool".into()), + ("factory_name", "crypto_pool_factory".into()), + ]) { let lp_token = component - .static_att - .iter() - .find(|attr| attr.name == "lp_token") - .unwrap() - .value - .clone(); + .get_attribute_value("lp_token") + .expect("didn't find lp_token attribute"); store.set(0, hex::encode(lp_token), &1); } });