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//! ## Related Crates
9//!
10//! - **[`x402_core`]**: Core traits, types, and transport mechanisms
11//!   for the X402 protocol. This crate provides the foundational building blocks that `x402-kit` builds upon.
12//! - **[`x402_paywall`]**: A framework-agnostic HTTP paywall middleware
13//!   built on top of `x402-kit`. Use it to protect HTTP resources with X402 payments.
14//!
15//! ## Quick Start
16//!
17//! ```
18//! use alloy::primitives::address;
19//! use axum::{
20//!     extract::{Request, State},
21//!     middleware::{from_fn_with_state, Next},
22//!     response::{IntoResponse, Response},
23//!     routing::post,
24//!     Router,
25//! };
26//! use url_macro::url;
27//! use x402_kit::{
28//!     core::Resource,
29//!     facilitator_client::{FacilitatorClient, StandardFacilitatorClient},
30//!     networks::evm::assets::UsdcBaseSepolia,
31//!     paywall::paywall::PayWall,
32//!     schemes::exact_evm::ExactEvm,
33//! };
34//!
35//!
36//! #[derive(Clone)]
37//! struct PayWallState {
38//!     facilitator: StandardFacilitatorClient,
39//! }
40//!
41//! let facilitator = FacilitatorClient::from_url(url!("https://facilitator.example.com"));
42//!
43//! async fn paywall_middleware(State(state): State<PayWallState>, req: Request, next: Next) -> Response {
44//!     let paywall = PayWall::builder()
45//!         .facilitator(state.facilitator)
46//!         .accepts(
47//!             ExactEvm::builder()
48//!                 .amount(1000)
49//!                 .asset(UsdcBaseSepolia)
50//!                 .pay_to(address!("0x3CB9B3bBfde8501f411bB69Ad3DC07908ED0dE20"))
51//!                 .build(),
52//!         )
53//!         .resource(
54//!             Resource::builder()
55//!                 .url(url!("https://example.com/resource"))
56//!                 .description("Protected resource")
57//!                 .mime_type("application/json")
58//!                 .build(),
59//!         )
60//!         .build();
61//!
62//!     paywall
63//!         .handle_payment(req, |req| next.run(req))
64//!         .await
65//!         .unwrap_or_else(|err| err.into_response())
66//! }
67//! ```
68//!
69//! See [`examples/axum_seller.rs`](https://github.com/AIMOverse/x402-kit/blob/main/x402-kit/examples/axum_seller.rs)
70//! for a complete working example.
71//!
72//! ## Accepting Multiple Payment Methods
73//!
74//! You can accept payments from multiple networks (e.g., EVM and SVM) using [`transport::Accepts`]:
75//!
76//! ```
77//! use alloy::primitives::address;
78//! use solana_pubkey::pubkey;
79//! use x402_kit::{
80//!     networks::{evm::assets::UsdcBaseSepolia, svm::assets::UsdcSolanaDevnet},
81//!     schemes::{exact_evm::ExactEvm, exact_svm::ExactSvm},
82//!     transport::Accepts,
83//! };
84//!
85//! let accepts = Accepts::new()
86//!     .push(
87//!         ExactEvm::builder()
88//!             .amount(1000)
89//!             .asset(UsdcBaseSepolia)
90//!             .pay_to(address!("0x3CB9B3bBfde8501f411bB69Ad3DC07908ED0dE20"))
91//!             .build(),
92//!     )
93//!     .push(
94//!         ExactSvm::builder()
95//!             .amount(1000)
96//!             .asset(UsdcSolanaDevnet)
97//!             .pay_to(pubkey!("Ge3jkza5KRfXvaq3GELNLh6V1pjjdEKNpEdGXJgjjKUR"))
98//!             .build(),
99//!     );
100//! ```
101//!
102//! ## Core Components Overview
103//!
104//! ### For the X402 Protocol
105//!
106//! - **[`core`]**: Core traits and types used across the X402 Kit, including resource configuration.
107//! - **[`transport`]**: Types and traits for defining X402 transport mechanisms and facilitator interactions.
108//! - **[`types`]**: Common re-usable types for defining the X402 protocol.
109//!
110//! ### For Network-Specific Implementations
111//!
112//! - **[`networks`]**: Network-specific implementations, e.g., EVM / SVM assets and addresses.
113//! - **[`schemes`]**: Payment scheme implementations, e.g., Exact EVM / Exact SVM, and their signer logic.
114//!
115//! ### Facilitator Utilities
116//!
117//! - **[`facilitator`]**: Traits and types for building X402 facilitators.
118//! - **[`facilitator_client`]**: Utilities for building X402 facilitator clients.
119//!
120//! ## Extend X402 Kit As You Like
121//!
122//! The main idea is you don't need to wait for the upstream library to support the network or asset in your case.
123//! Adding a new network, asset, or scheme is as simple as implementing a few traits.
124//!
125//! However, we still recommend contributing back any useful implementations to the main repository to help grow the ecosystem!
126//!
127//! ### New Networks
128//!
129//! If you want support for new EVM / SVM networks or assets, just "declare" them anywhere in your codebase:
130//!
131//! #### Custom EVM Network
132//!
133//! ```
134//! use x402_kit::networks::evm::{ExplicitEvmNetwork, EvmNetwork};
135//!
136//! struct MyCustomEvmNetwork;
137//!
138//! impl ExplicitEvmNetwork for MyCustomEvmNetwork {
139//!     const NETWORK: EvmNetwork = EvmNetwork {
140//!         name: "my-custom-evm-network",
141//!         chain_id: 12345,
142//!         network_id: "eip155:12345",
143//!     };
144//! }
145//!
146//! // Now you can use MyCustomEvmNetwork with any scheme that supports EVM
147//! ```
148//!
149//! #### Custom SVM Network
150//!
151//! ```
152//! use x402_kit::networks::svm::{ExplicitSvmNetwork, SvmNetwork};
153//!
154//! struct MyCustomSvmNetwork;
155//!
156//! impl ExplicitSvmNetwork for MyCustomSvmNetwork {
157//!     const NETWORK: SvmNetwork = SvmNetwork {
158//!         name: "my-custom-svm-network",
159//!         caip_2_id: "solana:BASE58_GENESIS_HASH",
160//!     };
161//! }
162//!
163//! // Now you can use MyCustomSvmNetwork with any scheme that supports SVM
164//! ```
165//!
166//! ### New Assets
167//!
168//! Similarly, you can define custom assets for your networks:
169//!
170//! #### Custom EVM Asset
171//!
172//! ```
173//! use alloy_primitives::address;
174//! use x402_kit::networks::evm::{
175//!     ExplicitEvmAsset, ExplicitEvmNetwork, EvmNetwork, EvmAsset, EvmAddress, Eip712Domain
176//! };
177//!
178//! struct MyCustomNetwork;
179//! impl ExplicitEvmNetwork for MyCustomNetwork {
180//!     const NETWORK: EvmNetwork = EvmNetwork {
181//!         name: "my-network",
182//!         chain_id: 12345,
183//!         network_id: "eip155:12345",
184//!     };
185//! }
186//!
187//! struct MyCustomToken;
188//! impl ExplicitEvmAsset for MyCustomToken {
189//!     type Network = MyCustomNetwork;
190//!
191//!     const ASSET: EvmAsset = EvmAsset {
192//!         address: EvmAddress(address!("0x1234567890123456789012345678901234567890")),
193//!         decimals: 18,
194//!         name: "My Custom Token",
195//!         symbol: "MCT",
196//!     };
197//!
198//!     const EIP712_DOMAIN: Option<Eip712Domain> = Some(Eip712Domain {
199//!         name: "My Custom Token",
200//!         version: "1",
201//!     });
202//! }
203//!
204//! // Now you can use MyCustomToken with ExactEvm or other EVM schemes
205//! ```
206//!
207//! #### Custom SVM Asset
208//!
209//! ```
210//! use solana_pubkey::pubkey;
211//! use x402_kit::networks::svm::{
212//!     ExplicitSvmAsset, ExplicitSvmNetwork, SvmNetwork, SvmAsset, SvmAddress
213//! };
214//!
215//! struct MyCustomSvmNetwork;
216//! impl ExplicitSvmNetwork for MyCustomSvmNetwork {
217//!     const NETWORK: SvmNetwork = SvmNetwork {
218//!         name: "my-svm-network",
219//!         caip_2_id: "solana:custom",
220//!     };
221//! }
222//!
223//! struct MyCustomSvmToken;
224//! impl ExplicitSvmAsset for MyCustomSvmToken {
225//!     type Network = MyCustomSvmNetwork;
226//!
227//!     const ASSET: SvmAsset = SvmAsset {
228//!         address: SvmAddress(pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")),
229//!         decimals: 9,
230//!         name: "My Custom SVM Token",
231//!         symbol: "MCST",
232//!     };
233//! }
234//!
235//! // Now you can use MyCustomSvmToken with ExactSvm or other SVM schemes
236//! ```
237//!
238//! #### Using Custom Assets with Schemes
239//!
240//! Once you've defined your custom asset, you can use it with payment schemes just like built-in assets:
241//!
242//! ```
243//! use alloy_primitives::address;
244//! use x402_kit::{
245//!     networks::evm::{ExplicitEvmAsset, ExplicitEvmNetwork, EvmNetwork, EvmAsset, EvmAddress, Eip712Domain},
246//!     schemes::exact_evm::ExactEvm,
247//!     transport::PaymentRequirements,
248//! };
249//!
250//! // Define your custom network and asset
251//! struct Polygon;
252//! impl ExplicitEvmNetwork for Polygon {
253//!     const NETWORK: EvmNetwork = EvmNetwork {
254//!         name: "polygon",
255//!         chain_id: 137,
256//!         network_id: "eip155:137",
257//!     };
258//! }
259//!
260//! struct UsdcPolygon;
261//! impl ExplicitEvmAsset for UsdcPolygon {
262//!     type Network = Polygon;
263//!     const ASSET: EvmAsset = EvmAsset {
264//!         address: EvmAddress(address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174")),
265//!         decimals: 6,
266//!         name: "USD Coin",
267//!         symbol: "USDC",
268//!     };
269//!     const EIP712_DOMAIN: Option<Eip712Domain> = Some(Eip712Domain {
270//!         name: "USD Coin",
271//!         version: "2",
272//!     });
273//! }
274//!
275//! # fn use_custom_asset() {
276//! // Use it in payment requirements
277//! let payment = ExactEvm::builder()
278//!     .asset(UsdcPolygon)
279//!     .amount(1000000) // 1 USDC
280//!     .pay_to(address!("0x3CB9B3bBfde8501f411bB69Ad3DC07908ED0dE20"))
281//!     .build();
282//!
283//! // Convert to PaymentRequirements for use with facilitator
284//! let requirements: PaymentRequirements = payment.into();
285//! # }
286//! ```
287//!
288//! ### Defining New Network Families
289//!
290//! If you want to define an entirely new family of networks (beyond EVM or SVM), you need to implement the core traits under [`core`]:
291//!
292//! - [`core::NetworkFamily`]: Represents a blockchain network family
293//! - [`core::Address`]: Represents an address on that network
294//!
295//! The `Address` type should also implement `FromStr`, `Display`, `Copy`, `Debug`, `Clone`, `PartialEq`, `Eq`, and `Hash` for proper serialization/deserialization and usage throughout the SDK.
296//!
297//! Here's a complete example:
298//!
299//! ```
300//! use std::{fmt::Display, str::FromStr};
301//! use x402_kit::core::{Address, Asset, NetworkFamily};
302//!
303//! // Define your network family
304//! struct MyNetworkFamily {
305//!     network_name: &'static str,
306//!     network_id: &'static str,
307//! }
308//!
309//! impl NetworkFamily for MyNetworkFamily {
310//!     fn network_name(&self) -> &str {
311//!         self.network_name
312//!     }
313//!     fn network_id(&self) -> &str {
314//!         self.network_id
315//!     }
316//! }
317//!
318//! // Define an address type for your network
319//! #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
320//! struct MyAddress(u64);
321//!
322//! impl FromStr for MyAddress {
323//!     type Err = std::num::ParseIntError;
324//!
325//!     fn from_str(s: &str) -> Result<Self, Self::Err> {
326//!         s.parse::<u64>().map(MyAddress)
327//!     }
328//! }
329//!
330//! impl Display for MyAddress {
331//!     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
332//!         write!(f, "{}", self.0)
333//!     }
334//! }
335//!
336//! impl Address for MyAddress {
337//!     type Network = MyNetworkFamily;
338//! }
339//!
340//! // Define an asset type for your network
341//! type MyAsset = Asset<MyAddress>;
342//!
343//! # fn use_custom_network_family() {
344//! // Now you can use your custom network family
345//! let network = MyNetworkFamily {
346//!     network_name: "my-custom-network",
347//!     network_id: "mynet:42",
348//! };
349//!
350//! let address: MyAddress = "12345".parse().unwrap();
351//! assert_eq!(address.to_string(), "12345");
352//!
353//! let asset = MyAsset {
354//!     address,
355//!     decimals: 18,
356//!     name: "My Token",
357//!     symbol: "MTK",
358//! };
359//! # }
360//! ```
361//!
362//! 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.
363//!
364//! ### Defining new Schemes
365//!
366//! To define a new payment scheme, implement the `Scheme` trait from the `core` module. This involves specifying the associated network and payload types.
367//!
368//! Just take how `ExactSvmScheme` is defined for example:
369//!
370//! ```
371//! use serde::{Deserialize, Serialize};
372//! use x402_kit::core::Scheme;
373//! use x402_kit::networks::svm::SvmNetwork;
374//!
375//! pub struct ExactSvmScheme(pub SvmNetwork);
376//!
377//! #[derive(Debug, Clone, Serialize, Deserialize)]
378//! #[serde(rename_all = "camelCase")]
379//! pub struct ExplicitSvmPayload {
380//!     pub transaction: String,
381//! }
382//!
383//! impl Scheme for ExactSvmScheme {
384//!     type Network = SvmNetwork;
385//!     type Payload = ExplicitSvmPayload;
386//!     const SCHEME_NAME: &'static str = "exact";
387//!     fn network(&self) -> &Self::Network {
388//!         &self.0
389//!     }
390//! }
391//! ```
392//!
393//! Then you should make an entrypoint to convert the scheme into `PaymentRequirements`.
394//!
395//! Note that `Payment` is a type-safe builder for constructing payment configurations from schemes.
396//!
397//! ```
398//! use bon::Builder;
399//! use x402_kit::core::Payment;
400//! use x402_kit::networks::svm::{ExplicitSvmAsset, ExplicitSvmNetwork, SvmAddress, SvmNetwork};
401//! use x402_kit::schemes::exact_svm::ExactSvmScheme;
402//! use x402_kit::transport::PaymentRequirements;
403//!
404//! #[derive(Builder, Debug, Clone)]
405//! pub struct ExactSvm<A: ExplicitSvmAsset> {
406//!     pub asset: A,
407//!     #[builder(into)]
408//!     pub pay_to: SvmAddress,
409//!     pub amount: u64,
410//!     pub max_timeout_seconds_override: Option<u64>,
411//! }
412//!
413//! impl<A: ExplicitSvmAsset> From<ExactSvm<A>> for Payment<ExactSvmScheme, SvmAddress> {
414//!     fn from(scheme: ExactSvm<A>) -> Self {
415//!         Payment {
416//!             scheme: ExactSvmScheme(A::Network::NETWORK),
417//!             pay_to: scheme.pay_to,
418//!             asset: A::ASSET,
419//!             amount: scheme.amount.into(),
420//!             max_timeout_seconds: scheme.max_timeout_seconds_override.unwrap_or(300),
421//!             extra: None,
422//!         }
423//!     }
424//! }
425//!
426//! // Then implement From for PaymentRequirements
427//! impl<A: ExplicitSvmAsset> From<ExactSvm<A>> for PaymentRequirements {
428//!     fn from(scheme: ExactSvm<A>) -> Self {
429//!         PaymentRequirements::from(Payment::from(scheme))
430//!     }
431//! }
432//! ```
433//!
434
435/// Core components for the X402 protocol.
436pub mod core {
437    pub use x402_core::core::*;
438}
439
440/// Transport mechanisms and facilitator interactions.
441pub mod transport {
442    pub use x402_core::transport::*;
443}
444
445/// Common types used across the X402 protocol.
446pub mod types {
447    pub use x402_core::types::*;
448}
449
450/// Facilitator traits and types.
451pub mod facilitator {
452    pub use x402_core::facilitator::*;
453}
454
455/// Errors used across X402 Kit.
456pub mod errors {
457    pub use x402_core::errors::*;
458}
459
460/// X402 Paywall middleware for protecting HTTP resources.
461#[cfg(feature = "paywall")]
462pub mod paywall {
463    pub use x402_paywall::*;
464}
465
466/// Facilitator client utilities.
467#[cfg(feature = "facilitator-client")]
468pub mod facilitator_client;
469/// Network-specific implementations.
470pub mod networks;
471/// Payment scheme implementations.
472pub mod schemes;