data_anchor_api/
rpc.rs

1use std::collections::HashSet;
2
3use chrono::{DateTime, Utc};
4use jsonrpsee::{
5    core::{RpcResult, SubscriptionResult},
6    proc_macros::rpc,
7};
8use serde::{Deserialize, Serialize};
9use solana_sdk::{clock::Slot, pubkey::Pubkey};
10
11use crate::CompoundProof;
12
13/// A data structure representing a blober's information, including the blober's pubkey, the
14/// payer's pubkey, and the network of the blober.
15#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
16pub struct BloberData {
17    #[serde(with = "pubkey_with_str")]
18    pub blober: Pubkey,
19    pub payer: Pubkey,
20    pub network_id: u64,
21}
22
23/// A time range with optional start and end times, used for filtering time.
24#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
25pub struct TimeRange {
26    /// The start time of the range, inclusive.
27    pub start: Option<DateTime<Utc>>,
28    /// The end time of the range, inclusive.
29    pub end: Option<DateTime<Utc>>,
30}
31
32impl TimeRange {
33    /// Returns the start and end times as a tuple of `DateTime<Utc>`, with defaults for
34    /// missing values.
35    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/// A wrapper around a blober's pubkey, used to identify a blober in RPC calls.
47#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
48pub struct PubkeyFromStr(#[serde(with = "pubkey_with_str")] pub Pubkey);
49
50impl From<PubkeyFromStr> for Pubkey {
51    fn from(value: PubkeyFromStr) -> Self {
52        value.0
53    }
54}
55
56impl From<Pubkey> for PubkeyFromStr {
57    fn from(value: Pubkey) -> Self {
58        PubkeyFromStr(value)
59    }
60}
61
62/// The Indexer RPC interface.
63#[rpc(server, client)]
64pub trait IndexerRpc {
65    /// Retrieve a list of blobs for a given slot and blober pubkey. Returns an error if there was a
66    /// database or RPC failure, and None if the slot has not been completed yet. If the slot is
67    /// completed, an empty list will be returned.
68    #[method(name = "get_blobs")]
69    async fn get_blobs(&self, blober: PubkeyFromStr, slot: u64) -> RpcResult<Option<Vec<Vec<u8>>>>;
70
71    /// Retrieve a list of blobs for a given blober pubkey and time range. Returns an error if there
72    /// was a database or RPC failure, and an empty list if no blobs were found.
73    #[method(name = "get_blobs_by_blober")]
74    async fn get_blobs_by_blober(
75        &self,
76        blober: PubkeyFromStr,
77        time_range: Option<TimeRange>,
78    ) -> RpcResult<Vec<Vec<u8>>>;
79
80    /// Retrieve a list of blobs for a given payer pubkey, network ID, and time range. Returns an
81    /// error if there was a database or RPC failure, and an empty list if no blobs were found.
82    #[method(name = "get_blobs_by_payer")]
83    async fn get_blobs_by_payer(
84        &self,
85        payer: PubkeyFromStr,
86        network_name: String,
87        time_range: Option<TimeRange>,
88    ) -> RpcResult<Vec<Vec<u8>>>;
89
90    /// Retrieve a list of blobs for a given network name and time range. Returns an error if there
91    /// was a database or RPC failure, and an empty list if no blobs were found.
92    #[method(name = "get_blobs_by_network")]
93    async fn get_blobs_by_network(
94        &self,
95        network_name: String,
96        time_range: TimeRange,
97    ) -> RpcResult<Vec<Vec<u8>>>;
98
99    /// Retrieve a list of blobs for a given namespace and time range. Returns an error if there
100    /// was a database or RPC failure, and an empty list if no blobs were found.
101    #[method(name = "get_blobs_by_namespace")]
102    async fn get_blobs_by_namespace_for_payer(
103        &self,
104        namespace: String,
105        payer: Option<PubkeyFromStr>,
106        time_range: TimeRange,
107    ) -> RpcResult<Vec<Vec<u8>>>;
108
109    /// Retrieve a list of payers for a given network name. Returns an error if there was a
110    /// database or RPC failure, and an empty list if no payers were found.
111    #[method(name = "get_payers_by_network")]
112    async fn get_payers_by_network(&self, network_name: String) -> RpcResult<Vec<PubkeyFromStr>>;
113
114    /// Retrieve a proof for a given slot and blober pubkey. Returns an error if there was a
115    /// database or RPC failure, and None if the slot has not been completed yet.
116    #[method(name = "get_proof")]
117    async fn get_proof(&self, blober: PubkeyFromStr, slot: u64)
118    -> RpcResult<Option<CompoundProof>>;
119
120    /// Retrieve a compound proof that covers a particular blob. Returns an error if there was a
121    /// database or RPC failure, and None if the blob does not exist.
122    #[method(name = "get_proof_for_blob")]
123    async fn get_proof_for_blob(
124        &self,
125        blob_address: PubkeyFromStr,
126    ) -> RpcResult<Option<CompoundProof>>;
127
128    /// Listen to blob finalization events from specified blobers. This will return a stream of
129    /// slots and blober PDAs that have finalized blobs. The stream will be closed when the RPC server is
130    /// shut down.
131    #[subscription(
132        name = "subscribe_blob_finalization" => "listen_subscribe_blob_finalization",
133        unsubscribe = "unsubscribe_blob_finalization", 
134        item = (Pubkey, Slot)
135    )]
136    async fn subscribe_blob_finalization(
137        &self,
138        blobers: HashSet<PubkeyFromStr>,
139    ) -> SubscriptionResult;
140}
141
142pub mod pubkey_with_str {
143    use std::str::FromStr;
144
145    use serde::{Deserialize, Deserializer, de};
146    use solana_sdk::pubkey::Pubkey;
147
148    pub fn deserialize<'de, D>(deserializer: D) -> Result<Pubkey, D::Error>
149    where
150        D: Deserializer<'de>,
151    {
152        String::deserialize(deserializer)
153            .and_then(|key| Pubkey::from_str(&key).map_err(de::Error::custom))
154    }
155
156    pub fn serialize<S>(pubkey: &Pubkey, serializer: S) -> Result<S::Ok, S::Error>
157    where
158        S: serde::Serializer,
159    {
160        serializer.serialize_str(&pubkey.to_string())
161    }
162}