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#[derive(Debug, Error)]
17pub enum BloberClientError {
18 #[error(transparent)]
20 UploadBlob(#[from] UploadBlobError),
21 #[error(transparent)]
23 Indexer(#[from] IndexerError),
24 #[error(transparent)]
26 Deployment(#[from] DeploymentError),
27 #[error("Failed to query Solana RPC: {0}")]
29 SolanaRpc(#[from] Error),
30 #[error("Invalid commitment: {0}")]
32 InvalidCommitment(#[from] ParseCommitmentLevelError),
33 #[error("Invalid indexer url: {0}")]
35 InvalidIndexerUrl(#[from] jsonrpsee::core::client::Error),
36 #[error("Invalid key or namespace for blober")]
38 InvalidKeyOrNamespace,
39 #[error(transparent)]
41 Io(#[from] std::io::Error),
42 #[error("Ledger data blob error: {0}")]
44 LedgerDataBlob(#[from] LedgerDataBlobError),
45}
46
47#[derive(Debug, Error)]
49pub enum LedgerDataBlobError {
50 #[error("No declare blob instruction found")]
52 DeclareNotFound,
53 #[error("Multiple declare instructions found")]
55 MultipleDeclares,
56 #[error("Declare blob size and inserts blob size mismatch")]
58 SizeMismatch,
59 #[error("No finalize instruction found")]
61 FinalizeNotFound,
62 #[error("Multiple finalize instructions found")]
64 MultipleFinalizes,
65}
66
67pub type BloberClientResult<T = ()> = Result<T, BloberClientError>;
69
70#[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#[derive(Error, Debug)]
82pub enum UploadBlobError {
83 #[error("Failed to query Solana RPC: {0}")]
85 SolanaRpc(#[from] Error),
86 #[error(transparent)]
88 TransactionFailure(#[from] OutcomeError),
89 #[error("Fee Strategy conversion failure: {0}")]
91 ConversionError(&'static str),
92 #[error("Failed to declare blob: {0}")]
94 DeclareBlob(OutcomeError),
95 #[error("Failed to insert chunks: {0}")]
97 InsertChunks(OutcomeError),
98 #[error("Failed to finalize blob: {0}")]
100 FinalizeBlob(OutcomeError),
101 #[error("Failed to discard blob: {0}")]
103 DiscardBlob(OutcomeError),
104 #[error("Failed to compound upload: {0}")]
106 CompoundUpload(OutcomeError),
107 #[error("Failed to initialize blober: {0}")]
109 InitializeBlober(OutcomeError),
110 #[error("Failed to close blober: {0}")]
112 CloseBlober(OutcomeError),
113}
114
115#[derive(Error, Debug)]
116pub enum IndexerError {
117 #[error("Failed to read blobs for slot {0} via indexer client: {1}")]
119 Blobs(Slot, String),
120 #[error("Failed to read proof for slot {0} via indexer client: {1}")]
122 Proof(Slot, String),
123 #[error("Failed to read blobs for blober {0} via indexer client: {1}")]
125 BlobsForBlober(String, String),
126 #[error("Failed to read proof for payer {0} via indexer client: {1}")]
128 BlobsForPayer(String, String),
129 #[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 #[error("Failed to create buffer account: {0}")]
138 Buffer(String),
139 #[error("Failed to deploy program: {0}")]
141 Deploy(String),
142 #[error("Failed to get minimum balance for rent exemption: {0}")]
144 RentBalance(String),
145 #[error("Failed to get recent blockhash")]
147 BlockHash,
148 #[error("Failed to read program bytecode: {0}")]
150 Bytecode(String),
151}
152
153#[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 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 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}