mppx-stableyard
March 19, 2026 · View on GitHub
A new payment method for MPP that lets any agent pay from any chain, and any merchant receive on any chain — powered by Stableyard.
tempo() → Tempo chain only
stripe() → cards only
stableyard() → 5 chains live (+ Tempo, Movement soon) + fiat to bank
The Problem
MPP launched with two payment methods:
tempo()— works only on Tempo chainstripe()— works only with cards
If an agent has USDC on Base and the server only accepts tempo(), the agent can't pay. Wrong chain. Stuck.
The Solution
stableyard() — a third payment method that plugs into mppx:
import { stableyard } from 'mppx-stableyard/server'
const mppx = Mppx.create({
methods: [
tempo.charge({ ... }), // Tempo chain
stableyard({ // ANY chain
apiKey: 'sy_secret_...',
destination: 'merchant@stableyard',
}),
],
})
One line added. The server now accepts payments from Base, Arbitrum, Polygon, Ethereum, and Solana — with Tempo and Movement coming soon.
How It Works
Agent calls API
↓
402 Payment Required
WWW-Authenticate: Payment method="stableyard"
{ amount: "100000", currency: "USDC", destination: "merchant@stableyard" }
↓
Agent (mppx-stableyard client):
1. POST /v2/sessions { amount, destination, sourceChain: "base" }
→ Gets deposit address on Base (inline, one call)
2. Sends 0.10 USDC to deposit address
3. POST /submit-tx { txHash }
→ Stableyard detects payment
4. Polls → settled (9 seconds)
↓
Agent retries with credential { sessionId }
↓
Server calls POST /v2/sessions/:id/verify
→ { verified: true }
↓
200 OK + data + Payment-Receipt
Proved with Real Money
Session: ses_b6afc57b153e2ae1f8fb1025
Tx: 0xbeaf32d41f8f7573e02653a79e02bf56a73ae667dca203acb9e5c181116914a9
Amount: 0.10 USDC on Base
Submit tx: → status: pending
Poll: → settled in 9 seconds
Verify: → { verified: true }
Install
npm i mppx-stableyard mppx
Server
Accept MPP payments via Stableyard. Settle to any chain or fiat.
import { Mppx, tempo } from 'mppx/server'
import { stableyard } from 'mppx-stableyard/server'
const mppx = Mppx.create({
methods: [
tempo.charge({ currency: USDC, recipient: '0x...' }),
stableyard({
apiKey: 'sy_secret_...',
destination: 'merchant@stableyard',
}),
],
})
app.get('/api/data', async (req) => {
const result = await mppx['stableyard/charge']({
amount: '100000',
description: 'Premium data',
})(req)
if (result.status === 402) return result.challenge
return result.withReceipt(Response.json({ data: '...' }))
})
The 402 response includes a WWW-Authenticate: Payment method="stableyard" challenge. The server verifies payment via Stableyard's /v2/sessions/:id/verify endpoint.
Client
Agent automatically handles 402 → pay via Stableyard → retry.
import { Mppx } from 'mppx/client'
import { stableyard } from 'mppx-stableyard/client'
Mppx.create({
methods: [
stableyard({
apiKey: 'sy_secret_...',
chain: 'base',
sendPayment: async (deposit) => {
// Send USDC to deposit address
return await sendERC20(deposit.address, deposit.amount.raw)
},
}),
],
})
// fetch auto-handles 402 → pay via Stableyard → retry
const res = await fetch('https://api.example.com/data')
What stableyard() Adds to MPP
| Feature | tempo() | stableyard() |
|---|---|---|
| Tempo chain | Yes | Yes (coming soon) |
| Base, Arbitrum, Polygon, Ethereum | Yes | |
| Solana | Yes | |
| Movement | Coming soon | |
| Fiat settlement (bank) | Yes | |
| Named identity (@stableyard) | Yes | |
| Gasless payments (vault) | Yes | |
| Merchant dashboard | Yes | |
| Cross-chain routing | Yes |
Supported Chains
| Chain | Settlement Time |
|---|---|
| Base | ~1s (same-chain) |
| Arbitrum | ~15s |
| Polygon | ~15s |
| Ethereum | ~15s |
| Solana | ~22s |
| Tempo | Coming soon |
| Movement | Coming soon |
Architecture
MPP Protocol
|
+-------------+-------------+
| | |
tempo() stripe() stableyard()
Tempo chain Cards Any chain -> Any chain
Powered by Stableyard
|
|-- 5 chains live (+ Tempo, Movement soon)
|-- Gasyard cross-chain routing
|-- Gasless vault payments
|-- Fiat settlement (KYC)
+-- x402+ backward compatible
Stableyard sits alongside Tempo and Stripe as a payment rail in MPP. Not competing — extending.
What's Inside
mppx-stableyard/
src/method.ts — Method.from() definition (stableyard/charge)
src/server.ts — Method.toServer() — generates 402 challenges, verifies via Stableyard API
src/client.ts — Method.toClient() — creates session, gets deposit addr, pays, polls
src/stableyard-api.ts — Stableyard API client (sessions, quote, verify, submit-tx, poll)
demo/server.ts — Working MPP server with tempo() + stableyard() methods
demo/agent.ts — Agent that auto-pays via Stableyard
Configuration
Server
stableyard({
apiKey: 'sy_secret_...', // Stableyard API key
destination: 'merchant@stableyard', // Where payments settle
currency: 'USDC', // Default: 'USDC'
decimals: 6, // Default: 6
verifyTimeoutMs: 30000, // Default: 30s
})
Client
stableyard({
apiKey: 'sy_secret_...', // Stableyard API key
chain: 'base', // Agent's payment chain
settlementTimeoutMs: 60000, // Default: 60s
sendPayment: async (deposit) => { // Your wallet logic
return txHash
},
})
Demo
git clone https://github.com/stableyardfi/mppx-stableyard
cd mppx-stableyard
npm install
# Start server
cp demo/.env.example .env
# Edit .env with your Stableyard keys
npx tsx demo/server.ts
# Test 402 response
curl -D- http://localhost:3000/api/market-data
# Run agent
npx tsx demo/agent.ts
Also Built: Stableyard MPP Service Registry Entry
PR ready to add Stableyard as a service in the MPP service directory (alongside Alchemy, OpenAI, fal.ai). 9 endpoints covering sessions, network, accounts, and deposits.
Links
- Stableyard — Cross-chain stablecoin payments
- MPP — Machine Payments Protocol
- mppx — TypeScript SDK for MPP
- x402+ — Stableyard's x402 protocol implementation
- Stableyard API — OpenAPI spec
License
MIT