This commit is contained in:
Enol Álvarez
2023-07-27 19:44:06 +02:00
parent 38c52d9a2a
commit 0618138987
4 changed files with 52 additions and 29 deletions

View File

@@ -0,0 +1 @@
max_width = 120

View File

@@ -1,32 +1,33 @@
use crate::pb::eth::event::v1::Event; use crate::pb::eth::event::v1::Event;
use crate::pb::eth::event::v1::Events; use crate::pb::eth::event::v1::Events;
use crate::util; use crate::util;
use anyhow::anyhow;
use anyhow::Ok; use anyhow::Ok;
use substreams::errors::Error; use substreams::errors::Error;
use substreams::Hex; use substreams::Hex;
use substreams_ethereum::pb::eth::v2::Block; use substreams_ethereum::pb::eth::v2::Block;
use anyhow::anyhow;
#[substreams::handlers::map] #[substreams::handlers::map]
fn map_contract_events(contract_address: String, blk: Block) -> Result<Events, Error> { fn map_contract_events(contract_address: String, blk: Block) -> Result<Events, Error> {
verify_parameter(&contract_address)?; verify_parameter(&contract_address)?;
let events: Vec<Event> = blk.logs() let events: Vec<Event> = blk
.filter(| log| log.address().to_vec() == Hex::decode(&contract_address).expect("already validated")) .logs()
.map(|log| Event { .filter(|log| log.address().to_vec() == Hex::decode(&contract_address).expect("already validated"))
address: Hex::encode(log.address()), .map(|log| Event {
topics: log.topics().into_iter().map(| topic| Hex::encode(topic)).collect(), address: Hex::encode(log.address()),
tx_hash: Hex::encode(&log.receipt.transaction.hash) topics: log.topics().into_iter().map(Hex::encode).collect(),
}) tx_hash: Hex::encode(&log.receipt.transaction.hash),
.collect(); })
.collect();
Ok(Events { events }) Ok(Events { events })
} }
fn verify_parameter(address: &String) -> Result<(), Error> { fn verify_parameter(address: &String) -> Result<(), Error> {
if !util::is_address_valid(&address) { if !util::is_address_valid(&address) {
return Err(anyhow!("Contract address is not valid")); return Err(anyhow!("Contract address ({}) is not valid", address));
} }
Ok(()) Ok(())
} }

View File

