typhoon_errors/
lib.rs

1mod error_code;
2mod extension;
3
4use pinocchio::program_error::{ProgramError, ToStr};
5pub use {error_code::*, extension::*};
6
7pub struct Error {
8    error: ProgramError,
9    account_name: Option<String>,
10}
11
12impl Error {
13    pub fn new(error: impl Into<ProgramError>) -> Self {
14        Error {
15            error: error.into(),
16            account_name: None,
17        }
18    }
19
20    pub fn with_account(mut self, name: impl ToString) -> Self {
21        self.account_name = Some(name.to_string());
22        self
23    }
24
25    pub fn account_name(&self) -> Option<&String> {
26        self.account_name.as_ref()
27    }
28}
29
30impl ToStr for Error {
31    fn to_str<E>(&self) -> &'static str
32    where
33        E: 'static + ToStr + TryFrom<u32>,
34    {
35        if let ProgramError::Custom(code) = self.error {
36            if (100..200).contains(&code) {
37                return self.error.to_str::<ErrorCode>();
38            }
39        }
40        self.error.to_str::<E>()
41    }
42}
43
44impl From<ProgramError> for Error {
45    fn from(error: ProgramError) -> Self {
46        Error {
47            error,
48            account_name: None,
49        }
50    }
51}
52
53impl From<ErrorCode> for Error {
54    fn from(value: ErrorCode) -> Self {
55        Error {
56            error: value.into(),
57            account_name: None,
58        }
59    }
60}
61
62impl From<Error> for ProgramError {
63    fn from(value: Error) -> Self {
64        value.error
65    }
66}
67
68#[macro_export]
69macro_rules! impl_error_logger {
70    ($error:ident) => {
71        #[cfg(feature = "logging")]
72        #[cold]
73        fn log_error(error: &ErrorV2) {
74            pinocchio::log::sol_log(error.to_str::<$error>());
75
76            if let Some(account_name) = error.account_name() {
77                pinocchio::log::sol_log(&std::format!("Account origin: {account_name}"));
78            }
79        }
80    };
81}