sequenceDiagram
participant User as User<br/>(Has: Wallet, xUSDC)<br/>(Knows: Sign messages)
participant Client as Client App<br/>(x402 SDK)
participant Server as Resource Server<br/>(Has: Solana wallet)<br/>(Knows: Basic web)
participant Facilitator as Facilitator<br/>(Has: Permanent Delegate)<br/>(Knows: Solana txs)
participant Solana as Solana<br/>(xUSDC Program)
Note over User,Solana: ONE-TIME SETUP (Once per user lifetime)
User->>Solana: Deposit USDC, get xUSDC
Note over User: User now has xUSDC in wallet
Note over User,Solana: PAYMENT FLOW (Every request)
%% Step 1: Initial Request
User->>Client: "Get premium content"
Client->>Server: GET /premium-article
Server-->>Client: 402 Payment Required<br/>X-PAYMENT-REQUIRED: {<br/> payTo: "server_solana_wallet",<br/> amount: "0.001 xUSDC",<br/> nonce: "abc123"<br/>}
%% Step 2: Client creates signature
Note over Client: Client SDK handles all complexity
Client->>User: Sign message (NOT transaction):<br/>"Pay 0.001 xUSDC to server_wallet<br/>for nonce abc123"
User-->>Client: Ed25519 signature
%% Step 3: Retry with payment
Client->>Server: GET /premium-article<br/>X-PAYMENT: base64(signature + params)
%% Step 4: Server settlement
Server->>Facilitator: POST /settle<br/>{signature, from, to, amount, nonce}
Note over Facilitator: Facilitator verifies signature
Facilitator->>Solana: Transfer using Permanent Delegate<br/>(No user signature needed!)
Solana-->>Facilitator: Transfer complete
Facilitator-->>Server: Settlement confirmed + tx_hash
Server-->>Client: 200 OK + Article content<br/>X-PAYMENT-RESPONSE: {tx_hash}
Required Knowledge:
✓ How to sign messages with wallet
✓ How to hold xUSDC tokens
✗ NO knowledge of Solana transactions
✗ NO knowledge of gas/fees
✗ NO knowledge of PDAs, programs, etc.
User Experience:
1. One-time: "Deposit USDC to get xUSDC" (like depositing to PayPal)
2. Ongoing: Click "Pay" → Sign message → Done
Required Knowledge:
✓ How to generate payment requirements (amount, wallet address)
✓ How to call facilitator API
✗ NO Solana transaction knowledge
✗ NO program interaction
✗ NO key management beyond having an address
Server Experience:
1. Return 402 with payment requirements
2. Receive payment header
3. Call facilitator.settle(payment_data)
4. Serve content when confirmed
Required Knowledge:
✓ Solana transaction construction
✓ Program interactions
✓ Permanent delegate usage
✓ Ed25519 signature verification
✓ RPC node management
✓ Error handling & retries
Facilitator Responsibilities:
1. Verify signatures match payment intent
2. Construct & submit Solana transactions
3. Handle all blockchain complexity
4. Provide simple API to servers
User Flow:
1. Server creates Solana transaction
2. User reviews complex transaction
3. User signs full transaction
4. Facilitator adds fee payer signature
5. Submit to Solana
Problems:
❌ Users see scary Solana transaction details
❌ Servers must understand Solana transactions
❌ Security risk - users signing arbitrary txs
❌ Cloudflare/Vercel won't implement this
❌ Transaction can be modified after signing
❌ Complex error handling
User Flow:
1. User signs simple message: "Pay X to Y"
2. Done.
Advantages:
✅ Users sign human-readable messages
✅ Servers need zero blockchain knowledge
✅ Cloudflare/Vercel can implement easily
✅ Same UX as EIP-3009 on Ethereum
✅ Signature intent is immutable
✅ Facilitator handles all complexity
// User signs exactly this:
{
"action": "pay",
"from": "user_wallet",
"to": "server_wallet",
"amount": "0.001",
"asset": "xUSDC",
"nonce": "abc123",
"validUntil": 1234567890
}
// Intent is crystal clear
// Cannot be modified
// Easy to audit// User signs complex transaction:
{
"instructions": [{
"programId": "TokenkegQ...",
"keys": [
{"pubkey": "...", "isSigner": true, "isWritable": true},
{"pubkey": "...", "isSigner": false, "isWritable": true},
// ... 8 more accounts
],
"data": "0x0a0b0c0d..." // Opaque bytes
}],
"recentBlockhash": "...",
"signatures": [...]
}
// What is this doing?
// Can instructions be added?
// Hard to auditWith Message Signing:
// Simple to implement
function handlePayment(paymentHeader) {
const { signature, params } = decode(paymentHeader);
// Just forward to facilitator
return fetch('facilitator.com/settle', {
method: 'POST',
body: JSON.stringify({ signature, ...params })
});
}With Transaction Signing:
// Complex and risky
function handlePayment(signedTx) {
// Must understand Solana transactions
// Must validate transaction safety
// Must handle partial signatures
// Must deal with transaction malleability
// Platform providers won't do this!
}The Permanent Delegate approach maintains the elegant simplicity of x402:
- Users: "I authorize payment of X"
- Servers: "I need payment of X"
- Facilitator: "I'll handle the blockchain stuff"
This separation of concerns is why x402 works so well on EVM, and why the permanent delegate approach is the right path for Solana.