nitro_da_client/
types.rs

1use std::fmt::Display;
2
3use nitro_da_blober::instruction::{
4    Close, DeclareBlob, DiscardBlob, FinalizeBlob, Initialize, InsertChunk,
5};
6use solana_rpc_client_api::client_error::Error;
7use solana_sdk::{clock::Slot, commitment_config::ParseCommitmentLevelError};
8use thiserror::Error;
9
10use crate::{
11    tx::{Compound, CompoundDeclare, CompoundFinalize, MessageBuilder},
12    TransactionOutcome,
13};
14
15/// Errors that can occur when interacting with the Blober client.
16#[derive(Debug, Error)]
17pub enum BloberClientError {
18    /// Upload blob errors
19    #[error(transparent)]
20    UploadBlob(#[from] UploadBlobError),
21    /// Indexer errors
22    #[error(transparent)]
23    Indexer(#[from] IndexerError),
24    /// Deployment errors
25    #[error(transparent)]
26    Deployment(#[from] DeploymentError),
27    /// Failed to query Solana RPC: {0}
28    #[error("Failed to query Solana RPC: {0}")]
29    SolanaRpc(#[from] Error),
30    /// Invalid commitment: {0}
31    #[error("Invalid commitment: {0}")]
32    InvalidCommitment(#[from] ParseCommitmentLevelError),
33    /// Invalid indexer url: {0}
34    #[error("Invalid indexer url: {0}")]
35    InvalidIndexerUrl(#[from] jsonrpsee::core::client::Error),
36    /// Invalid key or namespace for blober
37    #[error("Invalid key or namespace for blober")]
38    InvalidKeyOrNamespace,
39    /// IO error
40    #[error(transparent)]
41    Io(#[from] std::io::Error),
42    /// Ledger data blob error: {0}
43    #[error("Ledger data blob error: {0}")]
44    LedgerDataBlob(#[from] LedgerDataBlobError),
45}
46
47/// Errors that can occur when fetching blob data from the ledger.
48#[derive(Debug, Error)]
49pub enum LedgerDataBlobError {
50    /// No declare instruction found
51    #[error("No declare blob instruction found")]
52    DeclareNotFound,
53    /// Multiple declare instructions found
54    #[error("Multiple declare instructions found")]
55    MultipleDeclares,
56    /// Declare blob size and inserts built blob size mismatch
57    #[error("Declare blob size and inserts blob size mismatch")]
58    SizeMismatch,
59    /// No finalize instruction found
60    #[error("No finalize instruction found")]
61    FinalizeNotFound,
62    /// Multiple finalize instructions found
63    #[error("Multiple finalize instructions found")]
64    MultipleFinalizes,
65}
66
67/// Result returned when interacting with the Blober client.
68pub type BloberClientResult<T = ()> = Result<T, BloberClientError>;
69
70/// Transaction outcomes were not successfull.
71#[derive(Error, Debug)]
72pub enum OutcomeError {
73    #[error(
74        "Transaction outcomes were not successfull: \n{}",
75        .0.iter().filter_map(TransactionOutcome::error).map(|t| format!("- {}: {} [{}]", t.data, t.error, t.logs.join("\n"))).collect::<Vec<_>>().join("\n")
76    )]
77    Unsuccesful(Vec<TransactionOutcome<TransactionType>>),
78}
79
80/// An error that can occur when uploading a blob to a blober account.
81#[derive(Error, Debug)]
82pub enum UploadBlobError {
83    /// Failed to query Solana RPC: {0}
84    #[error("Failed to query Solana RPC: {0}")]
85    SolanaRpc(#[from] Error),
86    /// Failed when sending transactions. Transaction errors:\n{}
87    #[error(transparent)]
88    TransactionFailure(#[from] OutcomeError),
89    /// Fee Strategy conversion failure: {0}
90    #[error("Fee Strategy conversion failure: {0}")]
91    ConversionError(&'static str),
92    /// Failed to declare blob: {0}
93    #[error("Failed to declare blob: {0}")]
94    DeclareBlob(OutcomeError),
95    /// Failed to insert chunks: {0}
96    #[error("Failed to insert chunks: {0}")]
97    InsertChunks(OutcomeError),
98    /// Failed to finalize blob: {0}
99    #[error("Failed to finalize blob: {0}")]
100    FinalizeBlob(OutcomeError),
101    /// Failed to discard blob: {0}
102    #[error("Failed to discard blob: {0}")]
103    DiscardBlob(OutcomeError),
104    /// Failed to compound upload: {0}
105    #[error("Failed to compound upload: {0}")]
106    CompoundUpload(OutcomeError),
107    /// Failed to initialize blober: {0}
108    #[error("Failed to initialize blober: {0}")]
109    InitializeBlober(OutcomeError),
110    /// Failed to close blober: {0}
111    #[error("Failed to close blober: {0}")]
112    CloseBlober(OutcomeError),
113}
114
115#[derive(Error, Debug)]
116pub enum IndexerError {
117    /// Failed to read blobs for slot {0} via indexer client: {1}
118    #[error("Failed to read blobs for slot {0} via indexer client: {1}")]
119    Blobs(Slot, String),
120    /// Failed to read proof for slot {0} via indexer client: {1}
121    #[error("Failed to read proof for slot {0} via indexer client: {1}")]
122    Proof(Slot, String),
123    /// Failed to read blobs for blober {0} via indexer client: {1}
124    #[error("Failed to read blobs for blober {0} via indexer client: {1}")]
125    BlobsForBlober(String, String),
126    /// Failed to read blobs for payer {0} via indexer client: {1}
127    #[error("Failed to read proof for payer {0} via indexer client: {1}")]
128    BlobsForPayer(String, String),
129    /// Failed to read proof for blob {0} via indexer client: {1}
130    #[error("Failed to read proof for blob {0} via indexer client: {1}")]
131    ProofForBlob(String, String),
132}
133
134#[derive(Error, Debug)]
135pub enum DeploymentError {
136    /// Failed to create buffer account: {0}
137    #[error("Failed to create buffer account: {0}")]
138    Buffer(String),
139    /// Failed to deploy program: {0}
140    #[error("Failed to deploy program: {0}")]
141    Deploy(String),
142    /// Failed to get minimum balance for rent exemption: {0}
143    #[error("Failed to get minimum balance for rent exemption: {0}")]
144    RentBalance(String),
145    /// Failed to get recent blockhash
146    #[error("Failed to get recent blockhash")]
147    BlockHash,
148    /// Failed to read program bytecode: {0}
149    #[error("Failed to read program bytecode: {0}")]
150    Bytecode(String),
151}
152
153/// Transaction types which can be performed by the [`blober::blober`] program.
154#[derive(Debug, Clone, Copy)]
155pub enum TransactionType {
156    CloseBlober,
157    Compound,
158    CompoundDeclare,
159    CompoundFinalize,
160    DeclareBlob,
161    DiscardBlob,
162    FinalizeBlob,
163    InitializeBlober,
164    InsertChunk(u16),
165}
166
167impl Display for TransactionType {
168    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
169        match self {
170            TransactionType::CloseBlober => write!(f, "CloseBlober"),
171            TransactionType::Compound => write!(f, "CompoundUpload"),
172            TransactionType::CompoundDeclare => write!(f, "CompoundDeclare"),
173            TransactionType::CompoundFinalize => write!(f, "CompoundFinalize"),
174            TransactionType::DeclareBlob => write!(f, "DeclareBlob"),
175            TransactionType::DiscardBlob => write!(f, "DiscardBlob"),
176            TransactionType::FinalizeBlob => write!(f, "FinalizeBlob"),
177            TransactionType::InitializeBlober => write!(f, "InitializeBlober"),
178            TransactionType::InsertChunk(i) => write!(f, "InsertChunk {i}"),
179        }
180    }
181}
182
183impl TransactionType {
184    /// Returns the number of signatures required for the transaction type.
185    pub(crate) fn num_signatures(&self) -> u16 {
186        match self {
187            TransactionType::CloseBlober => Close::NUM_SIGNATURES,
188            TransactionType::Compound => Compound::NUM_SIGNATURES,
189            TransactionType::CompoundDeclare => CompoundDeclare::NUM_SIGNATURES,
190            TransactionType::CompoundFinalize => CompoundFinalize::NUM_SIGNATURES,
191            TransactionType::DeclareBlob => DeclareBlob::NUM_SIGNATURES,
192            TransactionType::DiscardBlob => DiscardBlob::NUM_SIGNATURES,
193            TransactionType::FinalizeBlob => FinalizeBlob::NUM_SIGNATURES,
194            TransactionType::InitializeBlober => Initialize::NUM_SIGNATURES,
195            TransactionType::InsertChunk(_) => InsertChunk::NUM_SIGNATURES,
196        }
197    }
198
199    /// Returns the compute unit limit for the transaction type.
200    pub(crate) fn compute_unit_limit(&self) -> u32 {
201        match self {
202            TransactionType::CloseBlober => Close::COMPUTE_UNIT_LIMIT,
203            TransactionType::Compound => Compound::COMPUTE_UNIT_LIMIT,
204            TransactionType::CompoundDeclare => CompoundDeclare::COMPUTE_UNIT_LIMIT,
205            TransactionType::CompoundFinalize => CompoundFinalize::COMPUTE_UNIT_LIMIT,
206            TransactionType::DeclareBlob => DeclareBlob::COMPUTE_UNIT_LIMIT,
207            TransactionType::DiscardBlob => DiscardBlob::COMPUTE_UNIT_LIMIT,
208            TransactionType::FinalizeBlob => FinalizeBlob::COMPUTE_UNIT_LIMIT,
209            TransactionType::InitializeBlober => Initialize::COMPUTE_UNIT_LIMIT,
210            TransactionType::InsertChunk(_) => InsertChunk::COMPUTE_UNIT_LIMIT,
211        }
212    }
213}