rust_x402/types/
facilitator.rs

1//! Facilitator configuration and response types
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::HashMap;
6use std::sync::Arc;
7use std::time::Duration;
8
9/// Type alias for authentication headers function
10pub type AuthHeadersFn =
11    dyn Fn() -> crate::Result<HashMap<String, HashMap<String, String>>> + Send + Sync;
12
13/// Type alias for authentication headers function wrapped in Arc
14pub type AuthHeadersFnArc = Arc<AuthHeadersFn>;
15
16/// Type alias for authentication headers function wrapped in Box
17pub type AuthHeadersFnBox = Box<AuthHeadersFn>;
18
19/// Facilitator configuration
20#[derive(Clone)]
21pub struct FacilitatorConfig {
22    /// Base URL of the facilitator service
23    pub url: String,
24    /// Request timeout
25    pub timeout: Option<Duration>,
26    /// Function to create authentication headers
27    pub create_auth_headers: Option<AuthHeadersFnArc>,
28}
29
30impl std::fmt::Debug for FacilitatorConfig {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        f.debug_struct("FacilitatorConfig")
33            .field("url", &self.url)
34            .field("timeout", &self.timeout)
35            .field("create_auth_headers", &"<function>")
36            .finish()
37    }
38}
39
40impl FacilitatorConfig {
41    /// Create a new facilitator config
42    pub fn new(url: impl Into<String>) -> Self {
43        Self {
44            url: url.into(),
45            timeout: None,
46            create_auth_headers: None,
47        }
48    }
49
50    /// Validate the facilitator configuration
51    pub fn validate(&self) -> crate::Result<()> {
52        if self.url.is_empty() {
53            return Err(crate::X402Error::config("Facilitator URL cannot be empty"));
54        }
55
56        if !self.url.starts_with("http://") && !self.url.starts_with("https://") {
57            return Err(crate::X402Error::config(
58                "Facilitator URL must start with http:// or https://",
59            ));
60        }
61
62        Ok(())
63    }
64
65    /// Set the request timeout
66    pub fn with_timeout(mut self, timeout: Duration) -> Self {
67        self.timeout = Some(timeout);
68        self
69    }
70
71    /// Set the auth headers creator
72    pub fn with_auth_headers(mut self, creator: AuthHeadersFnBox) -> Self {
73        self.create_auth_headers = Some(Arc::from(creator));
74        self
75    }
76}
77
78impl Default for FacilitatorConfig {
79    fn default() -> Self {
80        Self::new("https://x402.org/facilitator")
81    }
82}
83
84/// Payment verification response
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct VerifyResponse {
87    /// Whether the payment is valid
88    #[serde(rename = "isValid")]
89    pub is_valid: bool,
90    /// Reason for invalidity (if applicable)
91    #[serde(rename = "invalidReason", skip_serializing_if = "Option::is_none")]
92    pub invalid_reason: Option<String>,
93    /// Payer's address
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub payer: Option<String>,
96}
97
98/// Payment settlement response
99#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct SettleResponse {
101    /// Whether the settlement was successful
102    pub success: bool,
103    /// Error reason if settlement failed
104    #[serde(rename = "errorReason", skip_serializing_if = "Option::is_none")]
105    pub error_reason: Option<String>,
106    /// Transaction hash or identifier
107    pub transaction: String,
108    /// Network where the transaction was executed
109    pub network: String,
110    /// Payer address if applicable
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub payer: Option<String>,
113}
114
115impl SettleResponse {
116    /// Encode the settle response to base64
117    pub fn to_base64(&self) -> crate::Result<String> {
118        use base64::{engine::general_purpose, Engine as _};
119        let json = serde_json::to_string(self)?;
120        Ok(general_purpose::STANDARD.encode(json))
121    }
122}
123
124/// Supported payment schemes and networks
125#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct SupportedKinds {
127    /// List of supported payment schemes and networks
128    pub kinds: Vec<SupportedKind>,
129}
130
131/// Individual supported payment scheme and network
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct SupportedKind {
134    /// Protocol version
135    #[serde(rename = "x402Version")]
136    pub x402_version: u32,
137    /// Payment scheme identifier
138    pub scheme: String,
139    /// Blockchain network identifier
140    pub network: String,
141    /// Additional metadata provided by the facilitator
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub metadata: Option<Value>,
144}