use std::str::FromStr; use ethabi::ethereum_types::Address; use serde::Deserialize; use substreams::prelude::BigInt; use substreams_ethereum::pb::eth::v2::{self as eth}; use substreams_helper::{event_handler::EventHandler, hex::Hexable}; use crate::abi::factory::events::PairCreated; use tycho_substreams::prelude::*; #[derive(Debug, Deserialize)] struct Params { factory_address: String, protocol_type_name: String, } #[substreams::handlers::map] pub fn map_pools_created( params: String, block: eth::Block, ) -> Result { let mut new_pools: Vec = vec![]; let params: Params = serde_qs::from_str(params.as_str()).expect("Unable to deserialize params"); get_pools(&block, &mut new_pools, ¶ms); let tycho_block: Block = (&block).into(); Ok(BlockChanges { block: Some(tycho_block), changes: new_pools }) } fn get_pools(block: ð::Block, new_pools: &mut Vec, params: &Params) { // Extract new pools from PairCreated events let mut on_pair_created = |event: PairCreated, _tx: ð::TransactionTrace, _log: ð::Log| { let tycho_tx: Transaction = _tx.into(); new_pools.push(TransactionChanges { tx: Some(tycho_tx.clone()), contract_changes: vec![], entity_changes: vec![EntityChanges { component_id: event.pair.to_hex(), attributes: vec![ Attribute { name: "reserve0".to_string(), value: BigInt::from(0).to_signed_bytes_be(), change: ChangeType::Creation.into(), }, Attribute { name: "reserve1".to_string(), value: BigInt::from(0).to_signed_bytes_be(), change: ChangeType::Creation.into(), }, ], }], component_changes: vec![ProtocolComponent { id: event.pair.to_hex(), tokens: vec![event.token0.clone(), event.token1.clone()], contracts: vec![], static_att: vec![ // Trading Fee is hardcoded to 0.3%, saved as int in bps (basis points) Attribute { name: "fee".to_string(), value: BigInt::from(30).to_signed_bytes_be(), change: ChangeType::Creation.into(), }, Attribute { name: "pool_address".to_string(), value: event.pair.clone(), change: ChangeType::Creation.into(), }, ], change: i32::from(ChangeType::Creation), protocol_type: Some(ProtocolType { name: params.protocol_type_name.to_string(), financial_type: FinancialType::Swap.into(), attribute_schema: vec![], implementation_type: ImplementationType::Custom.into(), }), tx: Some(tycho_tx), }], balance_changes: vec![ BalanceChange { token: event.token0, balance: BigInt::from(0).to_signed_bytes_be(), component_id: event.pair.to_hex().as_bytes().to_vec(), }, BalanceChange { token: event.token1, balance: BigInt::from(0).to_signed_bytes_be(), component_id: event.pair.to_hex().as_bytes().to_vec(), }, ], }) }; let mut eh = EventHandler::new(block); eh.filter_by_address(vec![Address::from_str(¶ms.factory_address).unwrap()]); eh.on::(&mut on_pair_created); eh.handle_events(); }