solana-explorer: add map_filter_transactions module
This commit is contained in:
@@ -2,3 +2,4 @@ mod pb;
|
||||
mod map_block_full;
|
||||
mod map_block_meta;
|
||||
mod map_filter_instructions;
|
||||
mod map_filter_transactions;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use substreams_solana::pb::sf::solana::r#type::v1::Block;
|
||||
use crate::pb::sol::block_meta::v1::BlockMeta;
|
||||
use crate::pb::sol::block::v1::BlockMeta;
|
||||
|
||||
#[substreams::handlers::map]
|
||||
fn map_block_meta(blk: Block) -> Result<BlockMeta, substreams::errors::Error> {
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
use anyhow::anyhow;
|
||||
use serde::Deserialize;
|
||||
use substreams_solana::pb::sf::solana::r#type::v1::{Block, CompiledInstruction};
|
||||
use crate::pb::sol::programs::v1::{Instruction, Instructions};
|
||||
use crate::pb::sol::transactions::v1::{Instruction, Instructions};
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct TransactionFilterParams {
|
||||
struct InstructionFilterParams {
|
||||
program_id: Option<String>,
|
||||
}
|
||||
|
||||
|
||||
#[substreams::handlers::map]
|
||||
fn map_filter_instructions(params: String, blk: Block) -> Result<Instructions, Vec<substreams::errors::Error>> {
|
||||
let filters = parse_filters_from_params(params)?;
|
||||
@@ -17,14 +16,11 @@ fn map_filter_instructions(params: String, blk: Block) -> Result<Instructions, V
|
||||
|
||||
blk.transactions.iter().for_each(|tx| {
|
||||
let msg = tx.transaction.clone().unwrap().message.unwrap();
|
||||
tx.transaction.clone().unwrap().
|
||||
let acct_keys = msg.account_keys.as_slice();
|
||||
let insts : Vec<Instruction> = msg.instructions.iter()
|
||||
.filter(|inst| apply_filter(inst, &filters, acct_keys.to_vec()))
|
||||
.map(|inst| {
|
||||
Instruction {
|
||||
slot_number: blk.slot,
|
||||
block_hash: blk.blockhash.clone(),
|
||||
program_id: bs58::encode(acct_keys[inst.program_id_index as usize].to_vec()).into_string(),
|
||||
accounts: inst.accounts.iter().map(|acct| bs58::encode(acct_keys[*acct as usize].to_vec()).into_string()).collect(),
|
||||
data: bs58::encode(inst.data.clone()).into_string(),
|
||||
@@ -36,7 +32,7 @@ fn map_filter_instructions(params: String, blk: Block) -> Result<Instructions, V
|
||||
Ok(Instructions { instructions })
|
||||
}
|
||||
|
||||
fn parse_filters_from_params(params: String) -> Result<TransactionFilterParams, Vec<substreams::errors::Error>> {
|
||||
fn parse_filters_from_params(params: String) -> Result<InstructionFilterParams, Vec<substreams::errors::Error>> {
|
||||
let parsed_result = serde_qs::from_str(¶ms);
|
||||
if parsed_result.is_err() {
|
||||
return Err(Vec::from([anyhow!("Unexpected error while parsing parameters")]));
|
||||
@@ -48,7 +44,7 @@ fn parse_filters_from_params(params: String) -> Result<TransactionFilterParams,
|
||||
Ok(filters)
|
||||
}
|
||||
|
||||
fn apply_filter(instruction: &CompiledInstruction, filters: &TransactionFilterParams, account_keys: Vec<Vec<u8>>) -> bool {
|
||||
fn apply_filter(instruction: &CompiledInstruction, filters: &InstructionFilterParams, account_keys: Vec<Vec<u8>>) -> bool {
|
||||
if filters.program_id.is_none() {
|
||||
return true;
|
||||
}
|
||||
@@ -60,7 +56,6 @@ fn apply_filter(instruction: &CompiledInstruction, filters: &TransactionFilterPa
|
||||
}
|
||||
let program_account_key_val = bs58::encode(program_account_key.unwrap()).into_string();
|
||||
|
||||
//check if account key value is equal to the program id
|
||||
if program_account_key_val != program_id_filter {
|
||||
return false;
|
||||
}
|
||||
|
||||
69
solana-explorer/src/map_filter_transactions.rs
Normal file
69
solana-explorer/src/map_filter_transactions.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
use anyhow::anyhow;
|
||||
use serde::Deserialize;
|
||||
use substreams_solana::pb::sf::solana::r#type::v1::{Block, ConfirmedTransaction};
|
||||
use crate::pb::sol::transactions::v1::{Instruction, Transaction, Transactions};
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct TransactionFilterParams {
|
||||
signature: Option<String>,
|
||||
}
|
||||
|
||||
#[substreams::handlers::map]
|
||||
fn map_filter_transactions(params: String, blk: Block) -> Result<Transactions, Vec<substreams::errors::Error>> {
|
||||
let filters = parse_filters_from_params(params)?;
|
||||
|
||||
let mut transactions : Vec<Transaction> = Vec::new();
|
||||
|
||||
blk.transactions.iter()
|
||||
.filter(|tx| apply_filter(tx, &filters))
|
||||
.for_each(|tx| {
|
||||
let msg = tx.transaction.clone().unwrap().message.unwrap();
|
||||
let acct_keys = msg.account_keys.as_slice();
|
||||
|
||||
let insts : Vec<Instruction> = msg.instructions.iter()
|
||||
.map(|inst| {
|
||||
Instruction {
|
||||
program_id: bs58::encode(acct_keys[inst.program_id_index as usize].to_vec()).into_string(),
|
||||
accounts: inst.accounts.iter().map(|acct| bs58::encode(acct_keys[*acct as usize].to_vec()).into_string()).collect(),
|
||||
data: bs58::encode(inst.data.clone()).into_string(),
|
||||
}
|
||||
}).collect();
|
||||
|
||||
let t = Transaction {
|
||||
signatures: tx.transaction.clone().unwrap().signatures.iter().map(|sig| bs58::encode(sig).into_string()).collect(),
|
||||
instructions: insts
|
||||
};
|
||||
transactions.push(t);
|
||||
});
|
||||
|
||||
Ok(Transactions { transactions })
|
||||
}
|
||||
|
||||
fn parse_filters_from_params(params: String) -> Result<TransactionFilterParams, Vec<substreams::errors::Error>> {
|
||||
let parsed_result = serde_qs::from_str(¶ms);
|
||||
if parsed_result.is_err() {
|
||||
return Err(Vec::from([anyhow!("Unexpected error while parsing parameters")]));
|
||||
}
|
||||
|
||||
let filters = parsed_result.unwrap();
|
||||
//todo: verify_filters(&filters)?;
|
||||
|
||||
Ok(filters)
|
||||
}
|
||||
|
||||
fn apply_filter(transaction: &&ConfirmedTransaction, filters: &TransactionFilterParams) -> bool {
|
||||
if filters.signature.is_none() {
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut found = false;
|
||||
|
||||
transaction.transaction.as_ref().unwrap().signatures.iter().for_each(|sig| {
|
||||
let xsig = bs58::encode(&sig).into_string();
|
||||
if xsig == filters.signature.clone().unwrap() {
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
|
||||
found
|
||||
}
|
||||
@@ -11,18 +11,18 @@ pub mod sf {
|
||||
}
|
||||
}
|
||||
pub mod sol {
|
||||
pub mod block_meta {
|
||||
// @@protoc_insertion_point(attribute:sol.block_meta.v1)
|
||||
pub mod block {
|
||||
// @@protoc_insertion_point(attribute:sol.block.v1)
|
||||
pub mod v1 {
|
||||
include!("sol.block_meta.v1.rs");
|
||||
// @@protoc_insertion_point(sol.block_meta.v1)
|
||||
include!("sol.block.v1.rs");
|
||||
// @@protoc_insertion_point(sol.block.v1)
|
||||
}
|
||||
}
|
||||
pub mod programs {
|
||||
// @@protoc_insertion_point(attribute:sol.programs.v1)
|
||||
pub mod transactions {
|
||||
// @@protoc_insertion_point(attribute:sol.transactions.v1)
|
||||
pub mod v1 {
|
||||
include!("sol.programs.v1.rs");
|
||||
// @@protoc_insertion_point(sol.programs.v1)
|
||||
include!("sol.transactions.v1.rs");
|
||||
// @@protoc_insertion_point(sol.transactions.v1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,19 @@ pub struct Instruction {
|
||||
pub accounts: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
|
||||
#[prost(string, tag="3")]
|
||||
pub data: ::prost::alloc::string::String,
|
||||
#[prost(uint64, tag="4")]
|
||||
pub slot_number: u64,
|
||||
#[prost(string, tag="5")]
|
||||
pub block_hash: ::prost::alloc::string::String,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct Transactions {
|
||||
#[prost(message, repeated, tag="1")]
|
||||
pub transactions: ::prost::alloc::vec::Vec<Transaction>,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct Transaction {
|
||||
#[prost(string, repeated, tag="1")]
|
||||
pub signatures: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
|
||||
#[prost(message, repeated, tag="2")]
|
||||
pub instructions: ::prost::alloc::vec::Vec<Instruction>,
|
||||
}
|
||||
// @@protoc_insertion_point(module)
|
||||
Reference in New Issue
Block a user