1use light_account_checks::error::AccountError;
2use light_sdk_types::lca::CompressedAccountError;
3use light_hasher::HasherError;
4use light_sdk_types::error::LightSdkTypesError;
5use thiserror::Error;
6
7use crate::ProgramError;
8
9pub type Result<T> = std::result::Result<T, LightSdkError>;
10
11#[derive(Debug, Error, PartialEq)]
12pub enum LightSdkError {
13 #[error("Constraint violation")]
14 ConstraintViolation,
15 #[error("Invalid light-system-program ID")]
16 InvalidLightSystemProgram,
17 #[error("Expected accounts in the instruction")]
18 ExpectedAccounts,
19 #[error("Expected address Merkle context to be provided")]
20 ExpectedAddressTreeInfo,
21 #[error("Expected address root index to be provided")]
22 ExpectedAddressRootIndex,
23 #[error("Accounts with a specified input are expected to have data")]
24 ExpectedData,
25 #[error("Accounts with specified data are expected to have a discriminator")]
26 ExpectedDiscriminator,
27 #[error("Accounts with specified data are expected to have a hash")]
28 ExpectedHash,
29 #[error("Expected the `{0}` light account to be provided")]
30 ExpectedLightSystemAccount(String),
31 #[error("`mut` and `close` accounts are expected to have a Merkle context")]
32 ExpectedMerkleContext,
33 #[error("Expected root index to be provided")]
34 ExpectedRootIndex,
35 #[error("Cannot transfer lamports from an account without input")]
36 TransferFromNoInput,
37 #[error("Cannot transfer from an account without lamports")]
38 TransferFromNoLamports,
39 #[error("Account, from which a transfer was attempted, has insufficient amount of lamports")]
40 TransferFromInsufficientLamports,
41 #[error("Integer overflow resulting from too large resulting amount")]
42 TransferIntegerOverflow,
43 #[error("Borsh error.")]
44 Borsh,
45 #[error("Fewer accounts than number of system accounts.")]
46 FewerAccountsThanSystemAccounts,
47 #[error("InvalidCpiSignerAccount")]
48 InvalidCpiSignerAccount,
49 #[error("Missing meta field: {0}")]
50 MissingField(String),
51 #[error("Output state tree index is none. Use an CompressedAccountMeta type with output tree index to initialize or update accounts.")]
52 OutputStateTreeIndexIsNone,
53 #[error("Address is none during initialization")]
54 InitAddressIsNone,
55 #[error("Address is none during initialization with address")]
56 InitWithAddressIsNone,
57 #[error("Output is none during initialization with address")]
58 InitWithAddressOutputIsNone,
59 #[error("Address is none during meta mutation")]
60 MetaMutAddressIsNone,
61 #[error("Input is none during meta mutation")]
62 MetaMutInputIsNone,
63 #[error("Output lamports is none during meta mutation")]
64 MetaMutOutputLamportsIsNone,
65 #[error("Output is none during meta mutation")]
66 MetaMutOutputIsNone,
67 #[error("Address is none during meta close")]
68 MetaCloseAddressIsNone,
69 #[error("Input is none during meta close")]
70 MetaCloseInputIsNone,
71 #[error("CPI accounts index out of bounds: {0}")]
72 CpiAccountsIndexOutOfBounds(usize),
73 #[error("Invalid CPI context account")]
74 InvalidCpiContextAccount,
75 #[error("Invalid SolPool PDA account")]
76 InvalidSolPoolPdaAccount,
77 #[error("CpiAccounts accounts slice starts with an invalid account. It should start with LightSystemProgram SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7.")]
78 InvalidCpiAccountsOffset,
79 #[error("Expected LightAccount to have no data for closure.")]
80 ExpectedNoData,
81 #[error("CPI context must be added before any other accounts (next_index must be 0)")]
82 CpiContextOrderingViolation,
83 #[error("Invalid merkle tree index in CPI accounts")]
84 InvalidMerkleTreeIndex,
85 #[error(
86 "Read-only account cannot use to_account_info(), use to_packed_read_only_account() instead"
87 )]
88 ReadOnlyAccountCannotUseToAccountInfo,
89 #[error("Account is not read-only, cannot use to_packed_read_only_account()")]
90 NotReadOnlyAccount,
91 #[error("Read-only accounts are not supported in write_to_cpi_context operations")]
92 ReadOnlyAccountsNotSupportedInCpiContext,
93 #[error(transparent)]
94 AccountError(#[from] AccountError),
95 #[error(transparent)]
96 Hasher(#[from] HasherError),
97 #[error("Program error: {0}")]
98 ProgramError(#[from] ProgramError),
99 #[error("Compressed account error: {0}")]
100 CompressedAccountError(#[from] CompressedAccountError),
101 #[error("Expected tree info to be provided for init_if_needed")]
102 ExpectedTreeInfo,
103 #[error("ExpectedSelfProgram")]
104 ExpectedSelfProgram,
105 #[error("Expected CPI context to be provided")]
106 ExpectedCpiContext,
107 #[error("Account missing compression_info field")]
108 MissingCompressionInfo,
109 #[error("Cannot access compression_info on packed variant")]
110 PackedVariantCompressionInfo,
111 #[error("CToken variant does not support compression_info operations")]
112 CTokenCompressionInfo,
113 #[error("Unexpected unpacked variant during decompression")]
114 UnexpectedUnpackedVariant,
115 #[error("Token variant's prepare() method was called (tokens use separate handling)")]
116 TokenPrepareCalled,
117 #[error("Cannot access compression_info on zero_copy unpacked variant (stores raw bytes)")]
118 ZeroCopyUnpackedVariant,
119 #[error("Rent sponsor account does not match the expected PDA from config")]
120 InvalidRentSponsor,
121}
122
123impl From<LightSdkError> for ProgramError {
124 fn from(e: LightSdkError) -> Self {
125 ProgramError::Custom(e.into())
126 }
127}
128
129impl From<LightSdkError> for LightSdkTypesError {
133 fn from(e: LightSdkError) -> Self {
134 match e {
135 LightSdkError::ConstraintViolation => LightSdkTypesError::ConstraintViolation,
136 LightSdkError::Borsh => LightSdkTypesError::Borsh,
137 LightSdkError::AccountError(e) => LightSdkTypesError::AccountError(e),
138 LightSdkError::Hasher(e) => LightSdkTypesError::Hasher(e),
139 LightSdkError::MissingCompressionInfo => LightSdkTypesError::MissingCompressionInfo,
140 LightSdkError::InvalidRentSponsor => LightSdkTypesError::InvalidRentSponsor,
141 LightSdkError::CpiAccountsIndexOutOfBounds(i) => {
142 LightSdkTypesError::CpiAccountsIndexOutOfBounds(i)
143 }
144 LightSdkError::ReadOnlyAccountsNotSupportedInCpiContext => {
145 LightSdkTypesError::ReadOnlyAccountsNotSupportedInCpiContext
146 }
147 LightSdkError::CompressedAccountError(e) => {
148 LightSdkTypesError::CompressedAccountError(e)
149 }
150 LightSdkError::ProgramError(e) => LightSdkTypesError::ProgramError(u64::from(e) as u32),
151 _ => LightSdkTypesError::ConstraintViolation,
152 }
153 }
154}
155
156impl From<LightSdkTypesError> for LightSdkError {
158 fn from(e: LightSdkTypesError) -> Self {
159 match e {
160 LightSdkTypesError::InitAddressIsNone => LightSdkError::InitAddressIsNone,
161 LightSdkTypesError::InitWithAddressIsNone => LightSdkError::InitWithAddressIsNone,
162 LightSdkTypesError::InitWithAddressOutputIsNone => {
163 LightSdkError::InitWithAddressOutputIsNone
164 }
165 LightSdkTypesError::MetaMutAddressIsNone => LightSdkError::MetaMutAddressIsNone,
166 LightSdkTypesError::MetaMutInputIsNone => LightSdkError::MetaMutInputIsNone,
167 LightSdkTypesError::MetaMutOutputLamportsIsNone => {
168 LightSdkError::MetaMutOutputLamportsIsNone
169 }
170 LightSdkTypesError::MetaMutOutputIsNone => LightSdkError::MetaMutOutputIsNone,
171 LightSdkTypesError::MetaCloseAddressIsNone => LightSdkError::MetaCloseAddressIsNone,
172 LightSdkTypesError::MetaCloseInputIsNone => LightSdkError::MetaCloseInputIsNone,
173 LightSdkTypesError::FewerAccountsThanSystemAccounts => {
174 LightSdkError::FewerAccountsThanSystemAccounts
175 }
176 LightSdkTypesError::CpiAccountsIndexOutOfBounds(index) => {
177 LightSdkError::CpiAccountsIndexOutOfBounds(index)
178 }
179 LightSdkTypesError::InvalidSolPoolPdaAccount => LightSdkError::InvalidSolPoolPdaAccount,
180 LightSdkTypesError::InvalidCpiContextAccount => LightSdkError::InvalidCpiContextAccount,
181 LightSdkTypesError::InvalidCpiAccountsOffset => LightSdkError::InvalidCpiAccountsOffset,
182 LightSdkTypesError::AccountError(e) => LightSdkError::AccountError(e),
183 LightSdkTypesError::Hasher(e) => LightSdkError::Hasher(e),
184 LightSdkTypesError::ConstraintViolation => LightSdkError::ConstraintViolation,
185 LightSdkTypesError::Borsh => LightSdkError::Borsh,
186 LightSdkTypesError::MissingCompressionInfo => LightSdkError::MissingCompressionInfo,
187 LightSdkTypesError::InvalidRentSponsor => LightSdkError::InvalidRentSponsor,
188 LightSdkTypesError::BorshIo(_) => LightSdkError::Borsh,
189 LightSdkTypesError::ReadOnlyAccountsNotSupportedInCpiContext => {
190 LightSdkError::ReadOnlyAccountsNotSupportedInCpiContext
191 }
192 LightSdkTypesError::CompressedAccountError(e) => {
193 LightSdkError::CompressedAccountError(e)
194 }
195 LightSdkTypesError::AccountDataTooSmall
196 | LightSdkTypesError::InvalidInstructionData
197 | LightSdkTypesError::InvalidSeeds
198 | LightSdkTypesError::CpiFailed
199 | LightSdkTypesError::NotEnoughAccountKeys
200 | LightSdkTypesError::MissingRequiredSignature => LightSdkError::ConstraintViolation,
201 LightSdkTypesError::ProgramError(code) => {
202 LightSdkError::ProgramError(ProgramError::Custom(code))
203 }
204 }
205 }
206}
207
208impl From<LightSdkError> for u32 {
209 fn from(e: LightSdkError) -> Self {
210 match e {
211 LightSdkError::ConstraintViolation => 16001,
212 LightSdkError::InvalidLightSystemProgram => 16002,
213 LightSdkError::ExpectedAccounts => 16003,
214 LightSdkError::ExpectedAddressTreeInfo => 16004,
215 LightSdkError::ExpectedAddressRootIndex => 16005,
216 LightSdkError::ExpectedData => 16006,
217 LightSdkError::ExpectedDiscriminator => 16007,
218 LightSdkError::ExpectedHash => 16008,
219 LightSdkError::ExpectedLightSystemAccount(_) => 16009,
220 LightSdkError::ExpectedMerkleContext => 16010,
221 LightSdkError::ExpectedRootIndex => 16011,
222 LightSdkError::TransferFromNoInput => 16012,
223 LightSdkError::TransferFromNoLamports => 16013,
224 LightSdkError::TransferFromInsufficientLamports => 16014,
225 LightSdkError::TransferIntegerOverflow => 16015,
226 LightSdkError::Borsh => 16016,
227 LightSdkError::FewerAccountsThanSystemAccounts => 16017,
228 LightSdkError::InvalidCpiSignerAccount => 16018,
229 LightSdkError::MissingField(_) => 16019,
230 LightSdkError::OutputStateTreeIndexIsNone => 16020,
231 LightSdkError::InitAddressIsNone => 16021,
232 LightSdkError::InitWithAddressIsNone => 16022,
233 LightSdkError::InitWithAddressOutputIsNone => 16023,
234 LightSdkError::MetaMutAddressIsNone => 16024,
235 LightSdkError::MetaMutInputIsNone => 16025,
236 LightSdkError::MetaMutOutputLamportsIsNone => 16026,
237 LightSdkError::MetaMutOutputIsNone => 16027,
238 LightSdkError::MetaCloseAddressIsNone => 16028,
239 LightSdkError::MetaCloseInputIsNone => 16029,
240 LightSdkError::CpiAccountsIndexOutOfBounds(_) => 16031,
241 LightSdkError::InvalidCpiContextAccount => 16032,
242 LightSdkError::InvalidSolPoolPdaAccount => 16033,
243 LightSdkError::InvalidCpiAccountsOffset => 16034,
244 LightSdkError::ExpectedNoData => 16035,
245 LightSdkError::CpiContextOrderingViolation => 16036,
246 LightSdkError::InvalidMerkleTreeIndex => 16037,
247 LightSdkError::ReadOnlyAccountCannotUseToAccountInfo => 16038,
248 LightSdkError::NotReadOnlyAccount => 16039,
249 LightSdkError::ReadOnlyAccountsNotSupportedInCpiContext => 16040,
250 LightSdkError::AccountError(e) => e.into(),
251 LightSdkError::Hasher(e) => e.into(),
252 LightSdkError::ProgramError(e) => u64::from(e) as u32,
253 LightSdkError::CompressedAccountError(e) => e.into(),
254 LightSdkError::ExpectedTreeInfo => 16041,
255 LightSdkError::ExpectedSelfProgram => 16042,
256 LightSdkError::ExpectedCpiContext => 16043,
257 LightSdkError::MissingCompressionInfo => 16044,
258 LightSdkError::PackedVariantCompressionInfo => 16045,
259 LightSdkError::CTokenCompressionInfo => 16046,
260 LightSdkError::UnexpectedUnpackedVariant => 16047,
261 LightSdkError::TokenPrepareCalled => 16048,
262 LightSdkError::ZeroCopyUnpackedVariant => 16049,
263 LightSdkError::InvalidRentSponsor => 16050,
264 }
265 }
266}