1use cometindex::{
2 async_trait,
3 index::{EventBatch, EventBatchContext},
4 sqlx, AppView, PgTransaction,
5};
6use penumbra_sdk_proto::{core::component::sct::v1 as pb, event::ProtoEvent};
7use sqlx::types::chrono::DateTime;
8
9#[derive(Debug)]
10pub struct Block {}
11
12#[async_trait]
13impl AppView for Block {
14 fn name(&self) -> String {
15 "block".to_string()
16 }
17
18 async fn init_chain(
19 &self,
20 dbtx: &mut PgTransaction,
21 _: &serde_json::Value,
22 ) -> Result<(), anyhow::Error> {
23 sqlx::query(
24 "
26CREATE TABLE IF NOT EXISTS block_details (
27 height BIGINT PRIMARY KEY,
28 root BYTEA NOT NULL,
29 timestamp TIMESTAMPTZ NOT NULL
30);
31",
32 )
33 .execute(dbtx.as_mut())
34 .await?;
35 Ok(())
36 }
37
38 async fn index_batch(
39 &self,
40 dbtx: &mut PgTransaction,
41 batch: EventBatch,
42 _ctx: EventBatchContext,
43 ) -> Result<(), anyhow::Error> {
44 for event in batch.events() {
45 let pe = match pb::EventBlockRoot::from_event(event.as_ref()) {
46 Ok(pe) => pe,
47 Err(_) => continue,
48 };
49 let timestamp = pe.timestamp.unwrap_or_default();
50
51 sqlx::query(
52 "
53 INSERT INTO block_details (height, timestamp, root)
54 VALUES ($1, $2, $3)
55 ",
56 )
57 .bind(i64::try_from(pe.height)?)
58 .bind(DateTime::from_timestamp(
59 timestamp.seconds,
60 u32::try_from(timestamp.nanos)?,
61 ))
62 .bind(pe.root.unwrap().inner)
63 .execute(dbtx.as_mut())
64 .await?;
65 }
66 Ok(())
67 }
68}