Skip to main content

metaboss/
errors.rs

1use solana_client::client_error::ClientErrorKind;
2use std::io;
3use thiserror::Error;
4
5#[derive(Error, Debug)]
6pub enum DecodeError {
7    #[error("Client Error: '{0}'")]
8    ClientError(Box<ClientErrorKind>),
9
10    #[error("Network Error: '{0}'")]
11    NetworkError(String),
12
13    #[error("Pubkey Parsing Failed: '{0}'")]
14    PubkeyParseFailed(String),
15
16    #[error("Metadata Decode Failed: '{0}'")]
17    DecodeMetadataFailed(String),
18}
19
20pub type MintAddress = String;
21pub type NetworkError = String;
22
23#[derive(Error, Debug)]
24pub enum MigrateError {
25    #[error("Migration failed with error: {1}")]
26    MigrationFailed(MintAddress, NetworkError),
27}
28
29#[derive(Error, Debug)]
30pub enum UpdateError {
31    #[error("Action failed with error: {1}")]
32    UpdateFailed(MintAddress, NetworkError),
33}
34
35#[derive(Error, Debug)]
36pub enum ActionError {
37    #[error("Action failed with error: {1}")]
38    ActionFailed(MintAddress, NetworkError),
39}
40
41#[derive(Error, Debug)]
42pub enum SolConfigError {
43    #[error("no home env var found")]
44    MissingHomeEnvVar,
45
46    #[error("failed to find or open Solana config file")]
47    IOError(#[from] io::Error),
48
49    #[error("failed to deserialize Solana config file")]
50    YmlError(#[from] serde_yaml::Error),
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    // DecodeError tests
58
59    #[test]
60    fn decode_error_network_error_display() {
61        let err = DecodeError::NetworkError("timeout".to_string());
62        assert_eq!(err.to_string(), "Network Error: 'timeout'");
63    }
64
65    #[test]
66    fn decode_error_pubkey_parse_failed_display() {
67        let err = DecodeError::PubkeyParseFailed("invalid base58".to_string());
68        assert_eq!(err.to_string(), "Pubkey Parsing Failed: 'invalid base58'");
69    }
70
71    #[test]
72    fn decode_error_decode_metadata_failed_display() {
73        let err = DecodeError::DecodeMetadataFailed("borsh error".to_string());
74        assert_eq!(err.to_string(), "Metadata Decode Failed: 'borsh error'");
75    }
76
77    #[test]
78    fn decode_error_client_error_display() {
79        let kind = ClientErrorKind::Custom("rpc failure".to_string());
80        let err = DecodeError::ClientError(Box::new(kind));
81        let msg = err.to_string();
82        assert!(
83            msg.starts_with("Client Error: '"),
84            "unexpected display: {msg}"
85        );
86    }
87
88    // MigrateError tests
89
90    #[test]
91    fn migrate_error_display() {
92        let err = MigrateError::MigrationFailed(
93            "AbcDef123".to_string(),
94            "connection refused".to_string(),
95        );
96        assert_eq!(
97            err.to_string(),
98            "Migration failed with error: connection refused"
99        );
100    }
101
102    // UpdateError tests
103
104    #[test]
105    fn update_error_display() {
106        let err = UpdateError::UpdateFailed("mint123".to_string(), "tx failed".to_string());
107        assert_eq!(err.to_string(), "Action failed with error: tx failed");
108    }
109
110    // ActionError tests
111
112    #[test]
113    fn action_error_display() {
114        let err = ActionError::ActionFailed("mint456".to_string(), "timeout".to_string());
115        assert_eq!(err.to_string(), "Action failed with error: timeout");
116    }
117
118    // SolConfigError tests
119
120    #[test]
121    fn sol_config_error_missing_home_display() {
122        let err = SolConfigError::MissingHomeEnvVar;
123        assert_eq!(err.to_string(), "no home env var found");
124    }
125
126    #[test]
127    fn sol_config_error_io_error_display() {
128        let err = SolConfigError::IOError(io::Error::new(io::ErrorKind::NotFound, "not found"));
129        assert_eq!(err.to_string(), "failed to find or open Solana config file");
130    }
131
132    #[test]
133    fn sol_config_error_from_io_error() {
134        let io_err = io::Error::new(io::ErrorKind::PermissionDenied, "permission denied");
135        let err: SolConfigError = io_err.into();
136        assert!(matches!(err, SolConfigError::IOError(_)));
137    }
138
139    #[test]
140    fn sol_config_error_yml_error_display() {
141        // Construct an invalid YAML to get a serde_yaml::Error
142        let yml_err = serde_yaml::from_str::<serde_yaml::Value>("{{invalid").unwrap_err();
143        let err = SolConfigError::YmlError(yml_err);
144        assert_eq!(err.to_string(), "failed to deserialize Solana config file");
145    }
146
147    #[test]
148    fn sol_config_error_from_yml_error() {
149        let yml_err = serde_yaml::from_str::<serde_yaml::Value>("{{invalid").unwrap_err();
150        let err: SolConfigError = yml_err.into();
151        assert!(matches!(err, SolConfigError::YmlError(_)));
152    }
153}