XRPLHub.io — backend
The production app for xrplhub.io: Next.js (App Router, TypeScript) on Vercel, Neon Postgres
through Prisma, XRP Ledger reads through a rotated pool of public nodes, and Xaman / Crossmark / GemWallet for signing.
There is no AI or LLM anywhere in the shipped code.
What it does
| Product | What it is |
|---|
| XRPLScore | A 300–850 score for an XRPL wallet, from 8 public-ledger signals (one engine, src/lib/xrplscore.ts). Free lookups may be served from a 15-minute cache; the response says so (fromCache, cacheAgeSeconds). |
| Transaction services | Paid on-chain actions (trust lines, escrows, AMM, NFT, …). We build the exact transaction; the buyer signs it in their own wallet. The count comes only from BUILDABLE_SERVICE_IDS in src/app/api/execute/serviceCatalog.ts. |
| B2B API | Keys sold for RLUSD/XRP (/api/v1/*, /api/monitor/*, /api/screen/ofac, lending endpoints). Plans in src/lib/plans.ts; quotas are hard (HTTP 429 at the limit). |
| x402 pay-per-call | Per-request payment for the score, report and screening endpoints (RLUSD via the t54 XRPL facilitator; USDC on Base via Coinbase's facilitator). |
| Continuous monitoring | Watched wallets, HMAC-signed webhooks, sparse attested observations. Once a day, not real-time. See docs/MONITORING.md. |
| OFAC screening receipts | An exact-match check against the OFAC SDN list's XRP addresses, recorded as a receipt that attests to the process only — never to an address being clean or sanctioned. |
| MPT / credential lookups | Read-only views of Multi-Purpose Token issuers and XLS-70 credentials, each labelled with its coverage. |
| Community grants | A person reviews every application; nothing is decided or paid automatically. Applications are currently paused (GRANT_APPLICATIONS_OPEN in src/lib/grantsStatus.ts) because approved grants are waiting for funds. Donations stay open. |
XRPLHub is not a bank, credit bureau, consumer reporting agency or regulated entity, and nothing it returns is legal,
financial or compliance advice.
Things that are deliberately true of this codebase
- The server decides every price.
src/lib/servicePrices.ts is the only price table. Nothing the client sends about
amount or currency is read.
- Payments are verified on the ledger, once.
src/lib/paymentGate.ts checks a validated, successful Payment to the
treasury in XRP or RLUSD from the real issuer, covering the price; each payment hash is single-use in the database.
- Invoices are matched without a scan window. Checkout invoices (
src/lib/rlusd.ts) are found by exact transaction
hash when known, otherwise by walking the treasury's history back to the invoice's creation — dust traffic cannot push a
real payment out of view. An invoice is only closed after the ledger was read completely.
- A mistyped address is rejected, not screened. Every address goes through
src/lib/address.ts (base58check).
- A cached score never reaches an attestation.
scripts/check-attestation-freshness.mjs runs in npm run build and
fails if any attestation module imports the cache or fetches a cache-backed score route.
- Partial data never reads as whole. A failed ledger read is a 503 or a
degraded / complete:false flag, never a
clean-looking answer.
- Every judgment carries a disclaimer in its response.
- The treasury is a single-key XRPL account. It has no signer list on the ledger; nothing here may claim multi-sig
protection until it does.
Layout
src/app/api/… route handlers (payments, scoring, screening, monitoring, x402, MCP, admin, cron)
src/app/… the site (homepage, pricing, donate, verify pages)
src/lib/… engine, pricing + payment gate, x402, monitoring, screening, MPT/credentials, watchdog
prisma/schema.prisma
scripts/ build gates (freshness, service parity) and operator scripts
docs/ AUTONOMY.md (what runs unattended), MONITORING.md, CREDENTIAL-SPEC.md, calibration notes
Running it locally
npm install
cp .env.example .env
npx prisma db push
npm run dev
npm run build runs the two build gates (attestation freshness, service parity), prisma generate, then next build
with TypeScript errors enforced.
Main environment variables (see .env.example; anything unset degrades loudly, not silently):
| Variable | Used for |
|---|
DATABASE_URL | Neon Postgres |
TREASURY_ADDRESS, RLUSD_ISSUER, RLUSD_CURRENCY | Where payments go and which RLUSD counts |
XUMM_API_KEY, XUMM_API_SECRET | Xaman sign-in and payment requests |
ADMIN_API_TOKEN | Every admin route (fails closed when unset) |
CRON_SECRET | The two daily crons |
CREDENTIAL_SIGNING_SECRET | The paid off-ledger certificate (nothing is issued without it) |
ANCHOR_WALLET_SEED, MPT_ANCHOR_ENABLED | On-ledger Merkle-root anchors |
BITHOMP_API_KEY | MPT registry holder counts |
CDP_API_KEY_ID, CDP_API_KEY_SECRET | USDC-on-Base x402 facilitator |
ERROR_WEBHOOK_URL, HEALTHCHECK_PING_URL | Alerts and the external dead-man's switch |
Operations
docs/AUTONOMY.md is the source of truth for what runs unattended (two Vercel crons, 06:00 and 07:00
UTC), what expires and when, the watchdog, and what to check first after a long absence. Deploys go out on every push to
main; redeploy with the Vercel build cache off.
Contact: support@xrplhub.io