use r402::proto;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum McpPaymentError {
#[error("Tool call failed: {0}")]
ToolCallFailed(String),
#[error("No matching payment option found")]
NoMatchingPaymentOption,
#[error("Failed to create payment: {0}")]
PaymentCreationFailed(String),
#[error("Failed to sign payment: {0}")]
SigningFailed(String),
#[error("Payment verification failed: {0}")]
VerificationFailed(String),
#[error("Settlement failed: {0}")]
SettlementFailed(String),
#[error("Operation aborted: {0}")]
Aborted(String),
#[error("Payment required")]
PaymentRequired(Box<PaymentRequiredError>),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error(transparent)]
Facilitator(#[from] r402::facilitator::FacilitatorError),
#[error("Client error: {0}")]
Client(#[from] r402::scheme::ClientError),
}
#[derive(Debug, Clone)]
pub struct PaymentRequiredError {
pub message: String,
pub payment_required: proto::PaymentRequired,
}
impl std::fmt::Display for PaymentRequiredError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.message)
}
}
impl std::error::Error for PaymentRequiredError {}
impl PaymentRequiredError {
#[must_use]
pub fn new(message: impl Into<String>, payment_required: proto::PaymentRequired) -> Self {
Self {
message: message.into(),
payment_required,
}
}
}
#[must_use]
pub const fn is_payment_required_error(err: &McpPaymentError) -> bool {
matches!(err, McpPaymentError::PaymentRequired(_))
}