A fully-functional x402 V1-compliant payment facilitator for the Stellar blockchain.
This is a complete implementation of the x402 protocol on Stellar, fully compatible with the Coinbase x402 specification.
x402 is an open payment protocol that leverages the HTTP 402 "Payment Required" status code to enable seamless, internet-native payments. This implementation brings x402 to Stellar.
# Install dependencies
pnpm install
# Terminal 1: Start Redis (required for replay protection)
docker run -d -p 6379:6379 redis
# Terminal 2: Start the facilitator server
pnpm --filter facilitator dev
# Terminal 3: Start the demo app
pnpm --filter demo dev
# Open http://localhost:3000
# Connect your Freighter wallet and click "Pay to Unlock"1. User clicks "Pay to Unlock"
↓
2. GET /api/content → HTTP 402 + payment requirements
↓
3. User connects Freighter wallet
↓
4. App builds Stellar transaction
↓
5. User signs in Freighter popup
↓
6. App sends X-PAYMENT header with signed transaction
↓
7. Facilitator /verify → validates the transaction
↓
8. Facilitator /settle → submits to Stellar testnet
↓
9. Server returns 200 + content + X-PAYMENT-RESPONSE header
↓
10. Content unlocked! 🎉
This implementation follows the Coinbase x402 specification:
| Requirement | Status |
|---|---|
| 402 Response Format | ✅ |
| X-PAYMENT Header | ✅ |
| X-PAYMENT-RESPONSE Header | ✅ |
| Facilitator /verify | ✅ |
| Facilitator /settle | ✅ |
| Facilitator /supported | ✅ |
| Base64 Encoding | ✅ |
| XDR Validation | ✅ |
| Replay Protection | ✅ |
| Settlement Idempotency | ✅ |
| Fee Sponsorship (Fee-bump) | ✅ |
See COMPATIBILITY.md for full details.
stellar-x402-facilitator/
├── packages/
│ └── facilitator/ # x402 Facilitator server
│ ├── src/
│ │ ├── index.ts # Express server (port 4022)
│ │ ├── types.ts # x402 TypeScript types
│ │ ├── routes/
│ │ │ ├── verify.ts # POST /verify
│ │ │ └── settle.ts # POST /settle
│ │ ├── stellar/
│ │ │ ├── verify.ts # Stellar XDR verification
│ │ │ └── settle.ts # Stellar settlement + fee-bump
│ │ └── storage/
│ │ ├── redis.ts # Redis client
│ │ └── replay-store.ts # Replay protection & caching
│ └── package.json
├── apps/
│ └── demo/ # Next.js demo app
│ ├── app/
│ │ ├── page.tsx # Pay-to-view UI with Freighter
│ │ └── api/content/ # Protected endpoint (returns 402)
│ └── lib/
│ └── x402.ts # Client x402 helpers
├── COMPATIBILITY.md # x402 spec compliance details
└── README.md
Health check endpoint.
List supported (scheme, network) combinations.
// Response (per x402 spec)
{
"kinds": [
{ "x402Version": 1, "scheme": "exact", "network": "stellar-testnet" }
]
}Verify a payment authorization.
// Request
{
"x402Version": 1,
"paymentHeader": "<raw X-PAYMENT header string (base64)>",
"paymentRequirements": {
"scheme": "exact",
"network": "stellar-testnet",
"maxAmountRequired": "100000",
"asset": "C...",
"payTo": "G..."
}
}
// Response (per x402 spec)
{
"isValid": true,
"payer": "GABC..."
}
// Error Response
{
"isValid": false,
"invalidReason": "Insufficient amount",
"payer": "GABC..."
}Execute a verified payment on the Stellar network.
// Request (same as /verify)
{
"x402Version": 1,
"paymentHeader": "<raw X-PAYMENT header string (base64)>",
"paymentRequirements": { ... }
}
// Response (per x402 spec)
{
"success": true,
"payer": "GABC...",
"transaction": "abc123def456...",
"network": "stellar-testnet"
}
// Error Response
{
"success": false,
"errorReason": "Transaction failed",
"payer": "GABC...",
"transaction": "",
"network": "stellar-testnet"
}Note: The request supports both
paymentHeader(base64 string) andpaymentPayload(JSON object) formats for compatibility with different x402 clients.
- Request:
X-PAYMENT: <base64 encoded PaymentPayload> - Response:
X-PAYMENT-RESPONSE: <base64 encoded SettlementResponse>
- Install Freighter browser extension
- Switch to Testnet in Freighter settings
- Fund with testnet XLM:
https://friendbot.stellar.org?addr=YOUR_PUBLIC_KEY
Copy the example environment file and customize:
cp packages/facilitator/env.example.local .envKey settings:
# Server port
PORT=4022
# Redis URL (required for replay protection)
REDIS_URL=redis://localhost:6379
# Fee sponsorship: set this to pay user fees via fee-bump
# Generate at: https://laboratory.stellar.org/#account-creator?network=test
FACILITATOR_SECRET_KEY=S...
# Your Stellar address that receives payments
PAY_TO_ADDRESS=G...
# Asset: "native" for XLM, or contract address for tokens
ASSET_CONTRACT=native# Run unit and integration tests
pnpm --filter facilitator test
# Test 402 response
curl http://localhost:3000/api/content
# → HTTP 402 + payment requirements JSON
# Test facilitator health
curl http://localhost:4022/health
# → {"status":"ok","service":"x402-stellar-facilitator"}
# Test supported schemes
curl http://localhost:4022/supported
# → {"kinds":[{"x402Version":1,"scheme":"exact","network":"stellar-testnet"}]}| Feature | Status | Description |
|---|---|---|
| XDR Validation | ✅ | Parses signed transactions to verify payment details |
| Replay Protection | ✅ | Redis-backed, prevents duplicate payments |
| Settlement Idempotency | ✅ | Same transaction returns cached result |
| Fee Sponsorship | ✅ | Optional fee-bump via FACILITATOR_SECRET_KEY |
| USDC Soroban Token | ⏳ | Using native XLM for now |
- USDC Soroban Token support
- Stellar mainnet deployment
- SDK package (
@stellar/x402-sdk)
MIT