xmtp_common/
error_code.rs1pub trait ErrorCode: std::error::Error {
30 fn error_code(&self) -> &'static str;
34}
35
36impl<E: ErrorCode> ErrorCode for Box<E> {
37 fn error_code(&self) -> &'static str {
38 (**self).error_code()
39 }
40}
41
42impl<E: ErrorCode> ErrorCode for &E {
43 fn error_code(&self) -> &'static str {
44 (*self).error_code()
45 }
46}
47
48#[allow(dead_code)]
51mod cryptography_error_codes {
52 #[derive(xmtp_common::ErrorCode)]
53 #[error_code(remote = "xmtp_cryptography::GeneratePostQuantumKeyError")]
54 enum GeneratePostQuantumKeyError {
55 Crypto(()),
56 Rand(()),
57 }
58
59 #[derive(xmtp_common::ErrorCode)]
60 #[error_code(remote = "xmtp_cryptography::signature::SignatureError")]
61 enum SignatureError {
62 BadAddressFormat(()),
63 BadSignatureFormat(()),
64 BadSignature { addr: String },
65 Signer(()),
66 Unknown,
67 }
68
69 #[derive(xmtp_common::ErrorCode)]
70 #[error_code(remote = "xmtp_cryptography::signature::IdentifierValidationError")]
71 enum IdentifierValidationError {
72 InvalidAddresses(Vec<String>),
73 HexDecode(()),
74 Generic(String),
75 }
76
77 #[derive(xmtp_common::ErrorCode)]
78 #[error_code(remote = "xmtp_cryptography::ethereum::EthereumCryptoError")]
79 enum EthereumCryptoError {
80 InvalidLength,
81 InvalidKey,
82 SignFailure,
83 DecompressFailure,
84 }
85}
86
87impl ErrorCode for hex::FromHexError {
89 fn error_code(&self) -> &'static str {
90 "hex::FromHexError"
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::ErrorCode;
97 use thiserror::Error;
98 use xmtp_macro::ErrorCode;
99
100 #[derive(Debug, Error, ErrorCode)]
102 #[error("inner error")]
103 struct InnerError;
104
105 #[derive(Debug, Error, ErrorCode)]
106 enum StorageError {
107 #[error("connection failed")]
109 Connection,
110 #[error("not found")]
112 NotFound,
113 }
114
115 #[derive(Debug, Error, ErrorCode)]
116 enum GroupError {
117 #[error("group not found")]
119 NotFound,
120 #[error("invalid membership")]
122 InvalidMembership,
123 #[error("storage: {0}")]
124 #[error_code(inherit)]
125 Storage(#[from] StorageError),
126 #[error("inner: {0}")]
127 #[error_code(inherit)]
128 Inner(#[from] InnerError),
129 }
130
131 #[test]
132 fn test_struct_error_code() {
133 let err = InnerError;
134 assert_eq!(err.error_code(), "InnerError");
135 }
136
137 #[test]
138 fn test_enum_error_code() {
139 let err = StorageError::Connection;
140 assert_eq!(err.error_code(), "StorageError::Connection");
141
142 let err = StorageError::NotFound;
143 assert_eq!(err.error_code(), "StorageError::NotFound");
144 }
145
146 #[test]
147 fn test_inherited_error_code() {
148 let err = GroupError::NotFound;
149 assert_eq!(err.error_code(), "GroupError::NotFound");
150
151 let err = GroupError::InvalidMembership;
152 assert_eq!(err.error_code(), "GroupError::InvalidMembership");
153
154 let err = GroupError::Storage(StorageError::Connection);
156 assert_eq!(err.error_code(), "StorageError::Connection");
157
158 let err = GroupError::Inner(InnerError);
160 assert_eq!(err.error_code(), "InnerError");
161 }
162
163 #[test]
164 fn test_boxed_error_code() {
165 let err = Box::new(StorageError::Connection);
166 assert_eq!(err.error_code(), "StorageError::Connection");
167 }
168
169 #[test]
170 fn test_ref_error_code() {
171 let err = StorageError::Connection;
172 let err_ref = &err;
173 assert_eq!(err_ref.error_code(), "StorageError::Connection");
174 }
175
176 #[derive(Debug, Error, ErrorCode)]
178 enum RenamedError {
179 #[error("new name for the variant")]
181 #[error_code("RenamedError::OldVariantName")]
182 NewVariantName,
183 #[error("another variant")]
185 AnotherVariant,
186 }
187
188 #[test]
189 fn test_custom_error_code() {
190 let err = RenamedError::NewVariantName;
192 assert_eq!(err.error_code(), "RenamedError::OldVariantName");
193
194 let err = RenamedError::AnotherVariant;
196 assert_eq!(err.error_code(), "RenamedError::AnotherVariant");
197 }
198
199 #[test]
202 fn test_signature_error_codes() {
203 use xmtp_cryptography::signature::SignatureError;
204
205 let err = SignatureError::BadAddressFormat(hex::FromHexError::OddLength);
207 assert_eq!(err.error_code(), "SignatureError::BadAddressFormat");
208
209 let err = SignatureError::BadSignature {
211 addr: "0x123".to_string(),
212 };
213 assert_eq!(err.error_code(), "SignatureError::BadSignature");
214
215 let err = SignatureError::Unknown;
216 assert_eq!(err.error_code(), "SignatureError::Unknown");
217 }
218
219 #[test]
220 fn test_identifier_validation_error_codes() {
221 use xmtp_cryptography::signature::IdentifierValidationError;
222
223 let err = IdentifierValidationError::InvalidAddresses(vec!["bad".to_string()]);
224 assert_eq!(
225 err.error_code(),
226 "IdentifierValidationError::InvalidAddresses"
227 );
228
229 let err = IdentifierValidationError::HexDecode(hex::FromHexError::OddLength);
230 assert_eq!(err.error_code(), "IdentifierValidationError::HexDecode");
231
232 let err = IdentifierValidationError::Generic("generic error".to_string());
233 assert_eq!(err.error_code(), "IdentifierValidationError::Generic");
234 }
235
236 #[test]
237 fn test_ethereum_crypto_error_codes() {
238 use xmtp_cryptography::ethereum::EthereumCryptoError;
239
240 let err = EthereumCryptoError::InvalidLength;
241 assert_eq!(err.error_code(), "EthereumCryptoError::InvalidLength");
242
243 let err = EthereumCryptoError::InvalidKey;
244 assert_eq!(err.error_code(), "EthereumCryptoError::InvalidKey");
245
246 let err = EthereumCryptoError::SignFailure;
247 assert_eq!(err.error_code(), "EthereumCryptoError::SignFailure");
248
249 let err = EthereumCryptoError::DecompressFailure;
250 assert_eq!(err.error_code(), "EthereumCryptoError::DecompressFailure");
251 }
252
253 #[test]
254 fn test_hex_from_hex_error_code() {
255 let err = hex::FromHexError::OddLength;
256 assert_eq!(err.error_code(), "hex::FromHexError");
257
258 let err = hex::FromHexError::InvalidHexCharacter { c: 'Z', index: 0 };
259 assert_eq!(err.error_code(), "hex::FromHexError");
260
261 let err = hex::FromHexError::InvalidStringLength;
262 assert_eq!(err.error_code(), "hex::FromHexError");
263 }
264}