Ember
Ember is a research project into whether transactions can be exchanged offline in connectivity-constrained environments, where bank transfers, POS and USSD stop working when the network does.
Two contributors built a prototype that moves signed payments between two offline phones as animated QR codes. Status: research prototype on simulated balances — not a production payment system.
- Status
- Research prototype on simulated balances. Not a production payment system.
- Team
- Two contributors
- Source
- Private repository
- Crypto
- Ed25519 (tweetnacl) on client and server
- Stack

Governing idea
Offline, you can't prevent a double spend. You can bound it and detect it.
Overview
Bank transfers, POS and USSD all need a live connection. When mobile data or Wi-Fi drops — routinely, in markets and transport parks — commerce stops, even for people holding digital money.
Ember investigates the feasibility of exchanging transactions without that connection. The prototype covers one path end to end: an offline payment between two phones, settled or flagged once either phone reconnects. Everything runs on simulated money.
Problem and constraints
Preventing an offline double spend requires secure hardware that ordinary phones don't guarantee. So Ember doesn't claim to. It detects the double spend at reconnect and bounds the possible loss to the customer's offline limit — the same trust model used by offline-capable chip cards.
Architecture and design
While online, a customer pre-funds an offline wallet and receives a bank-signed authorisation with a spending limit. Offline, the merchant shows a payment request as a QR code; the customer scans it, signs the payment with their device key and shows a second QR with the signed packet. The merchant checks both signatures locally, against a bank public key built into the app.
When either phone reconnects, queued payments sync and the server settles them into a mock ledger — or flags them, if a packet is replayed or spending goes past the authorised limit.
Diagram 01
An offline payment, and what happens later
₦2,000 at a market stall, both phones offline.
Customer pre-funds; the bank signs an authorisation certificate with an offline limit.
Every stage, in words
- 01Fund (online) (server · bank signer) — Customer pre-funds; the bank signs an authorisation certificate with an offline limit.
- 02Request (merchant QR) — Merchant shows amount, payee and a one-time nonce. Expires after 120 s.
- 03Sign (customer device · Ed25519) — Customer signs the payment packet with their device key and shows it back as a QR.
- 04Verify offline (merchant device) — Merchant verifies the bank's and the customer's signatures with no connection.
- 05Sync (POST /api/sync) — Whichever phone reconnects first uploads its queued packets. Sync is serialised.
- 06Settle or flag (mock ledger) — Validate first, then credit. Replays and over-limit spends are flagged, not settled.
- 07Durable ledger (Postgres · atomic, planned) — Atomic, constraint-backed settlement and a hardware-backed signer.
Implementation — the prototype
What exists is a React/Vite PWA and an Express server, with keys in the browser's local storage and an in-memory ledger that resets on restart.
Settlement was the part most likely to be wrong in quiet ways, so I moved it to validate-before-mutation: a packet is fully checked before any balance changes, transaction ids and request nonces must be unique, and sync requests are serialised. Payment requests now expire after 120 seconds and carry a one-time nonce.
On the transport side I worked on QR reliability — an animated multi-frame encoding with parity recovery, scanner frame reassembly, and a matte anti-glare display that keeps the screen awake.

Results and limitations
The prototype demonstrates signed offline exchange over QR, local signature verification, and detection of replayed or over-limit payments at settlement. It does not demonstrate durable or atomic settlement: the ledger is in memory and balances are simulated.
The target architecture in the team's diagrams — a native app with a hardware-backed signer and a Postgres ledger with atomic settlement — is a plan, not an implementation. A review of that design concluded it isn't ready to handle real money until settlement atomicity, the funds-reservation model and the device trust model are specified.
Open research questions
These are proposed directions, not implemented features.
- NFC as a secondary offline transport — researched within the team; not part of the prototype.
- Bluetooth Low Energy as an alternative transport — proposed; not investigated in code.
- Settlement and double spending on reconnect — atomic, constraint-backed settlement and a funds-reservation model would be required; neither is built.
- Device trust — a hardware-backed signer appears in the target architecture only.