x402_kit/
concepts.rs

1//! Core traits and types used across the X402 Kit.
2
3use std::{fmt::Display, str::FromStr};
4
5use url::Url;
6
7use crate::{
8    transport::{
9        FacilitatorPaymentRequest, FacilitatorSettleResponse, FacilitatorSupportedResponse,
10        FacilitatorVerifyResponse, PaymentRequirements,
11    },
12    types::{AmountValue, AnyJson, OutputSchema},
13};
14
15/// A series of network families, e.g. EVM, SVM, etc.
16pub trait NetworkFamily {
17    /// The name of the network in the family.
18    fn network_name(&self) -> &str;
19}
20
21/// Network-specific address type.
22pub trait Address: FromStr + Display + Copy {
23    type Network: NetworkFamily;
24}
25
26/// A payment scheme applied to a network family.
27pub trait Scheme {
28    type Network: NetworkFamily;
29    type Payload;
30    const SCHEME_NAME: &'static str;
31
32    fn network(&self) -> &Self::Network;
33
34    fn select<A: Address<Network = Self::Network>>(
35        &self,
36        pr: &PaymentRequirements,
37    ) -> Option<PaymentSelection<A>>
38    where
39        Self: Sized,
40    {
41        if pr.scheme == Self::SCHEME_NAME && pr.network == self.network().network_name() {
42            Some(PaymentSelection {
43                max_amount_required: pr.max_amount_required,
44                resource: pr.resource.clone(),
45                description: pr.description.clone(),
46                mime_type: pr.mime_type.clone(),
47                pay_to: pr.pay_to.parse().ok()?,
48                max_timeout_seconds: pr.max_timeout_seconds,
49                asset: pr.asset.parse().ok()?,
50                output_schema: pr.output_schema.clone(),
51                extra: pr.extra.clone(),
52            })
53        } else {
54            None
55        }
56    }
57}
58
59/// Represents an asset on a given address.
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61pub struct Asset<A: Address> {
62    pub address: A,
63    pub decimals: u8,
64    pub name: &'static str,
65    pub symbol: &'static str,
66}
67
68/// Selected payment requirements for a given scheme and address type.
69#[derive(Debug, Clone)]
70pub struct PaymentSelection<A: Address> {
71    /// Maximum amount required for the payment in smallest units
72    pub max_amount_required: AmountValue,
73    /// Resource URL to fetch payment details
74    pub resource: Url,
75    /// Description of the resource
76    pub description: String,
77    /// MIME type of the payment payload
78    pub mime_type: String,
79    /// Destination address or account to pay to
80    pub pay_to: A,
81    /// Maximum timeout in seconds for the payment to be completed
82    pub max_timeout_seconds: u64,
83    /// Asset address or identifier
84    pub asset: A,
85    /// Schema of the input / output payload
86    pub output_schema: Option<OutputSchema>,
87    /// Extra fields for extensibility
88    pub extra: Option<AnyJson>,
89}
90
91/// Signer for a given payment scheme.
92pub trait SchemeSigner<A: Address<Network = <Self::Scheme as Scheme>::Network>> {
93    type Scheme: Scheme;
94    type Error: std::error::Error;
95
96    fn sign(
97        &self,
98        selected: &PaymentSelection<A>,
99    ) -> impl Future<Output = Result<<Self::Scheme as Scheme>::Payload, Self::Error>>;
100}
101
102/// X402 facilitator interface.
103pub trait Facilitator {
104    type Error: std::error::Error;
105
106    fn supported(&self) -> impl Future<Output = Result<FacilitatorSupportedResponse, Self::Error>>;
107
108    fn verify(
109        &self,
110        request: FacilitatorPaymentRequest,
111    ) -> impl Future<Output = Result<FacilitatorVerifyResponse, Self::Error>>;
112
113    fn settle(
114        &self,
115        request: FacilitatorPaymentRequest,
116    ) -> impl Future<Output = Result<FacilitatorSettleResponse, Self::Error>>;
117}