X402 Kit
X402 Kit is a A fully modular, framework-agnostic, easy-to-extend SDK for building complex X402 payment integrations.
X402-kit is not a facilitator — it's a composable SDK for buyers (signers) and sellers (servers) to build custom business logic. Future support for modular facilitator components is planned.
Core Components Overview
For the X402 Protocol
- [
concepts]: Core traits and types used across the X402 Kit. - [
config]: Configuration types for defining resources and payment requirements. - [
transport]: Types and traits for defining X402 transport mechanisms and facilitator interactions. - [
types]: Common re-usable types for defining the X402 protocol.
For Network-Specific Implementations
- [
networks]: Network-specific implementations, e.g., EVM / SVM assets and addresses. - [
schemes]: Payment scheme implementations, e.g., Exact EVM / Exact SVM, and their signer logic.
Commonly-Used Utilities
- [
seller]: Utilities for building X402 sellers, including an Axum integration. - [
facilitator_client]: Utilities for building X402 facilitator clients.
Seller Guide
Configuring Payment Requirements
Resources
A [config::Resource] defines the details of what is being sold, including its URL, description, MIME type, and optional output schema.
use url;
use Resource;
use OutputSchema;
let resource = builder
.url
.description
.mime_type
// Make the endpoint discoverable with facilitators
.output_schema
.build;
See unit tests under [types::OutputSchema] in the GitHub repo for complex examples of defining input/output schemas.
Schemes
Choose a scheme for building payment requirements. For example, using the ExactEvm scheme:
use address;
use url;
use ;
#
Axum Integration
As a seller, you might be interested in Axum integration for building an X402-enabled server.
See [seller::axum::PaymentHandler] for more details.
use address;
use ;
use url;
use ;
async
# async
# async
The Seller Toolkit
The seller toolkit provides utilities for building custom payment handling logic outside of specific frameworks.
You might be interested in this if you are using a different web framework or have custom requirements.
See [seller::toolkit] for more details.
Extend X402 Kit As You Like
The main idea is you don't need to wait for the upstream library to support the network or asset in your case. Adding a new network, asset, or scheme is as simple as implementing a few traits.
However, we still recommend contributing back any useful implementations to the main repository to help grow the ecosystem!
New Networks
If you want support for new EVM / SVM networks or assets, just "declare" them anywhere in your codebase:
Custom EVM Network
use ;
;
// Now you can use MyCustomEvmNetwork with any scheme that supports EVM
Custom SVM Network
use ;
;
// Now you can use MyCustomSvmNetwork with any scheme that supports SVM
New Assets
Similarly, you can define custom assets for your networks:
Custom EVM Asset
use address;
use ;
;
;
// Now you can use MyCustomToken with ExactEvm or other EVM schemes
Custom SVM Asset
use pubkey;
use ;
;
;
// Now you can use MyCustomSvmToken with ExactSvm or other SVM schemes
Using Custom Assets with Schemes
Once you've defined your custom asset, you can use it with payment schemes just like built-in assets:
use alloy_primitives::address;
use url_macro::url;
use x402_kit::{
config::Resource,
networks::evm::{ExplicitEvmAsset, ExplicitEvmNetwork, EvmNetwork, EvmAsset, EvmAddress, Eip712Domain},
schemes::exact_evm::ExactEvm,
transport::PaymentRequirements,
};
// Define your custom network and asset
struct Polygon;
impl ExplicitEvmNetwork for Polygon {
const NETWORK: EvmNetwork = EvmNetwork {
name: "polygon",
chain_id: 137,
};
}
struct UsdcPolygon;
impl ExplicitEvmAsset for UsdcPolygon {
type Network = Polygon;
const ASSET: EvmAsset = EvmAsset {
address: EvmAddress(address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174")),
decimals: 6,
name: "USD Coin",
symbol: "USDC",
};
const EIP712_DOMAIN: Option<Eip712Domain> = Some(Eip712Domain {
name: "USD Coin",
version: "2",
});
}
# fn use_custom_asset() {
// Use it in payment requirements
let resource = Resource::builder()
.url(url!("https://example.com/api"))
.description("API access")
.mime_type("application/json")
.build();
let payment = ExactEvm::builder()
.asset(UsdcPolygon)
.amount(1000000) // 1 USDC
.pay_to(address!("0x3CB9B3bBfde8501f411bB69Ad3DC07908ED0dE20"))
.resource(resource)
.build();
let requirements: PaymentRequirements = payment.into();
# }
Defining New Network Families
If you want to define an entirely new family of networks (beyond EVM or SVM), you need to implement the core traits under [concepts]:
- [
concepts::NetworkFamily]: Represents a blockchain network family - [
concepts::Address]: Represents an address on that network
The Address type should also implement FromStr, Display, Copy, Debug, Clone, PartialEq, Eq, and Hash for proper serialization/deserialization and usage throughout the SDK.
Here's a complete example:
use ;
use ;
// Define your network family
// Define an address type for your network
;
// Define an asset type for your network
type MyAsset = ;
#
Once you have these core types defined, you can build schemes and payment requirements for your custom network family by implementing the [concepts::Scheme] trait.
Defining new Schemes
To define a new payment scheme, implement the Scheme trait from the concepts module. This involves specifying the associated network and payload types.
Just take how ExactSvmScheme is defined for example:
use ;
use Scheme;
use SvmNetwork;
;
Then you should make an entrypoint for sellers to convert the scheme into PaymentRequirements.
Note that PaymentRequirementsConfig is a type-safe builder for constructing PaymentRequirements from schemes.
use Builder;
use ;
use ;
use ExactSvmScheme;
use PaymentRequirements;