108 lines
3.1 KiB
Rust
Raw Normal View History

2026-01-12 15:51:24 +02:00
use anyhow::Result;
use bedrock_client::{BasicAuthCredentials, BedrockClient};
2026-01-13 15:11:51 +02:00
use common::block::{BlockHash, HashableBlockData};
2026-01-12 15:51:24 +02:00
use futures::StreamExt;
2026-01-14 16:16:45 +02:00
use log::info;
2026-01-12 15:51:24 +02:00
use nomos_core::mantle::{
Op, SignedMantleTx,
ops::channel::{ChannelId, inscribe::InscriptionOp},
};
use tokio::sync::mpsc::Sender;
2026-01-09 15:10:38 +02:00
use url::Url;
2026-01-13 15:11:51 +02:00
use crate::{config::IndexerConfig, state::IndexerState};
2026-01-12 15:51:24 +02:00
pub mod config;
2026-01-13 15:11:51 +02:00
pub mod state;
2026-01-12 15:51:24 +02:00
2026-01-09 15:10:38 +02:00
pub struct IndexerCore {
2026-01-12 15:51:24 +02:00
pub bedrock_client: BedrockClient,
2026-01-09 15:10:38 +02:00
pub bedrock_url: Url,
2026-01-13 15:11:51 +02:00
pub channel_sender: Sender<BlockHash>,
2026-01-12 15:51:24 +02:00
pub config: IndexerConfig,
2026-01-13 15:11:51 +02:00
pub state: IndexerState,
2026-01-09 15:10:38 +02:00
}
impl IndexerCore {
2026-01-12 15:51:24 +02:00
pub fn new(
addr: &str,
auth: Option<BasicAuthCredentials>,
2026-01-13 15:11:51 +02:00
sender: Sender<BlockHash>,
2026-01-12 15:51:24 +02:00
config: IndexerConfig,
) -> Result<Self> {
Ok(Self {
bedrock_client: BedrockClient::new(auth)?,
bedrock_url: Url::parse(addr)?,
channel_sender: sender,
config,
2026-01-13 15:11:51 +02:00
// No state setup for now, future task.
state: IndexerState {
latest_seen_block: 0,
},
2026-01-12 15:51:24 +02:00
})
2026-01-09 15:10:38 +02:00
}
2026-01-12 15:51:24 +02:00
pub async fn subscribe_parse_block_stream(&self) -> Result<()> {
let mut stream_pinned = Box::pin(
self.bedrock_client
.0
.get_lib_stream(self.bedrock_url.clone())
.await?,
);
2026-01-14 16:16:45 +02:00
info!("Block stream joined");
2026-01-12 15:51:24 +02:00
while let Some(block_info) = stream_pinned.next().await {
let header_id = block_info.header_id;
2026-01-14 16:16:45 +02:00
info!("Observed L1 block at height {}", block_info.height);
2026-01-12 15:51:24 +02:00
if let Some(l1_block) = self
.bedrock_client
.0
.get_block_by_id(self.bedrock_url.clone(), header_id)
.await?
{
2026-01-14 16:16:45 +02:00
info!("Extracted L1 block at height {} with data {l1_block:#?}", block_info.height);
2026-01-12 15:51:24 +02:00
let l2_blocks_parsed = parse_blocks(
l1_block.into_transactions().into_iter(),
&self.config.channel_id,
);
for l2_block in l2_blocks_parsed {
2026-01-13 15:11:51 +02:00
// Sending data into sequencer, may need to be expanded.
self.channel_sender.send(l2_block.block_hash()).await?;
2026-01-12 15:51:24 +02:00
}
}
}
Ok(())
}
}
pub fn parse_blocks(
block_txs: impl Iterator<Item = SignedMantleTx>,
decoded_channel_id: &ChannelId,
) -> Vec<HashableBlockData> {
block_txs
.flat_map(|tx| {
tx.mantle_tx
.ops
.iter()
.filter_map(|op| match op {
Op::ChannelInscribe(InscriptionOp {
channel_id,
inscription,
..
}) if channel_id == decoded_channel_id => {
// Assuming, that it is how block will be inscribed on l1
borsh::from_slice::<HashableBlockData>(inscription).ok()
}
_ => None,
})
.collect::<Vec<_>>()
})
.collect()
}