@@ -1,9 +1,9 @@
use crate::pb::eth::transaction::v1::{Transaction, Transactions}; use crate::pb::eth::transaction::v1::{Transaction, Transactions};
use crate::util; use crate::util;
use anyhow::anyhow;
use serde::Deserialize; use serde::Deserialize;
use substreams::Hex; use substreams::Hex;
use substreams_ethereum::pb::eth::v2::{Block, TransactionTraceStatus, TransactionTrace}; use substreams_ethereum::pb::eth::v2::{Block, TransactionTrace, TransactionTraceStatus};
use anyhow::anyhow;
#[derive(Deserialize)] #[derive(Deserialize)]
struct TransactionFilterParams { struct TransactionFilterParams {
@@ -13,36 +13,54 @@ struct TransactionFilterParams {
#[substreams::handlers::map] #[substreams::handlers::map]
fn map_filter_transactions(params: String, blk: Block) -> Result<Transactions, Vec<substreams::errors::Error>> { fn map_filter_transactions(params: String, blk: Block) -> Result<Transactions, Vec<substreams::errors::Error>> {
let filters: TransactionFilterParams = serde_qs::from_str(&params).unwrap(); let filters = parse_filters_from_params(params)?;
verify_filter_params(&filters)?;
let transactions: Vec<Transaction> = blk.transactions() let transactions: Vec<Transaction> = blk
.transactions()
.filter(|trans| apply_filter(&trans, &filters)) .filter(|trans| apply_filter(&trans, &filters))
.map(|trans| Transaction { .map(|trans| Transaction {
from: Hex::encode(&trans.from), from: Hex::encode(&trans.from),
to: Hex::encode(&trans.to), to: Hex::encode(&trans.to),
hash: Hex::encode(&trans.hash), hash: Hex::encode(&trans.hash),
}).collect(); })
.collect();
Ok(Transactions { Ok(Transactions { transactions })
transactions,
})
} }
fn verify_filter_params(params: &TransactionFilterParams) -> Result<(), Vec<substreams::errors::Error>> { fn parse_filters_from_params(params: String) -> Result<TransactionFilterParams, Vec<substreams::errors::Error>> {
let parsed_result = serde_qs::from_str(&params);
if parsed_result.is_err() {
return Err(Vec::from([anyhow!("Unpexcted error while parsing parameters")]));
}
let filters = parsed_result.unwrap();
verify_filters(&filters)?;
Ok(filters)
}
fn verify_filters(params: &TransactionFilterParams) -> Result<(), Vec<substreams::errors::Error>> {
let mut errors: Vec<substreams::errors::Error> = Vec::new(); let mut errors: Vec<substreams::errors::Error> = Vec::new();
if params.from.is_some() && !util::is_address_valid(&params.from.as_ref().unwrap()) { if params.from.is_some() && !util::is_address_valid(&params.from.as_ref().unwrap()) {
errors.push(anyhow!("'from' address is not valid")); let from = params.from.as_ref().unwrap();
if !util::is_address_valid(from) {
errors.push(anyhow!("'from' address ({}) is not valid", from));
}
} }
if params.to.is_some() && !util::is_address_valid(&params.to.as_ref().unwrap()) { if params.to.is_some() && !util::is_address_valid(&params.to.as_ref().unwrap()) {
errors.push(anyhow!("'to' address is not valid")); let to = params.to.as_ref().unwrap();
if !util::is_address_valid(to) {
errors.push(anyhow!("'to' address ({}) is not valid", to));
}
} }
if errors.len() > 0 { if errors.len() > 0 {
return Err(errors) return Err(errors);
} }
Ok(()) Ok(())
@@ -51,7 +69,8 @@ fn verify_filter_params(params: &TransactionFilterParams) -> Result<(), Vec<subs
fn apply_filter(transaction: &TransactionTrace, filters: &TransactionFilterParams) -> bool { fn apply_filter(transaction: &TransactionTrace, filters: &TransactionFilterParams) -> bool {
if !filter_by_parameter(&filters.from, &transaction.from) if !filter_by_parameter(&filters.from, &transaction.from)
|| !filter_by_parameter(&filters.to, &transaction.to) || !filter_by_parameter(&filters.to, &transaction.to)
|| transaction.status != (TransactionTraceStatus::Succeeded as i32) { || transaction.status != (TransactionTraceStatus::Succeeded as i32)
{
return false; return false;
} }
@@ -64,7 +83,7 @@ fn filter_by_parameter(parameter: &Option<String>, transaction_field: &Vec<u8>)
} }
let parameter_as_vec = &Hex::decode(parameter.as_ref().unwrap()).expect("already verified"); let parameter_as_vec = &Hex::decode(parameter.as_ref().unwrap()).expect("already verified");
if parameter_as_vec == transaction_field { if transaction_field == parameter_as_vec {
return true; return true;
} }

View File

@@ -39,5 +39,7 @@ modules:
type: proto:eth.event.v1.Events type: proto:eth.event.v1.Events
params: params:
# Filtering transactions with to = 0xdAC17F958D2ee523a2206206994597C13D831ec7 (USDT contract address)
map_filter_transactions: "to=0xdAC17F958D2ee523a2206206994597C13D831ec7" map_filter_transactions: "to=0xdAC17F958D2ee523a2206206994597C13D831ec7"
map_contract_events: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d" # Getting the logs of the BoredApeYachtClub smart contract
map_contract_events: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d"