use serde_json::Value;
use thiserror::Error;
use crate::signing::auth::AuthError;
pub type Result<T> = std::result::Result<T, DeriveWsError>;
#[derive(Debug, Error)]
pub enum DeriveWsError {
#[error("transport error: {0}")]
Transport(String),
#[error("serde error: {0}")]
Serde(#[from] serde_json::Error),
#[error("JSON-RPC error {code}: {message}")]
JsonRpc {
code: i64,
message: String,
data: Option<Value>,
},
#[error("request `{method}` cancelled before response was received")]
RequestCancelled {
method: String,
},
#[error("request `{method}` timed out before response was received")]
Timeout {
method: String,
},
#[error("auth error: {0}")]
Auth(#[from] AuthError),
#[error("missing credentials for `{operation}`")]
MissingCredentials {
operation: String,
},
#[error("WebSocket client is not connected")]
NotConnected,
}
impl DeriveWsError {
#[must_use]
pub fn transport(msg: impl Into<String>) -> Self {
Self::Transport(msg.into())
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use serde_json::json;
use super::*;
#[rstest]
fn test_transport_constructor_carries_message() {
let err = DeriveWsError::transport("broken pipe");
assert!(err.to_string().contains("broken pipe"));
}
#[rstest]
fn test_jsonrpc_error_renders_code_and_message() {
let err = DeriveWsError::JsonRpc {
code: -32601,
message: "Method not found".to_string(),
data: Some(json!({"method": "public/foo"})),
};
let rendered = err.to_string();
assert!(rendered.contains("-32601"));
assert!(rendered.contains("Method not found"));
}
#[rstest]
fn test_missing_credentials_names_operation() {
let err = DeriveWsError::MissingCredentials {
operation: "public/login".to_string(),
};
assert!(err.to_string().contains("public/login"));
}
}