x402_kit/
core.rs

1//! Core traits and types used across the X402 Kit.
2
3use std::{fmt::Display, str::FromStr};
4
5use bon::Builder;
6use url::Url;
7
8use crate::types::{AmountValue, AnyJson, Extension, OutputSchema, Record};
9
10/// A series of network families, e.g. EVM, SVM, etc.
11pub trait NetworkFamily {
12    /// The name of the network in the family.
13    fn network_name(&self) -> &str;
14
15    /// The Blockchain network identifier in CAIP-2 format (e.g., "eip155:84532")
16    fn network_id(&self) -> &str;
17}
18
19/// Network-specific address type.
20pub trait Address: FromStr + Display + Copy {
21    /// The network family this address belongs to.
22    type Network: NetworkFamily;
23}
24
25/// A payment scheme applied to a network family.
26pub trait Scheme {
27    /// The network family this scheme applies to.
28    type Network: NetworkFamily;
29    /// The payload type produced by this scheme.
30    type Payload;
31    /// The name of the scheme.
32    const SCHEME_NAME: &'static str;
33    /// Get the concrete network for this scheme.
34    fn network(&self) -> &Self::Network;
35
36    // fn select<A: Address<Network = Self::Network>>(
37    //     &self,
38    //     pr: &PaymentRequirements,
39    // ) -> Option<PaymentSelection<A>>
40    // where
41    //     Self: Sized,
42    // {
43    //     if pr.scheme == Self::SCHEME_NAME && pr.network == self.network().network_name() {
44    //         Some(PaymentSelection {
45    //             max_amount_required: pr.max_amount_required,
46    //             resource: pr.resource.clone(),
47    //             description: pr.description.clone(),
48    //             mime_type: pr.mime_type.clone(),
49    //             pay_to: pr.pay_to.parse().ok()?,
50    //             max_timeout_seconds: pr.max_timeout_seconds,
51    //             asset: pr.asset.parse().ok()?,
52    //             output_schema: pr.output_schema.clone(),
53    //             extra: pr.extra.clone(),
54    //         })
55    //     } else {
56    //         None
57    //     }
58    // }
59}
60
61/// Represents an asset on a given address.
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub struct Asset<A: Address> {
64    pub address: A,
65    pub decimals: u8,
66    pub name: &'static str,
67    pub symbol: &'static str,
68}
69
70/// Payment configuration for a given scheme and transport.
71#[derive(Builder)]
72pub struct Payment<S, A>
73where
74    S: Scheme,
75    A: Address<Network = S::Network>,
76{
77    /// The payment scheme.
78    pub scheme: S,
79    /// The address to use for payments.
80    #[builder(into)]
81    pub pay_to: A,
82    /// The asset for the payment
83    #[builder(into)]
84    pub asset: Asset<A>,
85    /// The amount of the asset to pay, in smallest units.
86    #[builder(into)]
87    pub amount: AmountValue,
88    /// Maximum timeout in seconds for the payment to be completed.
89    pub max_timeout_seconds: u64,
90    /// Optional extra data for the payment.
91    pub extra: Option<AnyJson>,
92}
93
94/// Payment configuration for a given scheme and transport.
95#[derive(Builder)]
96pub struct PaymentSelection<A: Address> {
97    /// The address to use for payments.
98    #[builder(into)]
99    pub pay_to: A,
100    /// The asset for the payment
101    #[builder(into)]
102    pub asset: A,
103    /// The amount of the asset to pay, in smallest units.
104    #[builder(into)]
105    pub amount: AmountValue,
106    /// Maximum timeout in seconds for the payment to be completed.
107    pub max_timeout_seconds: u64,
108    /// Optional extra data for the payment.
109    pub extra: Option<AnyJson>,
110    /// Resource definition.
111    pub resource: Resource,
112    /// Extensions
113    #[builder(default)]
114    pub extensions: Record<Extension>,
115}
116
117/// Signer for a given payment scheme.
118pub trait SchemeSigner<A: Address<Network = <Self::Scheme as Scheme>::Network>> {
119    type Scheme: Scheme;
120    type Error: std::error::Error;
121
122    fn sign(
123        &self,
124        payment: &PaymentSelection<A>,
125    ) -> impl Future<Output = Result<<Self::Scheme as Scheme>::Payload, Self::Error>>;
126}
127
128/// Resource definition.
129#[derive(Builder, Debug, Clone, PartialEq, Eq)]
130pub struct Resource {
131    /// Optional resource URL.
132    pub url: Url,
133    /// Optional description of the resource.
134    #[builder(into)]
135    pub description: String,
136    /// Optional MIME type of the resource.
137    #[builder(into)]
138    pub mime_type: String,
139    /// Optional output schema for the payment payload.
140    pub output_schema: Option<OutputSchema>,
141}