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