Chain-Fi: OAuth server, backend API and vault
CTO · May 2024 – February 2026 · company closed in 2026
I wrote an OAuth 2.0 server from scratch, plus the API, SDK and mobile app built around it.
Clients
Third-party app
134Embeds the JavaScript SDK for QR login and signing requests.
Mobile app (React Native)
45Holds the user's key. Scans QR codes and signs.
Dashboard and developer portal
12Consent screen, app registration, client credentials and usage stats.
Backend · Express, PostgreSQL
OAuth 2.0 server
1Authorization code and refresh grants, opaque tokens, rotation, revocation, 9 scopes.
REST API and Socket.IO
23487 endpoints, scope checks per route, real-time signing sessions.
Relayer
5Checks the user and second-factor signatures, pays gas from a server wallet.
Listener
6Follows vault activity and pushes it to clients over WebSocket.
On-chain · EVM testnets
Vault factory
5Deploys one minimal-proxy clone (EIP-1167) per user.
User vault
56Every withdrawal or transfer requires an EIP-712 signature.
- 1Sign-in: the app sends the user to the consent screen. Once they approve, the OAuth server returns a code, then access and refresh tokens.
- 2Setup: developers register their app, scopes and redirect URIs in the portal, and get client credentials.
- 3API calls: the app calls the API with its access token. Each route checks the token's scopes.
- 4Signing: the SDK opens a Socket.IO session and shows a QR code. The user scans it with the mobile app, which signs with their key.
- 5Transactions: the relayer checks both signatures and calls the factory or the vault. It pays the gas, so users never need funds for fees.
- 6Updates: the listener sees vault activity and pushes it to connected clients.
Chain-Fi was building accounts where users keep their own key, on their phone. Other apps could sign users in and ask them to approve transactions. So we needed a login system for developers, and a vault where users could hold assets without paying gas.
I wrote the OAuth 2.0 server myself, without a library. It handles authorization codes and refresh tokens, rotates refresh tokens, supports revocation and checks nine scopes. Users approve apps on a consent screen. Developers register their apps in a portal, get client credentials and see usage per app. Behind it sits the main API: 87 REST endpoints on Express and PostgreSQL, with plain SQL. It ships in Docker, and GitHub Actions runs unit and integration tests against Postgres and Redis. I also wrote the JavaScript SDK that other apps embed for QR-code login and signing, and the React Native app that holds the user's key and approves requests.
On-chain, I wrote the vault and its factory in Solidity. Each user gets their own small proxy contract (EIP-1167), and nothing leaves it without an EIP-712 signature. A relayer service checks two signatures, the user's and a second factor, then sends the transaction and pays the gas. Stripe handles billing. A Node.js listener watches vault activity on the Base, Arbitrum and Optimism testnets and pushes it to clients over WebSocket. The main rule: the backend never holds a user's key. The product ran on testnets until the company closed in February 2026.