x402_kit/
lib.rs

1//! # X402 Kit
2//!
3//! X402 Kit is a fully modular, framework-agnostic, easy-to-extend SDK for building complex X402 payment integrations.
4//!
5//! X402-kit is **not a facilitator** — it's a composable SDK for buyers (signers) and sellers (servers) to build custom business logic.
6//! Future support for modular facilitator components is planned.
7//!
8//! ## Core Components Overview
9//!
10//! ### For the X402 Protocol
11//!
12//! - **[`core`]**: Core traits and types used across the X402 Kit, including resource configuration.
13//! - **[`transport`]**: Types and traits for defining X402 transport mechanisms and facilitator interactions.
14//! - **[`types`]**: Common re-usable types for defining the X402 protocol.
15//!
16//! ### For Network-Specific Implementations
17//!
18//! - **[`networks`]**: Network-specific implementations, e.g., EVM / SVM assets and addresses.
19//! - **[`schemes`]**: Payment scheme implementations, e.g., Exact EVM / Exact SVM, and their signer logic.
20//!
21//! ### Facilitator Utilities
22//!
23//! - **[`facilitator`]**: Traits and types for building X402 facilitators.
24//! - **[`facilitator_client`]**: Utilities for building X402 facilitator clients.
25//!
26//! ## Extend X402 Kit As You Like
27//!
28//! The main idea is you don't need to wait for the upstream library to support the network or asset in your case.
29//! Adding a new network, asset, or scheme is as simple as implementing a few traits.
30//!
31//! However, we still recommend contributing back any useful implementations to the main repository to help grow the ecosystem!
32//!
33//! ### New Networks
34//!
35//! If you want support for new EVM / SVM networks or assets, just "declare" them anywhere in your codebase:
36//!
37//! #### Custom EVM Network
38//!
39//! ```
40//! use x402_kit::networks::evm::{ExplicitEvmNetwork, EvmNetwork};
41//!
42//! struct MyCustomEvmNetwork;
43//!
44//! impl ExplicitEvmNetwork for MyCustomEvmNetwork {
45//!     const NETWORK: EvmNetwork = EvmNetwork {
46//!         name: "my-custom-evm-network",
47//!         chain_id: 12345,
48//!         network_id: "eip155:12345",
49//!     };
50//! }
51//!
52//! // Now you can use MyCustomEvmNetwork with any scheme that supports EVM
53//! ```
54//!
55//! #### Custom SVM Network
56//!
57//! ```
58//! use x402_kit::networks::svm::{ExplicitSvmNetwork, SvmNetwork};
59//!
60//! struct MyCustomSvmNetwork;
61//!
62//! impl ExplicitSvmNetwork for MyCustomSvmNetwork {
63//!     const NETWORK: SvmNetwork = SvmNetwork {
64//!         name: "my-custom-svm-network",
65//!         caip_2_id: "solana:BASE58_GENESIS_HASH",
66//!     };
67//! }
68//!
69//! // Now you can use MyCustomSvmNetwork with any scheme that supports SVM
70//! ```
71//!
72//! ### New Assets
73//!
74//! Similarly, you can define custom assets for your networks:
75//!
76//! #### Custom EVM Asset
77//!
78//! ```
79//! use alloy_primitives::address;
80//! use x402_kit::networks::evm::{
81//!     ExplicitEvmAsset, ExplicitEvmNetwork, EvmNetwork, EvmAsset, EvmAddress, Eip712Domain
82//! };
83//!
84//! struct MyCustomNetwork;
85//! impl ExplicitEvmNetwork for MyCustomNetwork {
86//!     const NETWORK: EvmNetwork = EvmNetwork {
87//!         name: "my-network",
88//!         chain_id: 12345,
89//!         network_id: "eip155:12345",
90//!     };
91//! }
92//!
93//! struct MyCustomToken;
94//! impl ExplicitEvmAsset for MyCustomToken {
95//!     type Network = MyCustomNetwork;
96//!
97//!     const ASSET: EvmAsset = EvmAsset {
98//!         address: EvmAddress(address!("0x1234567890123456789012345678901234567890")),
99//!         decimals: 18,
100//!         name: "My Custom Token",
101//!         symbol: "MCT",
102//!     };
103//!
104//!     const EIP712_DOMAIN: Option<Eip712Domain> = Some(Eip712Domain {
105//!         name: "My Custom Token",
106//!         version: "1",
107//!     });
108//! }
109//!
110//! // Now you can use MyCustomToken with ExactEvm or other EVM schemes
111//! ```
112//!
113//! #### Custom SVM Asset
114//!
115//! ```
116//! use solana_pubkey::pubkey;
117//! use x402_kit::networks::svm::{
118//!     ExplicitSvmAsset, ExplicitSvmNetwork, SvmNetwork, SvmAsset, SvmAddress
119//! };
120//!
121//! struct MyCustomSvmNetwork;
122//! impl ExplicitSvmNetwork for MyCustomSvmNetwork {
123//!     const NETWORK: SvmNetwork = SvmNetwork {
124//!         name: "my-svm-network",
125//!         caip_2_id: "solana:custom",
126//!     };
127//! }
128//!
129//! struct MyCustomSvmToken;
130//! impl ExplicitSvmAsset for MyCustomSvmToken {
131//!     type Network = MyCustomSvmNetwork;
132//!
133//!     const ASSET: SvmAsset = SvmAsset {
134//!         address: SvmAddress(pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")),
135//!         decimals: 9,
136//!         name: "My Custom SVM Token",
137//!         symbol: "MCST",
138//!     };
139//! }
140//!
141//! // Now you can use MyCustomSvmToken with ExactSvm or other SVM schemes
142//! ```
143//!
144//! #### Using Custom Assets with Schemes
145//!
146//! Once you've defined your custom asset, you can use it with payment schemes just like built-in assets:
147//!
148//! ```no_run
149//! use alloy_primitives::address;
150//! use x402_kit::{
151//!     networks::evm::{ExplicitEvmAsset, ExplicitEvmNetwork, EvmNetwork, EvmAsset, EvmAddress, Eip712Domain},
152//!     schemes::exact_evm::ExactEvm,
153//!     transport::PaymentRequirements,
154//! };
155//!
156//! // Define your custom network and asset
157//! struct Polygon;
158//! impl ExplicitEvmNetwork for Polygon {
159//!     const NETWORK: EvmNetwork = EvmNetwork {
160//!         name: "polygon",
161//!         chain_id: 137,
162//!         network_id: "eip155:137",
163//!     };
164//! }
165//!
166//! struct UsdcPolygon;
167//! impl ExplicitEvmAsset for UsdcPolygon {
168//!     type Network = Polygon;
169//!     const ASSET: EvmAsset = EvmAsset {
170//!         address: EvmAddress(address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174")),
171//!         decimals: 6,
172//!         name: "USD Coin",
173//!         symbol: "USDC",
174//!     };
175//!     const EIP712_DOMAIN: Option<Eip712Domain> = Some(Eip712Domain {
176//!         name: "USD Coin",
177//!         version: "2",
178//!     });
179//! }
180//!
181//! # fn use_custom_asset() {
182//! // Use it in payment requirements
183//! let payment = ExactEvm::builder()
184//!     .asset(UsdcPolygon)
185//!     .amount(1000000) // 1 USDC
186//!     .pay_to(address!("0x3CB9B3bBfde8501f411bB69Ad3DC07908ED0dE20"))
187//!     .build();
188//!
189//! // Convert to PaymentRequirements for use with facilitator
190//! let requirements: PaymentRequirements = payment.into();
191//! # }
192//! ```
193//!
194//! ### Defining New Network Families
195//!
196//! If you want to define an entirely new family of networks (beyond EVM or SVM), you need to implement the core traits under [`core`]:
197//!
198//! - [`core::NetworkFamily`]: Represents a blockchain network family
199//! - [`core::Address`]: Represents an address on that network
200//!
201//! The `Address` type should also implement `FromStr`, `Display`, `Copy`, `Debug`, `Clone`, `PartialEq`, `Eq`, and `Hash` for proper serialization/deserialization and usage throughout the SDK.
202//!
203//! Here's a complete example:
204//!
205//! ```
206//! use std::{fmt::Display, str::FromStr};
207//! use x402_kit::core::{Address, Asset, NetworkFamily};
208//!
209//! // Define your network family
210//! struct MyNetworkFamily {
211//!     network_name: &'static str,
212//!     network_id: &'static str,
213//! }
214//!
215//! impl NetworkFamily for MyNetworkFamily {
216//!     fn network_name(&self) -> &str {
217//!         self.network_name
218//!     }
219//!     fn network_id(&self) -> &str {
220//!         self.network_id
221//!     }
222//! }
223//!
224//! // Define an address type for your network
225//! #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
226//! struct MyAddress(u64);
227//!
228//! impl FromStr for MyAddress {
229//!     type Err = std::num::ParseIntError;
230//!
231//!     fn from_str(s: &str) -> Result<Self, Self::Err> {
232//!         s.parse::<u64>().map(MyAddress)
233//!     }
234//! }
235//!
236//! impl Display for MyAddress {
237//!     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238//!         write!(f, "{}", self.0)
239//!     }
240//! }
241//!
242//! impl Address for MyAddress {
243//!     type Network = MyNetworkFamily;
244//! }
245//!
246//! // Define an asset type for your network
247//! type MyAsset = Asset<MyAddress>;
248//!
249//! # fn use_custom_network_family() {
250//! // Now you can use your custom network family
251//! let network = MyNetworkFamily {
252//!     network_name: "my-custom-network",
253//!     network_id: "mynet:42",
254//! };
255//!
256//! let address: MyAddress = "12345".parse().unwrap();
257//! assert_eq!(address.to_string(), "12345");
258//!
259//! let asset = MyAsset {
260//!     address,
261//!     decimals: 18,
262//!     name: "My Token",
263//!     symbol: "MTK",
264//! };
265//! # }
266//! ```
267//!
268//! Once you have these core types defined, you can build schemes and payment requirements for your custom network family by implementing the [`core::Scheme`] trait.
269//!
270//! ### Defining new Schemes
271//!
272//! To define a new payment scheme, implement the `Scheme` trait from the `core` module. This involves specifying the associated network and payload types.
273//!
274//! Just take how `ExactSvmScheme` is defined for example:
275//!
276//! ```
277//! use serde::{Deserialize, Serialize};
278//! use x402_kit::core::Scheme;
279//! use x402_kit::networks::svm::SvmNetwork;
280//!
281//! pub struct ExactSvmScheme(pub SvmNetwork);
282//!
283//! #[derive(Debug, Clone, Serialize, Deserialize)]
284//! #[serde(rename_all = "camelCase")]
285//! pub struct ExplicitSvmPayload {
286//!     pub transaction: String,
287//! }
288//!
289//! impl Scheme for ExactSvmScheme {
290//!     type Network = SvmNetwork;
291//!     type Payload = ExplicitSvmPayload;
292//!     const SCHEME_NAME: &'static str = "exact";
293//!     fn network(&self) -> &Self::Network {
294//!         &self.0
295//!     }
296//! }
297//! ```
298//!
299//! Then you should make an entrypoint to convert the scheme into `PaymentRequirements`.
300//!
301//! Note that `Payment` is a type-safe builder for constructing payment configurations from schemes.
302//!
303//! ```
304//! use bon::Builder;
305//! use x402_kit::core::Payment;
306//! use x402_kit::networks::svm::{ExplicitSvmAsset, ExplicitSvmNetwork, SvmAddress};
307//! use x402_kit::schemes::exact_svm::ExactSvmScheme;
308//! use x402_kit::transport::PaymentRequirements;
309//!
310//! #[derive(Builder, Debug, Clone)]
311//! pub struct ExactSvm<A: ExplicitSvmAsset> {
312//!     pub asset: A,
313//!     #[builder(into)]
314//!     pub pay_to: SvmAddress,
315//!     pub amount: u64,
316//!     pub max_timeout_seconds_override: Option<u64>,
317//! }
318//! impl<A: ExplicitSvmAsset> ExactSvm<A> {
319//!     pub fn into_payment(self) -> Payment<ExactSvmScheme, SvmAddress> {
320//!         Payment::builder()
321//!             .scheme(ExactSvmScheme(A::Network::NETWORK))
322//!             .amount(self.amount)
323//!             .asset(A::ASSET)
324//!             .pay_to(self.pay_to)
325//!             .max_timeout_seconds(self.max_timeout_seconds_override.unwrap_or(60))
326//!             .build()
327//!     }
328//! }
329//!
330//! ```
331//!
332
333pub mod core;
334pub mod errors;
335pub mod facilitator;
336pub mod networks;
337pub mod schemes;
338pub mod transport;
339pub mod types;
340
341#[cfg(feature = "facilitator-client")]
342pub mod facilitator_client;