@flarcos/kifira-lite
v0.1.0
Published
A lightweight Open Payments gateway — no Rafiki setup required
Maintainers
Readme
Kifira Lite
A lightweight, developer-friendly Open Payments gateway. No Docker, no Kubernetes, no Rafiki setup — just
npxand you're running.
What is this?
Kifira Lite implements the Open Payments API surface — the same REST endpoints that Rafiki exposes — as a single lightweight Node.js process. It's designed for:
- SDK Testing — Point your Open Payments client at
localhost:3000instead of deploying a full Rafiki stack - Arazzo Workflow Validation — Run machine-readable workflow specs against a real server
- Prototyping — Build payment UIs without infrastructure overhead
- Learning — Understand Open Payments by reading ~1200 lines of TypeScript
Quick Start
npx @flarcos/kifira-lite --wallet-address http://localhost:3000/alice --generate-keyThat's it. Two servers start:
- Resource Server at
http://localhost:3000— wallet address metadata, payments, quotes - Auth Server at
http://localhost:3001— GNAP grants, tokens, consent UI
Installation
npm install @flarcos/kifira-liteAs a Library
import { createKifiraServer, generateServerKey, StubBackend } from '@flarcos/kifira-lite';
import { serve } from '@hono/node-server';
const key = await generateServerKey();
const { resourceApp, authApp } = await createKifiraServer({
walletAddress: 'http://localhost:3000/alice',
publicName: 'Alice',
assetCode: 'USD',
assetScale: 2,
port: 3000,
authPort: 3001,
storage: 'memory',
privateKey: key.pem,
paymentBackend: new StubBackend(),
});
serve({ fetch: resourceApp.fetch, port: 3000 });
serve({ fetch: authApp.fetch, port: 3001 });API Surface
Wallet Address Server (public)
| Method | Path | Description |
|--------|------|-------------|
| GET | /alice | Wallet address metadata |
| GET | /alice/jwks.json | Server public keys (JWK Set) |
Auth Server (GNAP / RFC 9635)
| Method | Path | Description |
|--------|------|-------------|
| POST | / | Request a grant |
| POST | /continue/:id | Continue a grant |
| DELETE | /continue/:id | Cancel a grant |
| POST | /token/:id | Rotate an access token |
| DELETE | /token/:id | Revoke an access token |
| GET | /interact/:id | Consent UI (interactive grants) |
Resource Server (token-protected)
| Method | Path | Description |
|--------|------|-------------|
| POST | /alice/incoming-payments | Create incoming payment |
| GET | /alice/incoming-payments | List incoming payments |
| GET | /alice/incoming-payments/:id | Get incoming payment |
| POST | /alice/incoming-payments/:id/complete | Complete incoming payment |
| POST | /alice/quotes | Create quote |
| GET | /alice/quotes/:id | Get quote |
| POST | /alice/outgoing-payments | Create outgoing payment |
| GET | /alice/outgoing-payments | List outgoing payments |
| GET | /alice/outgoing-payments/:id | Get outgoing payment |
Usage Examples
1. Discover a Wallet Address
curl http://localhost:3000/alice{
"id": "http://localhost:3000/alice",
"publicName": "Alice",
"assetCode": "USD",
"assetScale": 2,
"authServer": "http://localhost:3001",
"resourceServer": "http://localhost:3000/alice"
}2. Get a Token (Non-Interactive)
curl -X POST http://localhost:3001/ \
-H "Content-Type: application/json" \
-d '{
"access_token": {
"access": [{ "type": "incoming-payment", "actions": ["create", "read"] }]
},
"client": "http://localhost:3000/alice"
}'3. Create an Incoming Payment
curl -X POST http://localhost:3000/alice/incoming-payments \
-H "Content-Type: application/json" \
-H "Authorization: GNAP <token>" \
-d '{
"walletAddress": "http://localhost:3000/alice",
"incomingAmount": { "value": "1000", "assetCode": "USD", "assetScale": 2 }
}'4. Interactive Grant (Outgoing Payment)
Outgoing payments require user consent. The flow is:
Client → POST / (grant request)
← { interact: { redirect: "/interact/:id" } }
User → GET /interact/:id (consent page rendered)
→ POST /interact/:id/approve
← 302 → client callback with interact_ref
Client → POST /continue/:id (with interact_ref)
← { access_token: { value: "..." } }Architecture
┌─────────────────────────┐ ┌─────────────────────────┐
│ Resource Server :3000 │ │ Auth Server :3001 │
│ │ │ │
│ GET /alice │ │ POST / (grant) │
│ GET /alice/jwks.json │ │ POST /continue/:id │
│ POST /alice/incoming-* │◄────│ POST /token/:id │
│ POST /alice/quotes │ │ GET /interact/:id │
│ POST /alice/outgoing-* │ │ │
└────────┬────────────────┘ └─────────────────────────┘
│
┌────▼────┐
│ Storage │ (Memory or SQLite)
└────┬────┘
│
┌──────▼───────┐
│ Payment │ (StubBackend or custom)
│ Backend │
└──────────────┘Configuration
CLI Options
--wallet-address <url> Wallet address URL (required)
--name <name> Display name (default: from URL)
--asset-code <code> Currency code (default: USD)
--asset-scale <n> Decimal scale (default: 2)
--port <n> Resource server port (default: 3000)
--auth-port <n> Auth server port (default: 3001)
--storage <type> "memory" or "sqlite" (default: memory)
--sqlite-path <path> SQLite file path (default: ./kifira.db)
--key <path> Ed25519 private key PEM file
--generate-key Generate a new key pair on startupStorage
- Memory (default) — Zero config, data lost on restart. Perfect for testing.
- SQLite — Persistent, WAL-mode, auto-creates tables. Use
--storage sqlite.
Payment Backend
The PaymentBackend interface abstracts money movement. Kifira Lite ships with a StubBackend that auto-succeeds all payments (great for testing). You can implement your own:
import type { PaymentBackend } from '@flarcos/kifira-lite';
class StripeBackend implements PaymentBackend {
async getQuote(params) {
// Call Stripe API for exchange rate
return { debitAmount, receiveAmount, expiresAt };
}
async executePayment(params) {
// Call Stripe transfer API
return { success: true, sentAmount };
}
}How it Compares to Rafiki
| Feature | Rafiki | Kifira Lite |
|---------|--------|-------------|
| Setup time | Hours (Docker, Postgres, Redis) | Seconds (npx) |
| Storage | PostgreSQL + Redis | In-Memory or SQLite |
| ILP Connector | Full STREAM/ILP | Stub (wire-compatible URLs) |
| GNAP Auth | Full RFC 9635 | Full RFC 9635 |
| HTTP Signatures | RFC 9421 verification | RFC 9421 (configurable) |
| Consent UI | Separate frontend | Built-in dark-mode page |
| Production ready | ✅ | ❌ (designed for dev/test) |
Development
# Install dependencies
npm install
# Run tests
npm test
# Start dev server
npx tsx src/cli.ts --wallet-address http://localhost:3000/alice --generate-keyTesting
54 tests covering:
- Wallet address — metadata, JWKS endpoints
- GNAP auth — non-interactive grants, interactive consent flow, token rotation/revocation
- Resources — incoming payments CRUD, quotes, outgoing payments
- Storage — both Memory and SQLite adapters
- E2E — full one-time payment workflow over HTTP
npm testLicense
Apache-2.0
