Skip to content

Commit 861784d

Browse files
committed
Refactor the api to support x402
1 parent 36742c1 commit 861784d

8 files changed

Lines changed: 781 additions & 1935 deletions

File tree

API.md

Lines changed: 148 additions & 308 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 85 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
[![Docker](https://img.shields.io/badge/docker-%230db7ed.svg?style=flat&logo=docker&logoColor=white)](https://hub.docker.com/r/zeropaydev/zeropay)
77
[![Rust](https://img.shields.io/badge/rust-%23000000.svg?style=flat&logo=rust&logoColor=white)](https://www.rust-lang.org)
88

9-
An open-source, self-hosted payment gateway for stablecoins and cryptocurrency payments.
9+
An open-source, self-hosted x402 payment facilitator for AI agents and autonomous systems.
1010

1111
[Features](#features)[Quick Start](#quick-start)[Documentation](#documentation)[Platform](#managed-platform)[Contributing](#contributing)
1212

@@ -16,161 +16,158 @@ An open-source, self-hosted payment gateway for stablecoins and cryptocurrency p
1616

1717
## Overview
1818

19-
ZeroPay is a lightweight, self-hosted payment gateway that enables merchants to accept stablecoin and cryptocurrency payments with minimal setup. Built with Rust for performance and reliability, it supports multiple EVM-compatible blockchains and provides real-time webhook notifications for payment events.
20-
21-
**New in v1.x:** ZeroPay now supports the **x402 Agent-to-Agent (A2A) payment protocol**, enabling AI agents and autonomous systems to programmatically discover, authorize, and settle payments using EIP-3009 gasless transfers.
19+
ZeroPay is a lightweight, self-hosted x402 payment facilitator built with Rust. It enables AI agents and autonomous systems to programmatically discover, authorize, and settle stablecoin payments using EIP-3009 gasless transfers — with no manual wallet management or blockchain infrastructure required.
2220

2321
### Key Features
2422

23+
- **x402 Protocol**: Full Agent-to-Agent (A2A) payment protocol for autonomous AI integrations
24+
- **Gasless Payments**: EIP-3009 `transferWithAuthorization` — payer signs off-chain, payee covers gas
25+
- **Instant Settlement**: No waiting for blockchain confirmation; payment settles in one transaction
26+
- **Secure**: EIP-712 typed signatures with time-bound authorization windows
27+
- **Discoverable**: Agents can browse available services via `/x402/discovery`
28+
- **Multi-Chain**: Ethereum, Polygon, Base, and other EVM-compatible networks
29+
- **Stablecoin Focused**: USDC, USDT, and other EIP-3009 compatible tokens
30+
- **EIP-8004 Support**: Optional agent reputation and identity registry integration
2531
- **Self-Hosted**: Full control over your payment infrastructure
26-
- **Multi-Chain Support**: Compatible with Ethereum, Polygon, BSC, and other EVM chains
27-
- **Stablecoin Focused**: Built for USDT, USDC, and other stablecoins
28-
- **Real-Time Notifications**: Webhook integration for payment events
29-
- **Automatic Settlement**: Funds automatically transferred to your wallet (minus commission)
30-
- **x402 Protocol Support**: Agent-to-Agent (A2A) payment protocol for AI-powered integrations
31-
- **Secure**: HMAC-based webhook authentication and EIP-712 signatures
32-
- **Easy Integration**: RESTful API with comprehensive documentation
33-
- **Docker Ready**: One-command deployment with Docker
32+
- **Docker Ready**: One-command deployment
3433

3534
## Quick Start
3635

3736
### Using Docker Compose (Recommended)
3837

39-
The easiest way to run ZeroPay with all dependencies:
40-
41-
1. **Configure your settings:**
42-
43-
Edit `docker-compose.yml` environment variables:
38+
1. **Configure your settings** in `docker-compose.yml`:
4439
```yaml
4540
environment:
4641
- MNEMONICS=your twelve or twenty four word mnemonic phrase
4742
- WALLET=0xYourWalletAddress
4843
- APIKEY=your-secure-api-key
49-
- WEBHOOK=https://your-webhook-url.com
5044
```
5145
52-
2. **Configure blockchain:**
53-
54-
Edit `config.toml` with your chain settings (RPC URL, tokens, etc.)
46+
2. **Configure blockchain** in `config.toml`:
47+
```toml
48+
[[chains]]
49+
chain_type = "evm"
50+
chain_name = "base-sepolia"
51+
latency = 1
52+
estimation = 12
53+
commission = 5
54+
commission_min = 50
55+
commission_max = 200
56+
admin = "0xYourAdminPrivateKey"
57+
rpc = "https://base-sepolia.g.alchemy.com/v2/YOUR-API-KEY"
58+
tokens = ["USDC:0xYourUSDCAddress:2"]
59+
```
60+
The `:2` suffix marks a token as x402-compatible (EIP-3009).
5561

5662
3. **Start all services:**
5763
```bash
5864
docker-compose up -d
5965
```
6066

61-
4. **Check logs:**
67+
4. **Verify x402 support:**
6268
```bash
63-
docker-compose logs -f zeropay
69+
curl "http://localhost:9000/x402/support?apikey=your-api-key"
6470
```
6571

6672
See [DEPLOYMENT.md](./DEPLOYMENT.md) for detailed setup instructions.
6773

6874
## Documentation
6975

70-
- **[Deployment Guide](./DEPLOYMENT.md)** - Complete setup instructions for Docker and source builds
71-
- **[API Reference](./API.md)** - REST API endpoints, webhook events, and usage examples
72-
- **[x402 Protocol Integration](./x402.md)** - Agent-to-Agent (A2A) payment protocol integration guide
73-
- **[AI Integration Guide](./docs/AI_INTEGRATION_GUIDE.md)** - Prompt and guide for AI agents to integrate with ZeroPay API
74-
- **[Configuration Guide](#configuration)** - Environment and chain configuration
75-
76-
## Managed Platform
76+
- **[Deployment Guide](./DEPLOYMENT.md)** - Complete setup for Docker and source builds
77+
- **[API Reference](./API.md)** - x402 REST API endpoints and usage examples
78+
- **[x402 Protocol Guide](./x402.md)** - Protocol overview and integration details
79+
- **[AI Integration Guide](./docs/AI_INTEGRATION_GUIDE.md)** - Complete guide for AI agents integrating with ZeroPay
7780

78-
For a hassle-free experience, use our managed platform at [zpaynow.com](https://zpaynow.com):
81+
## How x402 Works
7982

80-
**Benefits:**
81-
- No infrastructure management required
82-
- Automatic updates and security patches
83-
- Public payment UI for customers
84-
- Multiple chain support out of the box
85-
- Enterprise-grade reliability
86-
87-
**Setup:**
88-
1. Register your merchant account at [zpaynow.com](https://zpaynow.com)
89-
2. Use `https://api.zpaynow.com` as your API endpoint
90-
3. Start accepting payments immediately
83+
```
84+
┌─────────────────────────────────────────────────────┐
85+
│ AI Agent │
86+
│ │
87+
│ 1. GET /x402/requirements → discover payee addr │
88+
│ 2. Sign EIP-712 authorization off-chain │
89+
│ 3. POST /x402/payments → settle on-chain │
90+
│ 4. Receive tx hash + confirmation │
91+
└─────────────────────────────────────────────────────┘
92+
93+
94+
┌─────────────────────────────────────────────────────┐
95+
│ ZeroPay API │
96+
│ │
97+
│ /x402/requirements — payment requirements │
98+
│ /x402/payments — verify + settle │
99+
│ /x402/support — supported schemes │
100+
│ /x402/discovery — browse available services │
101+
└───────────────────────┬─────────────────────────────┘
102+
│ transferWithAuthorization
103+
104+
┌─────────────────────────────────────────────────────┐
105+
│ Blockchain (EVM) │
106+
│ EIP-3009 gasless token transfer │
107+
└─────────────────────────────────────────────────────┘
108+
```
91109
92-
**Note:** The platform charges a small commission for gas fees and hosting.
110+
**Payment flow:**
111+
1. Agent calls `GET /x402/requirements` with `customer` + `amount` → gets a payee address and accepted payment schemes
112+
2. Agent creates an EIP-712 signature authorizing the transfer (off-chain, gasless for payer)
113+
3. Agent calls `POST /x402/payments` with the signed authorization
114+
4. ZeroPay verifies the signature and executes `transferWithAuthorization` on-chain
115+
5. Returns transaction hash to the agent
93116
94117
## Architecture
95118
96119
```
97-
┌─────────────┐ ┌─────────────┐
98-
│ Client │ │ AI Agent │
99-
│ Application │ │ (x402) │
100-
└──────┬──────┘ └──────┬──────┘
101-
│ REST API │ x402 Protocol
102-
│ │ (EIP-3009)
103-
▼ ▼
104-
┌──────────────────────────────────┐
105-
│ ZeroPay API │
106-
│ /sessions /x402/* │◄──────┐
107-
└──────┬───────────────────────────┘ │
108-
│ │
109-
├───────────────────────────────────┤
110-
│ │
111-
▼ ▼
112-
┌──────────┐ ┌──────────┐
113-
│PostgreSQL│ │ Redis │
114-
└──────────┘ └──────────┘
115-
116-
│ Scanner + x402 Facilitator
117-
118-
┌─────────────────────────────────────┐
119-
│ Blockchain │
120-
│ (Ethereum, Polygon, Base, etc) │
121-
│ EIP-3009 transferWithAuthorization │
122-
└─────────────────────────────────────┘
120+
zeropay/
121+
├── api/ # REST API server (Axum)
122+
├── scanner/ # Chain scanner + x402 asset initialization
123+
├── x402/ # x402 protocol types, facilitator, client SDK
124+
├── config.toml # Chain and token configuration
125+
├── Dockerfile
126+
└── docker-compose.yml
123127
```
124128
125129
## Development
126130
127131
### Prerequisites
128132
129-
- Rust 1.75 or higher
133+
- Rust 1.75+
130134
- PostgreSQL 12+
131135
- Redis 6+
132136
133137
### Build from Source
134138
135139
```bash
136-
# Clone the repository
137-
git clone https://github.com/ZeroPayDev/zeropay.git
140+
git clone https://github.com/zpaynow/zeropay.git
138141
cd zeropay
139-
140-
# Build
141142
cargo build --release
142-
143-
# Run
144143
./target/release/api
145144
```
146145

147-
### Project Structure
146+
## Managed Platform
148147

149-
```
150-
zeropay/
151-
├── api/ # REST API server
152-
├── scanner/ # Blockchain scanner
153-
├── config.toml # Chain configuration
154-
├── Dockerfile # Container build file
155-
└── .env-template # Environment template
156-
```
148+
For a hassle-free experience, use our managed platform at [zpaynow.com](https://zpaynow.com):
149+
150+
- No infrastructure management required
151+
- Automatic updates and security patches
152+
- Multiple chain support out of the box
153+
- Enterprise-grade reliability
154+
155+
**Setup:** Register at [zpaynow.com](https://zpaynow.com) and use `https://api.zpaynow.com` as your API endpoint.
157156

158157
## Contributing
159158

160159
We welcome contributions!
161160

162161
### Reporting Vulnerabilities
163162

164-
If you discover a security vulnerability, please email [email protected] instead of using the issue tracker.
163+
Email [email protected] instead of using the issue tracker.
165164

166165
### Best Practices
167166

168167
- Never commit `.env` files or private keys
169168
- Use strong, randomly generated API keys
170-
- Verify webhook HMAC signatures
171169
- Keep dependencies updated
172170
- Use secure RPC endpoints
173-
- Enable firewall rules
174171

175172
## License
176173

api/src/api.rs

Lines changed: 5 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use crate::AppState;
22
use crate::error::{ApiError, Result};
3-
use crate::models::{Customer, Session, store_address_in_redis};
4-
use axum::extract::{Json, Path, Query, State};
5-
use chrono::NaiveDateTime;
6-
use serde::{Deserialize, Serialize};
3+
use crate::models::Customer;
4+
use axum::extract::{Json, Query, State};
5+
use serde::Deserialize;
76
use std::sync::Arc;
87
use x402::{
98
DiscoveryRequest, DiscoveryResponse, Payee, PaymentRequirementsResponse, SettlementResponse,
@@ -16,73 +15,15 @@ pub struct ApikeyAuth {
1615
}
1716

1817
#[derive(Deserialize)]
19-
pub struct CreateSession {
18+
pub struct PaymentRequest {
2019
customer: String,
2120
amount: i32,
2221
}
2322

24-
#[derive(Serialize)]
25-
pub struct SessionResponse {
26-
session_id: i32,
27-
customer: String,
28-
pay_eth: String,
29-
amount: i32,
30-
expired: NaiveDateTime,
31-
completed: bool,
32-
}
33-
34-
impl SessionResponse {
35-
fn new(customer: Customer, session: Session) -> SessionResponse {
36-
SessionResponse {
37-
session_id: session.id,
38-
customer: customer.account,
39-
pay_eth: customer.eth,
40-
amount: session.amount,
41-
expired: session.expired_at,
42-
completed: session.deposit.is_some(),
43-
}
44-
}
45-
}
46-
47-
pub async fn create_session(
48-
State(app): State<Arc<AppState>>,
49-
Query(auth): Query<ApikeyAuth>,
50-
Json(data): Json<CreateSession>,
51-
) -> Result<Json<SessionResponse>> {
52-
if auth.apikey != app.apikey {
53-
return Err(ApiError::UserAuth);
54-
}
55-
56-
let customer = Customer::get_or_insert(data.customer, &app.db, &app.mnemonics).await?;
57-
let session = Session::insert(customer.id, data.amount, &app.db).await?;
58-
59-
// save address to redis cache
60-
store_address_in_redis(&app.redis, &customer.eth, customer.id)
61-
.await
62-
.map_err(|_| ApiError::Internal)?;
63-
64-
Ok(Json(SessionResponse::new(customer, session)))
65-
}
66-
67-
pub async fn get_session(
68-
State(app): State<Arc<AppState>>,
69-
Query(auth): Query<ApikeyAuth>,
70-
Path(id): Path<i32>,
71-
) -> Result<Json<SessionResponse>> {
72-
if auth.apikey != app.apikey {
73-
return Err(ApiError::UserAuth);
74-
}
75-
76-
let session = Session::get(id, &app.db).await?;
77-
let customer = Customer::get(session.customer, &app.db).await?;
78-
79-
Ok(Json(SessionResponse::new(customer, session)))
80-
}
81-
8223
pub async fn x402_requirements(
8324
State(app): State<Arc<AppState>>,
8425
Query(auth): Query<ApikeyAuth>,
85-
Json(data): Json<CreateSession>,
26+
Json(data): Json<PaymentRequest>,
8627
) -> Result<Json<PaymentRequirementsResponse>> {
8728
if auth.apikey != app.apikey {
8829
return Err(ApiError::UserAuth);

api/src/main.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ struct Command {
7575
#[derive(Clone)]
7676
struct AppState {
7777
db: PgPool,
78-
redis: RedisClient,
7978
mnemonics: String,
8079
apikey: String,
8180
facilitator: Arc<Facilitator>,
@@ -167,7 +166,6 @@ async fn main() {
167166
let app_state = Arc::new(AppState {
168167
_sender,
169168
db,
170-
redis,
171169
facilitator: Arc::new(facilitator),
172170
apikey: args.apikey,
173171
mnemonics: args.mnemonics,
@@ -179,8 +177,6 @@ async fn main() {
179177
.allow_headers(Any);
180178

181179
let router = Router::new()
182-
.route("/sessions", post(api::create_session))
183-
.route("/sessions/{id}", get(api::get_session))
184180
.route("/x402/requirements", get(api::x402_requirements))
185181
.route("/x402/payments", post(api::x402_payment))
186182
.route("/x402/support", get(api::x402_support))

api/src/models/mod.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -132,19 +132,6 @@ impl scanner::ScannerStorage for Storage {
132132
}
133133
}
134134

135-
// Store customer address in Redis for fast lookup during scanning
136-
pub async fn store_address_in_redis(redis: &RedisClient, eth: &str, id: i32) -> Result<()> {
137-
let mut conn = redis.get_multiplexed_async_connection().await?;
138-
139-
let key = format!("zpc:{}", eth);
140-
141-
// Set expiration to 30 days
142-
let _: () = conn.set_ex(&key, id, 30 * 24 * 3600).await?;
143-
144-
debug!("Stored customer address in Redis: {}", eth);
145-
Ok(())
146-
}
147-
148135
// Store tranaction in Redis for avoid duplicate
149136
async fn store_transaction_in_redis(redis: &RedisClient, tx: &str) -> Result<()> {
150137
let mut conn = redis.get_multiplexed_async_connection().await?;

0 commit comments

Comments
 (0)