Skip to main content

r402_core/
facilitator.rs

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