Skip to main content

r402_facilitator/
facilitator.rs

1//! Unified asynchronous interface for x402 payment facilitators.
2
3use std::future::Future;
4use std::pin::Pin;
5use std::sync::Arc;
6
7use r402_protocol::error::FacilitatorError;
8use r402_protocol::payment::{
9    SettleRequest, SettleResponse, SupportedResponse, VerifyRequest, VerifyResponse,
10};
11
12/// Boxed future alias used by [`DynFacilitator`].
13pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
14
15/// Unified asynchronous interface for x402 facilitators.
16///
17/// This trait is **not** dyn-compatible because it uses `async fn` in traits.
18/// Callers that need a trait object should use [`DynFacilitator`].
19pub trait Facilitator: Send + Sync {
20    /// Verifies a payment payload against its requirements.
21    fn verify(
22        &self,
23        request: VerifyRequest,
24    ) -> impl Future<Output = Result<VerifyResponse, FacilitatorError>> + Send;
25
26    /// Settles a previously verified payment on-chain.
27    ///
28    /// [`r402_protocol::error::ErrorReason::SettlementPending`] must be returned
29    /// as `Ok(SettleResponse::Failure { transaction, .. })` with a non-empty
30    /// hash. `Err` is never retried by a resource server.
31    fn settle(
32        &self,
33        request: SettleRequest,
34    ) -> impl Future<Output = Result<SettleResponse, FacilitatorError>> + Send;
35
36    /// Returns the payment kinds supported by this facilitator.
37    fn supported(&self)
38    -> impl Future<Output = Result<SupportedResponse, FacilitatorError>> + Send;
39}
40
41/// Object-safe erasure of [`Facilitator`], suitable for storing as
42/// `Box<dyn DynFacilitator>` or `Arc<dyn DynFacilitator>`.
43pub trait DynFacilitator: Send + Sync {
44    /// See [`Facilitator::verify`].
45    fn verify(
46        &self,
47        request: VerifyRequest,
48    ) -> BoxFuture<'_, Result<VerifyResponse, FacilitatorError>>;
49
50    /// See [`Facilitator::settle`].
51    fn settle(
52        &self,
53        request: SettleRequest,
54    ) -> BoxFuture<'_, Result<SettleResponse, FacilitatorError>>;
55
56    /// See [`Facilitator::supported`].
57    fn supported(&self) -> BoxFuture<'_, Result<SupportedResponse, FacilitatorError>>;
58}
59
60impl<T> DynFacilitator for T
61where
62    T: Facilitator + ?Sized,
63{
64    fn verify(
65        &self,
66        request: VerifyRequest,
67    ) -> BoxFuture<'_, Result<VerifyResponse, FacilitatorError>> {
68        Box::pin(<Self as Facilitator>::verify(self, request))
69    }
70
71    fn settle(
72        &self,
73        request: SettleRequest,
74    ) -> BoxFuture<'_, Result<SettleResponse, FacilitatorError>> {
75        Box::pin(<Self as Facilitator>::settle(self, request))
76    }
77
78    fn supported(&self) -> BoxFuture<'_, Result<SupportedResponse, FacilitatorError>> {
79        Box::pin(<Self as Facilitator>::supported(self))
80    }
81}
82
83impl<T: Facilitator> Facilitator for Arc<T> {
84    async fn verify(&self, request: VerifyRequest) -> Result<VerifyResponse, FacilitatorError> {
85        self.as_ref().verify(request).await
86    }
87
88    async fn settle(&self, request: SettleRequest) -> Result<SettleResponse, FacilitatorError> {
89        self.as_ref().settle(request).await
90    }
91
92    async fn supported(&self) -> Result<SupportedResponse, FacilitatorError> {
93        self.as_ref().supported().await
94    }
95}
96
97impl<T: Facilitator> Facilitator for Box<T> {
98    async fn verify(&self, request: VerifyRequest) -> Result<VerifyResponse, FacilitatorError> {
99        self.as_ref().verify(request).await
100    }
101
102    async fn settle(&self, request: SettleRequest) -> Result<SettleResponse, FacilitatorError> {
103        self.as_ref().settle(request).await
104    }
105
106    async fn supported(&self) -> Result<SupportedResponse, FacilitatorError> {
107        self.as_ref().supported().await
108    }
109}
110
111impl Facilitator for Box<dyn DynFacilitator> {
112    async fn verify(&self, request: VerifyRequest) -> Result<VerifyResponse, FacilitatorError> {
113        DynFacilitator::verify(self.as_ref(), request).await
114    }
115
116    async fn settle(&self, request: SettleRequest) -> Result<SettleResponse, FacilitatorError> {
117        DynFacilitator::settle(self.as_ref(), request).await
118    }
119
120    async fn supported(&self) -> Result<SupportedResponse, FacilitatorError> {
121        DynFacilitator::supported(self.as_ref()).await
122    }
123}
124
125impl Facilitator for Arc<dyn DynFacilitator> {
126    async fn verify(&self, request: VerifyRequest) -> Result<VerifyResponse, FacilitatorError> {
127        DynFacilitator::verify(self.as_ref(), request).await
128    }
129
130    async fn settle(&self, request: SettleRequest) -> Result<SettleResponse, FacilitatorError> {
131        DynFacilitator::settle(self.as_ref(), request).await
132    }
133
134    async fn supported(&self) -> Result<SupportedResponse, FacilitatorError> {
135        DynFacilitator::supported(self.as_ref()).await
136    }
137}