1use std::{collections::HashSet, str::FromStr};
2
3use chrono::{DateTime, Utc};
4use jsonrpsee::{
5 core::{RpcResult, SubscriptionResult},
6 proc_macros::rpc,
7};
8use serde::{Deserialize, Deserializer, Serialize, de};
9use solana_sdk::{clock::Slot, pubkey::Pubkey};
10
11use crate::CompoundProof;
12
13#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
16pub struct BloberData {
17 #[serde(deserialize_with = "deserialize_pubkey")]
18 pub blober: Pubkey,
19 pub payer: Pubkey,
20 pub network_id: u64,
21}
22
23#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
25pub struct TimeRange {
26 pub start: Option<DateTime<Utc>>,
28 pub end: Option<DateTime<Utc>>,
30}
31
32impl TimeRange {
33 pub fn to_db_defaults(&self) -> (DateTime<Utc>, DateTime<Utc>) {
36 #[allow(clippy::unwrap_used, reason = "Hardcoding 0 will never panic")]
37 let default_start = DateTime::<Utc>::from_timestamp_micros(0).unwrap();
38
39 (
40 self.start.unwrap_or(default_start),
41 self.end.unwrap_or(Utc::now()),
42 )
43 }
44}
45
46#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
48pub struct BlobsByBlober {
49 #[serde(deserialize_with = "deserialize_pubkey")]
51 pub blober: Pubkey,
52 #[serde(flatten)]
54 pub time_range: TimeRange,
55}
56
57#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
59pub struct BlobsByPayer {
60 #[serde(deserialize_with = "deserialize_pubkey")]
62 pub payer: Pubkey,
63 pub network_name: String,
65 #[serde(flatten)]
67 pub time_range: TimeRange,
68}
69
70#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
72pub struct PubkeyFromStr(#[serde(deserialize_with = "deserialize_pubkey")] pub Pubkey);
73
74impl From<PubkeyFromStr> for Pubkey {
75 fn from(value: PubkeyFromStr) -> Self {
76 value.0
77 }
78}
79
80impl From<Pubkey> for PubkeyFromStr {
81 fn from(value: Pubkey) -> Self {
82 PubkeyFromStr(value)
83 }
84}
85
86#[rpc(server, client)]
88pub trait IndexerRpc {
89 #[method(name = "get_blobs")]
93 async fn get_blobs(&self, blober: PubkeyFromStr, slot: u64) -> RpcResult<Option<Vec<Vec<u8>>>>;
94
95 #[method(name = "get_blobs_by_blober")]
98 async fn get_blobs_by_blober(&self, blober: BlobsByBlober) -> RpcResult<Vec<Vec<u8>>>;
99
100 #[method(name = "get_blobs_by_payer")]
103 async fn get_blobs_by_payer(&self, payer: BlobsByPayer) -> RpcResult<Vec<Vec<u8>>>;
104
105 #[method(name = "get_blobs_by_network")]
108 async fn get_blobs_by_network(
109 &self,
110 network_name: String,
111 time_range: TimeRange,
112 ) -> RpcResult<Vec<Vec<u8>>>;
113
114 #[method(name = "get_blobs_by_namespace")]
117 async fn get_blobs_by_namespace_for_payer(
118 &self,
119 namespace: String,
120 payer: Option<PubkeyFromStr>,
121 time_range: TimeRange,
122 ) -> RpcResult<Vec<Vec<u8>>>;
123
124 #[method(name = "get_payers_by_network")]
127 async fn get_payers_by_network(&self, network_name: String) -> RpcResult<Vec<PubkeyFromStr>>;
128
129 #[method(name = "get_proof")]
132 async fn get_proof(&self, blober: PubkeyFromStr, slot: u64)
133 -> RpcResult<Option<CompoundProof>>;
134
135 #[method(name = "get_proof_for_blob")]
138 async fn get_proof_for_blob(
139 &self,
140 blob_address: PubkeyFromStr,
141 ) -> RpcResult<Option<CompoundProof>>;
142
143 #[method(name = "add_blobers")]
145 async fn add_blobers(&self, blobers: HashSet<BloberData>) -> RpcResult<()>;
146
147 #[method(name = "remove_blobers")]
149 async fn remove_blobers(&self, blobers: HashSet<PubkeyFromStr>) -> RpcResult<()>;
150
151 #[subscription(name = "subscribe_blob_finalization" => "listen_subscribe_blob_finalization", unsubscribe = "unsubscribe_blob_finalization", item = (Pubkey, Slot))]
155 async fn subscribe_blob_finalization(
156 &self,
157 blobers: HashSet<PubkeyFromStr>,
158 ) -> SubscriptionResult;
159}
160
161fn deserialize_pubkey<'de, D>(deserializer: D) -> Result<Pubkey, D::Error>
162where
163 D: Deserializer<'de>,
164{
165 String::deserialize(deserializer)
166 .and_then(|key| Pubkey::from_str(&key).map_err(de::Error::custom))
167}