-
-
A screenshot showing an example user dashboard
-
A screenshot showing an example subscriptions page
-
A screenshot showing an example transaction history
-
A screenshot showing the AI review for the example users transaction history
-
A screenshot showing the vendor page in light mode
-
A screenshot showing the spending guard page in light mode
EquiPay: Subscription Payments on XRPL
Inspiration
Netflix raises their prices and sends an email buried in your promotions folder. By the time you notice, they have already charged you at the new rate and there is nothing you can do about it. That pattern is not unique to Netflix -- it is how every subscription service operates. Merchants set the terms, merchants can change the terms, and the charge just shows up.
We wanted to flip that dynamic. What if the payment terms were committed to a ledger the moment you subscribed, and a price change required your explicit approval before the next cycle could lock? XRPL's native escrow primitive made that possible without any smart contract complexity, and RLUSD kept the amounts dollar-stable so volatility was never an excuse for a surprise.
What We Built
EquiPay is a subscription payment platform built on XRPL. Vendors create subscription requests signed with an HMAC contract. Users review and approve them, which locks funds into an on-chain escrow tied to the billing period. When the cycle ends the merchant can release the escrow. Users can cancel anytime, killing the auto-renew before the next cycle locks.
On top of the core escrow flow we added:
- RLUSD support for stablecoin-denominated subscriptions
- Spending guards that cap monthly outflows per wallet
- Vendor webhooks so external services get notified on every subscription event
- Financial snapshots pinned to IPFS via Pinata for immutable spending history
- AI spending review that pulls transaction history and active subscriptions and returns a plain-English summary via Gemini
- Support for multiple wallets with nicknames so you don't have to remember addresses
- In app transfer between wallets so you can easily make adjustments
How We Built It
The backend is FastAPI with SQLAlchemy over SQLite, using xrpl-py for all on-chain operations. We split handlers into dedicated modules (wallets, payments, subscriptions, snapshots, ai) behind a shared API router. Auth is JWT with bcrypt. Vendor routes use a shared-secret header instead, since vendors are server-side integrators rather than end users.
The frontend is Vue 4 with Pinia stores, PrimeVue components, and TypeScript throughout. Each major feature has its own store that talks to a typed apiHelper layer.
Challenges
Neither of us had any blockchain experience coming into this, so there was a lot to figure out as we went. Getting RLUSD working on devnet was our first big wall. The issues kept stacking up:
- The issuer address we configured did not exist on devnet yet
- A typo in the devnet RPC URL (
rippletdev.netinstead ofrippletest.net) - DefaultRipple was not enabled on the issuer account, which is required for peer transfers
- TrustSet transactions were setting the NoRipple flag, which broke the payment path
- Devnet accounts expire periodically, so the issuer account reset mid-session
Each of these returned the same tecPATH_DRY error with no further detail, which
made diagnosis slow for two developers reading XRPL docs for the first time. Once we
understood the account model well enough we added a startup health check that inspects
issuer flags on boot and it helped immensely.
The escrow timing tripped us up too. XRPL has its own time format that is different from the standard Unix timestamps we were used to, and getting those window values wrong means an escrow either can never be claimed or expires instantly. Simple fix once we spotted it, but it took a while to find.
Midway through we also realized we were passing wallet seeds back and forth in API requests, which is not great. We refactored so the backend just looks up the seed by wallet address instead. It touched a lot of files at once but was worth doing.
What We Learned
XRPL is genuinely well-suited for this use case. Escrow, trust lines, and issued currencies are first-class primitives rather than bolted-on token standards. The tradeoff is that the ledger is unforgiving about account configuration -- DefaultRipple, NoRipple flags, and reserve requirements all have to be exactly right or payments fail with a path error.
Building the contract signing layer (HMAC payload hash stored on the subscription row, verified on approval) gave us a lightweight audit trail without needing a separate blockchain for the contract itself.
What's Next
- Refund windows on new subscriptions so users have protection against shady vendors
- User-reported wallet flagging to surface bad actors across the platform
- 2FA for login
- 2FA confirmation when approving a new subscription or sending a payment
- Merchant dashboard with cycle release automation
- Multi-sig approval for high-value subscription tiers
- Dockerization for one-command local and production deploys
- Move from SQLite to Postgres for production
- Replace server-side seed storage with a proper HSM or user-controlled signing flow
Log in or sign up for Devpost to join the conversation.