Unified payment execution layer for autonomous agents on Stellar
Three payment protocols exist on Stellar for agent-to-service transactions: x402 (Coinbase), MPP charge (Stripe/Stellar), and MPP session channels (stellar-experimental). Each has a separate SDK, a separate integration path, and no discovery mechanism. The one-way-channel Soroban contract is unaudited and has no safe integration path. Every agent team hardcodes payment logic per endpoint.
import { RouteDockClient } from '@routedock/routedock'
const client = new RouteDockClient({ wallet, network: 'testnet' })
const result = await client.pay('https://provider.example.com/price')
// result.mode → 'x402' | 'mpp-charge' | 'mpp-session' (selected automatically)One SDK. One function call. The mode is selected from the provider's routedock.json manifest. The agent writes nothing else.
graph LR
Agent --> ModeRouter
ModeRouter --> x402Client
ModeRouter --> MppChargeClient
ModeRouter --> MppSessionClient
x402Client -->|mainnet| OZFacilitator["OZ Facilitator"]
x402Client -->|testnet| LocalFacilitator["Local Facilitator"]
OZFacilitator --> Stellar
LocalFacilitator --> Stellar
MppChargeClient --> StellarSAC["Stellar SAC transfer"]
StellarSAC --> Stellar
MppSessionClient --> ChannelContract["one-way-channel\nSoroban contract"]
ChannelContract --> Stellar
x402Client --> ProviderA["Provider A\n/price"]
MppChargeClient --> ProviderA
MppSessionClient --> ProviderB["Provider B\n/stream/orderbook"]
All produced by a single autonomous agent run against two live provider services. No mocks.
| Type | Tx Hash | Explorer |
|---|---|---|
| x402 settlement | 5f603387807faacdc02c71efb74b26091b1be67740f74dfd581d23d643e2db64 |
view |
| Channel open (deploy) | 6ceba32ba2cfd7f3145090c2e6f741db65ae4e4116f3204f2c3173b5266b98ff |
view |
| Channel close (50 vouchers settled) | 234dcbb34cfb7a086f17474f57cacaa9edee8bc8dee873e8f2b851abc0a29a20 |
view |
| Policy rejection | NO TX — daily cap enforced locally before any broadcast | — |
50 interactions. 2 on-chain transactions. The channel close settled the cumulative amount for all 50 vouchers in a single Soroban invocation.
Contracts deployed on testnet:
- Agent vault:
CAX5IDLC2XHGQSEA2YN3LPLZ7EXLMRXYX3HFJGKFXS6B7OQXBKWO44LT - One-way channel:
CCK4XOW3YKQUEZFONUTINKMSNW7SNMRQZURME5U3UP7E6WNGK7UHUCAH
npm install @routedock/routedockgit clone https://github.com/winsznx/routedock && cd routedock
pnpm install
cp apps/provider-a/.env.example apps/provider-a/.env
# Fill in STELLAR_PAYEE_SECRET, SUPABASE_URL, SUPABASE_SERVICE_KEY
pnpm --filter @routedock/provider-a devFull demo (both providers + agent): see docs/AGENT_RUN_CHECKLIST.md.
Server returns HTTP 402. Agent signs a Soroban auth entry for a USDC SAC transfer. On mainnet, the OpenZeppelin facilitator verifies and broadcasts. On testnet, the provider runs a local facilitator (same x402 V2 protocol). One request, one settlement.
Agent sends a payment intent via the Stellar MPP charge protocol. USDC transfers natively via the SAC — no facilitator, lower fees. Server verifies and returns the response.
Agent deposits USDC into a stellar-experimental/one-way-channel Soroban contract. For each unit of data consumed, the agent signs an off-chain ed25519 commitment (no RPC call, no transaction fee). The channel settles with one on-chain close transaction for the cumulative amount.
Deterministic, manifest-driven:
- Sustained access requested +
mpp-sessionavailable → session mpp-chargeavailable → charge (lower fees, no facilitator)mpp-sessionavailable → x402 (facilitator-backed)- Nothing available → throw
Every provider serves /.well-known/routedock.json. The SDK fetches and validates it (JSON Schema, AJV) before every call. Agents never hardcode payment logic.
{
"routedock": "1.0",
"name": "Stellar DEX Price Feed",
"modes": ["x402", "mpp-charge"],
"network": "testnet",
"asset": "USDC",
"asset_contract": "CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA",
"payee": "G...",
"pricing": {
"x402": { "amount": "0.001", "per": "request" },
"mpp-charge": { "amount": "0.0008", "per": "request" }
},
"endpoints": { "price": "GET /price" },
"tags": ["price", "stellar", "dex", "orderbook"]
}The Supabase providers table indexes manifests with pg_trgm trigram search — agents query by capability, not by URL.
import { routedock } from '@routedock/routedock/provider'
app.use('/price', routedock({
modes: ['x402', 'mpp-charge'],
pricing: { x402: '0.001', 'mpp-charge': '0.0008' },
asset: 'USDC',
assetContract: process.env.USDC_ASSET_CONTRACT,
payee: process.env.STELLAR_PAYEE_ADDRESS,
payeeSecretKey: process.env.STELLAR_PAYEE_SECRET,
network: process.env.STELLAR_NETWORK,
facilitatorApiKey: process.env.OPENZEPPELIN_API_KEY, // mainnet only
manifest,
}))One middleware. Handles x402, MPP charge, and MPP session. Serves routedock.json. Verifies payments. Settles on-chain.
| Layer | Mechanism | Enforcement |
|---|---|---|
| On-chain spend cap | __check_auth daily cap policy |
Soroban rejects, nothing broadcast |
| Endpoint allowlist | __check_auth payee check |
Contract rejects unknown payees |
| Session key expiry | SignerExpiration::Ledger |
Time-bounded autonomous access |
| Monotonic vouchers | DB trigger + application layer | Two-layer enforcement |
| Refund window | 17280 ledgers (~24h) | Server settles before funder reclaims |
| Channel settlement | ed25519_verify on Soroban |
Consensus-layer guarantee |
The one-way-channel Soroban contract (stellar-experimental/one-way-channel) has NOT been audited. RouteDock wraps it with safe defaults (17280-ledger refund window, durable session store with monotonic invariant, DB-level trigger enforcement). Production mainnet use should await a formal audit.
routedock/
├── packages/sdk/ # @routedock/routedock — npm
├── apps/web/ # Next.js 16 dashboard + landing — Vercel
├── apps/provider-a/ # Express price endpoint (x402 + MPP charge) — Railway
├── apps/provider-b/ # Express orderbook endpoint (MPP session) — Railway
├── contracts/agent-vault/ # Soroban contract account — Stellar
├── agent/ # Reference autonomous agent
└── supabase/ # Schema + RLS + trigram indexes + Realtime
| Capability | Detail |
|---|---|
| x402 settlement (testnet) | Local ExactStellarFacilitatorScheme — no third-party dependency |
| x402 settlement (mainnet) | OZ hosted facilitator at channels.openzeppelin.com/x402 with Bearer auth |
| MPP charge settlement | Server-side broadcast via @stellar/mpp pull mode |
| MPP session: off-chain vouchers | 50 vouchers verified — each signed as ed25519 commitment, no on-chain tx per voucher |
| MPP session: on-chain close | Single Soroban close(amount, signature) settles the cumulative amount |
| Contract account policy enforcement | __check_auth daily cap rejects overspend at the Soroban level |
| Dashboard Realtime | Supabase postgres_changes subscriptions on sessions and tx_log |
| Discovery registry | providers table with pg_trgm trigram indexes for fuzzy capability search |
| npm package | @routedock/routedock@0.1.0 |
| Network support | `STELLAR_NETWORK=testnet |
| Service | URL | Status |
|---|---|---|
| npm package | @routedock/routedock |
published |
| Agent vault | CAX5IDLC2XHGQSEA2YN3LPLZ7EXLMRXYX3HFJGKFXS6B7OQXBKWO44LT |
live (testnet) |
| Channel contract | CCK4XOW3YKQUEZFONUTINKMSNW7SNMRQZURME5U3UP7E6WNGK7UHUCAH |
live (testnet) |
| Dashboard | routedock.xyz | live |
| Provider A (price endpoint) | api-a.routedock.xyz | live |
| Provider B (orderbook endpoint) | api-b.routedock.xyz | live |
For a detailed walkthrough of the architecture, protocol conformance, security model, and design decisions, see the Submission Brief.
MIT