From Ladder's App Store listing
Ladder
A personal-finance app for Nigeria and Ghana: save, invest, budget and get help from an AI assistant.
In shortI rebuilt the whole app from scratch and replaced the old version while people were using it. The store rating went up after launch.
From the App Store listing
Deep dive Letting a Ghanaian buy a Nigerian IPO People in Ghana can invest in Nigerian IPOs in their own currency, and always pay the exact rate they agreed to. Read the full storyClose
A user in Accra pays in cedis for IPO units priced in naira, at a rate that can't change under them halfway through paying.
Context
Ladder lets people in Nigeria and Ghana invest, save, budget and withdraw across three currencies: naira, cedi and dollar.
Problem
Currency conversion had been written by hand in at least five different widgets. A cross-border purchase needs one rate that the user sees, agrees to and actually pays.
Constraints
Quotes expire, sometimes while the user is mid-payment. Fees must be right before the user commits. Error messages are written for people and can change, so code can't branch on them.
What I built
- One FX layer for naira, cedi and dollar, replacing the conversion code copied across five or more widgets.
- Locked quotes, so the rate the user confirms is the rate they pay.
- Fee calculation inside the same layer, shown before the user commits.
- Quote-expiry recovery. If a quote runs out mid-payment, the user gets a fresh quote and confirms it again.
- Typed error codes. The app branches on the error
code, never on the message text. - Tests on FX quotes and fees, including a walkthrough test that steps through the whole lock flow.
Trade-offs
One layer, not five copies. Pulling conversion out of the widgets took a refactor across the app, but now there's one place to get fees and rounding right.
Codes over messages. A backend team can reword an error without breaking the app's recovery logic.
Re-confirm, never re-price quietly. When a quote expires, the user sees the new rate and confirms it again. It costs one extra tap, but nobody pays a rate they didn't agree to.
Outcome
A Ghanaian user can buy Nigerian IPO units at a locked cross-border rate. Conversion now lives in one tested layer instead of five widgets.
Cross-border buying is still rolling out, so there are no volume numbers to share yet.
Deep dive Replacing a live fintech app Rebuilding Ladder from the ground up while v1 was live and holding real users' money. Read the full storyClose
Context
Ladder is a personal-finance app for Nigeria and Ghana covering investments, savings, budgeting, withdrawals and an AI assistant. v1 was live and holding users' money.
Problem
Build a v2.0 that replaces v1 in production instead of running beside it, across auth, KYC, savings, investments, budgeting and chat.
Constraints
Unreliable mobile networks. Two countries with different rails, rules and rollout timing. Tiered KYC limits. A codebase that grew to about 556 Dart files.
What I built
- Architecture on Riverpod + GetIt, with separate development, staging and production builds, each on its own Firebase project.
- WebSocket layer with heartbeat and exponential backoff, so balances stay live on bad networks instead of failing silently.
- Payments: Flutterwave card checkout with redirect and callback handling, Mobile Money with polled verification and manual retry, and NGN bank mandates with OTP for direct debit and auto-invest.
- One funding and withdrawal flow shared by savings and investments, with KYC tier limits checked before a transaction starts.
- Compile-time feature flags so a feature can ship in one country before the other.
- Networking on Dio, with interceptors for auth, cURL logging and error reporting.
- Release tooling: a makefile for builds and Shorebird over-the-air patches, plus git hooks that bump the version automatically.
Outcome
v2 replaced v1 in production, is live in both countries, and the app's store rating went up after launch. I wrote most of v2's code, about 78% of the commits. Ladder's store listing now reports 27K+ active users and $2M+ saved.
Deep dive More from Ladder An AI assistant, selfie ID checks, security, analytics and a two-country rollout. See allClose
An AI assistant inside a finance app
"Lady" streams replies over Server-Sent Events into an animated streaming-text view, with file attachments and chat history. A consent screen asks the user before any financial data is sent to the AI.
Selfie capture that checks itself
On-device identity capture with Google ML Kit. It checks face size, centring, open eyes and detection confidence, with adjustable strictness and exposure correction for dim rooms.
Security for a finance app
Face ID, fingerprint and PIN login, secure storage, decryption of sensitive payloads from the backend, and automatic logout after inactivity or when the app goes to the background.
Attribution without the mess
Kochava install attribution on iOS (with the tracking-permission prompt) and Android, plus Mixpanel, behind one analytics interface with an event map and onboarding-funnel tracking. Deep links cover universal links, app links and push notifications.
Two countries, one codebase
Compile-time feature flags decide what ships in Nigeria and what ships in Ghana. Development, staging and production each build against their own Firebase project.