use thiserror::Error;
pub type Result<T> = std::result::Result<T, SdkError>;
#[derive(Debug, Error)]
pub enum SdkError {
#[error("invalid agent id: {0}")]
InvalidAgentId(String),
#[error("agent id must start with did:agent:")]
InvalidAgentIdPrefix,
#[error("invalid public key length: expected 32 bytes, got {0}")]
InvalidPublicKeyLength(usize),
#[error("canonical JSON error: {0}")]
CanonicalJson(String),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("base64url decode error: {0}")]
Base64(#[from] base64::DecodeError),
#[error("Ed25519 error: {0}")]
Ed25519(#[from] ed25519_dalek::SignatureError),
#[error("random generation error: {0}")]
Random(String),
#[error("invalid signature length: expected 64 bytes, got {0}")]
InvalidSignatureLength(usize),
#[error("invalid event hash: expected {expected}, got {actual}")]
InvalidEventHash { expected: String, actual: String },
#[error("invalid event hash length: expected 32 bytes, got {0}")]
InvalidEventHashLength(usize),
#[error("invalid event protocol: expected {expected}, got {actual}")]
InvalidEventProtocol { expected: String, actual: String },
#[error("invalid event type: expected {expected}, got {actual}")]
InvalidEventType { expected: String, actual: String },
#[error("invalid actor: {0}")]
InvalidActor(String),
#[error("timestamp is outside the allowed live-write window")]
TimestampOutOfWindow,
#[error("invalid nonce: {0}")]
InvalidNonce(String),
#[error("nonce must be greater than accepted max nonce {max_nonce}")]
NonceNotGreater { max_nonce: u64 },
#[error("event requires a room_id")]
MissingRoomId,
#[error("room id mismatch: expected {expected}, got {actual}")]
RoomIdMismatch { expected: String, actual: String },
#[error("permission denied")]
PermissionDenied,
#[error("invalid payload: {0}")]
InvalidPayload(String),
#[error("event type is not defined in the room: {0}")]
TypeNotDefined(String),
#[error("event type is disabled in the room: {0}")]
TypeDisabled(String),
#[error("payload does not satisfy the type schema: {0}")]
PayloadSchemaViolation(String),
#[error("type pack cannot be resolved or fails verification: {0}")]
PackUnavailable(String),
#[error("invalid JWT: {0}")]
InvalidJwt(String),
#[error("invalid JWT claim: {0}")]
InvalidJwtClaim(&'static str),
#[error("{code}: {message}")]
Protocol { code: &'static str, message: String },
#[error("{code}: {message}")]
ProtocolWithData {
code: &'static str,
message: String,
data: serde_json::Value,
},
#[error("paginated read did not complete within {0} pages")]
PageLimitExceeded(usize),
#[error("HTTP {status}: {body}")]
HttpStatus {
status: u16,
code: Option<String>,
data: Option<serde_json::Value>,
max_seen_nonce: Option<String>,
body: String,
},
#[cfg(feature = "http-client")]
#[error("HTTP client error: {0}")]
Http(#[from] reqwest::Error),
}
impl SdkError {
pub fn protocol(code: &'static str, message: impl Into<String>) -> Self {
Self::Protocol {
code,
message: message.into(),
}
}
pub fn protocol_with_data(
code: &'static str,
message: impl Into<String>,
data: serde_json::Value,
) -> Self {
Self::ProtocolWithData {
code,
message: message.into(),
data,
}
}
pub fn data(&self) -> Option<&serde_json::Value> {
match self {
Self::ProtocolWithData { data, .. } => Some(data),
Self::HttpStatus { data, .. } => data.as_ref(),
_ => None,
}
}
pub fn code(&self) -> Option<&str> {
match self {
Self::Protocol { code, .. } | Self::ProtocolWithData { code, .. } => Some(code),
Self::HttpStatus { code, .. } => code.as_deref(),
Self::InvalidSignatureLength(_) | Self::Ed25519(_) => Some("invalid_signature"),
Self::InvalidEventHash { .. } | Self::InvalidEventHashLength(_) => {
Some("invalid_event_hash")
}
Self::TimestampOutOfWindow => Some("timestamp_out_of_window"),
Self::NonceNotGreater { .. } => Some("nonce_not_greater"),
Self::PermissionDenied => Some("permission_denied"),
Self::TypeNotDefined(_) => Some("type_not_defined"),
Self::TypeDisabled(_) => Some("type_disabled"),
Self::PayloadSchemaViolation(_) => Some("payload_schema_violation"),
Self::PackUnavailable(_) => Some("pack_unavailable"),
Self::InvalidJwt(_) | Self::InvalidJwtClaim(_) => Some("invalid_token"),
Self::InvalidActor(_) => Some("invalid_actor"),
_ => None,
}
}
}