There are 2 billion people in the world without smartphones. In Kenya alone, millions of M-Pesa transactions happen every day on feature phones — Nokias, Techno candybars, phones that cost 800 shillings. These people aren't waiting for a better wallet app. They've been doing mobile money since 2007 on a dial pad.
But Bitcoin? Bitcoin still asks you to download an app, set up a seed phrase, have internet data, own a smartphone. It has accidentally locked out the very people it was supposed to free.
We looked at that gap and asked one question: what if you could send and receive Bitcoin the same way you send M-Pesa?
Dial a code. Follow a menu. Done.
What it does
LNpesa is a USSD interface for Bitcoin agents — built on the Pontmore open protocol over Nostr.
Any agent, on any phone, dials *384#. They enter their name, choose their payment method, set their liquidity. In seconds they are live as a registered Bitcoin swap agent on the Pontmore network — discoverable by anyone, anywhere, without asking permission from any company or platform.
No smartphone. No app. No internet data. Just a dial tone and a dream.
Agents can view incoming swap requests, confirm M-Pesa payments sent, and manage their liquidity — all from a 2010 Nokia. Every action they take publishes a cryptographically signed Nostr event to the Pontmore protocol, the same protocol that powers Minmo's smartphone app. Same network. Different door.
How we built it
We built LNpesa in a single hackathon night on top of three open layers:
Pontmore Protocol We read PIP-00 and PIP-02 directly from the spec. No API key. No permission. We implemented the agent definition event (kind:30360) and swap transition events (kind:7301) exactly as the protocol defines them. When our agent registers via USSD, a valid signed Pontmore event appears on Nostr relays — the same events Minmo reads.
Africa's Talking USSD Gateway . We built a stateless Express.js session machine that handles the Africa's Talking webhook. Every menu state is derived purely from the accumulated text input — no server-side session storage needed. Clean, fast, works on any network.
Nostr-tools We generate a fresh Nostr keypair per agent, store the secret key against their phone number in SQLite, and use it to sign every protocol event. Agents own their identity. We publish simultaneously to three relays relay.damus.io, relay.nostr.band, and nos.lol so the agent is discoverable regardless of which relay a client connects to.
The stack is Node.js, Express, nostr-tools v2, better-sqlite3, and Africa's Talking. The whole thing fits in seven files.
Challenges we ran into
Getting the PIP-00 event shape exactly right. The difference between an agent appearing on Pontmore and not appearing is a single missing tag. The t: agent tag, the JSON content structure, the relay declarations — every field matters. We read the spec three times before we were confident.
USSD statelesness. USSD sessions don't persist between requests. Everything which step the user is on, what they've typed has to be derived from a single accumulating text string split by asterisks. Designing a clean state machine on top of that constraint was harder than it sounds.
nostr-tools v2 breaking changes. The import patterns changed significantly from v1. Named exports, new relay connection API, different signing flow. We hit walls before we found the right patterns.
Time. We had one night.
Accomplishments that we're proud of
We are proud that when an agent dials our USSD code and completes registration, a real cryptographically signed Nostr event appears on public relays. You can go to nostr.band right now, search our agent's pubkey, and see them. They exist on the open protocol. No company owns that. No one can take it away.
We are proud that we extended the Pontmore ecosystem without asking Minmo for anything. We read their open protocol, we implemented it, and we became the second independent client on their network. That's what open source means.
And we are proud that we built something that works on a phone your grandmother has had since 2011.
What we learned
We learned that open protocols are only as powerful as the number of people who implement them. Pontmore is a great protocol. But it needed more than one door. We built another one.
We learned that the hardest UX constraint a 180 second USSD session with no persistent state forces you to make things so simple they actually work for everyone.
We learned that the gap between Bitcoin and the unbanked is not a money problem or a technology problem. It is an interface problem. And interface problems are solvable in a single night.
What's next for LNpesa
The USSD interface is the beginning. Next we want to:
Add Lightning invoice generation so agents can receive actual sats from customers over Lightning, settled in real time Swahili and Kikuyu voice prompts for users who can't read, so LNpesa works for everyone regardless of literacy Agent reputation publishing implement MIP-09 attestations so completed swaps build a verifiable on-chain track record for every agent Go live with real agents pilot with M-Pesa operators in Nairobi, Kisumu, and Mombasa who are already running informal Bitcoin exchanges today
LNpesa is not a product. It is a protocol implementation. It belongs to everyone who dials the code.
Built With
- africastalking
- better-sqlite3
- express.js
- node.js
- nostr
- prontmore
Log in or sign up for Devpost to join the conversation.