Documentation Index Fetch the complete documentation index at: https://mintlify.com/Crossmint/crossmint-agentic-finance/llms.txt
Use this file to discover all available pages before exploring further.
Ping Crossmint Demo
The Ping Crossmint demo is a complete full-stack implementation showing how to integrate Crossmint smart wallets with the x402 payment protocol. It includes both a React client with UI and an Express server with detailed logging.
Overview
This demo demonstrates:
React Client : Full UI for wallet creation, deployment, and payment execution
Express Server : Protected endpoints with x402 middleware and facilitator integration
Smart Wallets : Crossmint wallet integration with two signer types (API Key and Email OTP)
Payment Flow : Complete end-to-end payment from user approval to settlement
Key Features:
Crossmint smart wallet creation and management
Two authentication methods: API Key (server-side) and Email OTP (client-side)
Wallet deployment with ERC-6492 pre-deployment support
Balance checking (ETH and USDC)
Payment approval UI with detailed transaction info
Comprehensive logging and debugging tools
Prerequisites
Development Environment
Node.js 18.17.0 or higher
npm 9.0.0 or higher
Git
Crossmint Account
Create account at https://www.crossmint.com/
Navigate to Developer Console → API Keys
Generate two API keys:
Server API Key (format: sk_staging_...) - For API key signer
Client API Key (format: ck_staging_...) - For Email OTP signer
Important: Save keys securely - never commit to git
Testnet Tokens
ETH for gas fees (0.01 ETH minimum):
USDC for payments (1 USDC minimum):
Setup
1. Clone and Install
cd ping-crossmint
# Install server dependencies
cd server
npm install
# Install client dependencies
cd ../client
npm install
PORT = 3100
PAY_TO = 0x233521928665E16de96267D17313571687eC41b7
NETWORK = base-sepolia
Configuration Options:
PORT - Server listen port (default: 3100)
PAY_TO - Payment recipient address (use your own to receive testnet USDC)
NETWORK - Payment settlement network (default: base-sepolia)
Start the server:
Expected Output:
Server running on http://localhost:3100
Network: base-sepolia
Payment recipient: 0x2335...c41b7
Protected endpoints:
GET /ping -> $0.001 USDC
3. Start Client
Expected Output:
VITE ready in 234 ms
➜ Local: http://localhost:5174/
4. Verify Setup
# Test server health
curl http://localhost:3100/health
# Test 402 response
curl -H "Accept: application/vnd.x402+json" http://localhost:3100/ping
# Open client in browser
open http://localhost:5174
Server Implementation
The server uses x402-express middleware with facilitator integration:
import express from "express" ;
import cors from "cors" ;
import { paymentMiddleware } from "x402-express" ;
import { facilitator } from "@coinbase/x402" ;
import * as dotenv from "dotenv" ;
dotenv . config ();
const app = express ();
const port = process . env . PORT ? Number ( process . env . PORT ) : 3100 ;
const payTo = process . env . PAY_TO || "0x233521928665E16de96267D17313571687eC41b7" ;
const network = process . env . NETWORK || "base-sepolia" ;
// CORS configuration for client
app . use ( cors ({
origin: [ "http://localhost:5173" , "http://localhost:5174" ],
credentials: true ,
}));
// Apply payment middleware with facilitator
app . use ( paymentMiddleware ( payTo , {
"GET /ping" : { price: "$0.001" , network }
}, facilitator ));
// Health check endpoint (no payment required)
app . get ( "/health" , ( _req , res ) => {
res . json ({
status: "healthy" ,
timestamp: new Date (). toISOString (),
uptime: process . uptime (),
port ,
network ,
payTo: payTo . substring ( 0 , 10 ) + "..." ,
endpoints: { ping: "$0.001" }
});
});
// Protected ping endpoint
app . get ( "/ping" , ( _req , res ) => {
res . json ({ message: "pong" });
});
app . listen ( port , () => {
console . log ( `Server listening on http://localhost: ${ port } ` );
});
Debug Logging
The server includes comprehensive logging middleware:
app . use (( req , res , next ) => {
const xpay = req . header ( "X-PAYMENT" );
console . log ( `[REQ] ${ req . method } ${ req . path } xpay= ${ xpay ? `len: ${ xpay . length } ` : "none" } ` );
if ( xpay ) {
const decoded = exact . evm . decodePayment ( xpay );
console . log ( `[X-PAYMENT] network= ${ decoded . network } ` );
console . log ( `[X-PAYMENT] authorization.from: ${ decoded . payload . authorization . from } ` );
console . log ( `[X-PAYMENT] authorization.to: ${ decoded . payload . authorization . to } ` );
console . log ( `[X-PAYMENT] authorization.value: ${ decoded . payload . authorization . value } ` );
}
res . on ( "finish" , () => {
console . log ( `[RES] ${ req . method } ${ req . path } -> ${ res . statusCode } ` );
});
next ();
});
Client Implementation
Project Structure
client/
├── src/
│ ├── components/
│ │ ├── WalletDisplay.tsx # Wallet address, balances, status
│ │ ├── PaymentApproval.tsx # Payment confirmation dialog
│ │ ├── ServerStatus.tsx # Server health indicator
│ │ └── ActivityLogs.tsx # Event logging display
│ ├── hooks/
│ │ ├── useCrossmintWallet.ts # Wallet init, deployment, OTP
│ │ ├── useX402Payments.ts # Payment request/execution
│ │ └── useWalletBalances.ts # ETH/USDC balance queries
│ ├── utils/
│ │ ├── x402Adapter.ts # Crossmint → x402 signer adapter
│ │ └── walletGuards.ts # Deployment checks, utilities
│ ├── constants/
│ │ └── chains.ts # Chain configs, RPC URLs, USDC
│ └── types/ # TypeScript definitions
└── package.json
Key Integration: x402 Adapter
The critical integration point between Crossmint SDK and x402:
client/src/utils/x402Adapter.ts
import type { Signer } from "x402" ;
import type { EVMSmartWallet } from "@crossmint/wallets-sdk" ;
export function createX402Signer ( wallet : EVMSmartWallet ) : Signer {
return {
async signTypedData ( typedData ) {
const signature = await wallet . signTypedData ( typedData );
return signature as `0x ${ string } ` ;
},
address: wallet . address as `0x ${ string } ` ,
chainId: wallet . chain . id
};
}
This adapter:
Converts Crossmint wallet to x402 Signer interface
Preserves ERC-6492 pre-deployment signatures
Handles EIP-1271 deployed wallet signatures
Maintains compatibility with facilitator
Usage Guide
1. Initialize Wallet
API Key Signer (Simpler)
Open http://localhost:5174
Signer Type : Select “API Key”
API Key : Enter your sk_staging_... key
Email : your-email@example.com
Chain : base-sepolia
Server URL : http://localhost:3100
Click “Initialize Wallet”
Success Output:
✅ Crossmint wallet created!
📍 Wallet address: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
🏗️ Wallet status: pre-deployed
Email OTP Signer (More Secure)
Signer Type : Select “Email OTP”
API Key : Enter your ck_staging_... key
Email : Enter accessible email address
Click “Initialize Wallet”
Click “Send OTP”
Check email for 6-digit code
Enter code and click “Verify OTP”
Success Output:
✅ OTP verified successfully!
✅ Crossmint wallet created!
📍 Wallet address: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
2. Fund Wallet
Copy the wallet address and fund with testnet tokens:
# Get Base Sepolia ETH
# Visit: https://www.alchemy.com/faucets/base-sepolia
# Paste: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
# Wait 30-60 seconds
# Get Base Sepolia USDC
# Visit: https://faucet.circle.com/
# Select: Base Sepolia
# Paste: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
# Wait 30-60 seconds
Verify balances in UI:
💰 ETH: 0.1000
💰 USDC: 10.0000
3. Deploy Wallet (Optional but Recommended)
Pre-deployed wallets work for signature verification but may fail at settlement.
Click “Deploy Wallet”
Wait 30-60 seconds for confirmation
Status changes to “deployed”
Expected Output:
🚀 Deploying wallet...
📝 Transaction hash: 0x1a2b3c4d...
✅ Wallet deployed successfully!
Cost: ~0.001 ETH (Base Sepolia gas)
4. Make Payment Request
Click “Make Ping”
Server returns 402 Payment Required
UI displays:
💳 Payment Required
Amount: 0.001000 USDC
Recipient: 0x2335...c41b7
Network: base-sepolia
5. Approve and Execute Payment
Review payment details
Click “Approve Payment”
Wallet signs authorization (automatic)
Client retries with X-PAYMENT header
Success Output:
✅ Payment executed successfully!
📨 Server response: {"message":"pong"}
🎉 X402 + Crossmint payment complete!
Payment Flow
Initial Request
Client requests /ping without payment header
402 Response
Server returns payment requirements in JSON format
Sign Authorization
Crossmint wallet signs EIP-712 typed data
Retry with Payment
Client includes signed payment in X-PAYMENT header
Verify Signature
Server verifies signature off-chain (ERC-6492 or EIP-1271)
Settlement
Facilitator attempts on-chain USDC transfer
Return Content
Server returns {"message":"pong"} on success
Pre-deployed Wallet (ERC-6492)
Format: 0x<signature><factory-data>6492649264926492...
Length: ~854 characters
Purpose: Signature verification before contract deployment
How it works:
Signature includes deployment parameters
Can be verified off-chain without deployed contract
Facilitator may fail settlement (requires deployment)
Demonstrates successful signature verification
Deployed Wallet (EIP-1271)
Format: 0x<signature-data>
Length: ~174 characters
Purpose: Contract validates via isValidSignature()
How it works:
Smart contract implements EIP-1271 interface
On-chain signature validation
Full settlement support
Production-ready pattern
API Reference
GET /health
Health check endpoint - no payment required.
Request:
curl http://localhost:3100/health
Response:
{
"status" : "healthy" ,
"timestamp" : "2024-10-02T14:32:15.234Z" ,
"uptime" : 3456.789 ,
"port" : 3100 ,
"network" : "base-sepolia" ,
"payTo" : "0x233521928..." ,
"endpoints" : {
"ping" : "$0.001"
}
}
GET /ping
Protected endpoint requiring $0.001 USDC payment.
Request (without payment):
curl -H "Accept: application/vnd.x402+json" http://localhost:3100/ping
Response (402):
{
"accepts" : [{
"payTo" : "0x233521928665E16de96267D17313571687eC41b7" ,
"network" : "base-sepolia" ,
"asset" : "0x036CbD53842c5426634e7929541eC2318f3dCF7e" ,
"maxAmountRequired" : "1000"
}],
"version" : "2"
}
Request (with payment):
curl -H "X-PAYMENT: <base64>" http://localhost:3100/ping
Response (200):
Dependencies
Client
{
"dependencies" : {
"@crossmint/wallets-sdk" : "latest" ,
"@crossmint/client-sdk-react-ui" : "latest" ,
"x402-axios" : "^0.6.1" ,
"viem" : "^2.37.6" ,
"axios" : "^1.12.2" ,
"react" : "^18.2.0"
}
}
Server
{
"dependencies" : {
"express" : "^5.1.0" ,
"x402-express" : "^0.6.1" ,
"@coinbase/x402" : "^0.6.1" ,
"cors" : "^2.8.5" ,
"dotenv" : "^17.2.2"
}
}
Next Steps
Solana Demo Implement paywalls on Solana blockchain
Weather Demo Protect dynamic endpoints with query parameters
Crossmint Docs Deep dive into Crossmint Wallets SDK
x402 Protocol Read the full x402 specification
Troubleshooting
Wallet Initialization Fails
Error: “Invalid API key”
Solution: Use sk_staging_... for API Key signer, ck_staging_... for Email OTP signer.
Payment Settlement Fails
Message: “Payment verification completed, settlement had issues”
Status: Expected with pre-deployed wallets. Signature verification works, on-chain settlement requires deployment.
Solution: Deploy wallet first for full end-to-end payment flow.
Port Already in Use
Error: EADDRINUSE
Solution:
# Find process
lsof -i :3100
# Kill it
kill -9 < PI D >
# Or use different port
PORT = 3200 npm run dev