Skip to content

About

Offline-first personal finance tracker for Android: expenses, budgets, accounts and loans. Built with Expo, React Native and TypeScript.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

SmartWallet icon

SmartWallet

An offline-first personal finance tracker for Android. Log expenses in seconds by tapping or just speaking, see where your money goes, stay within budget and track loans to the last EMI. All data stays on your phone; voice entry is optional and, when used, sends only the recording plus your category and account names to Gemini.

Expo SDK React Native TypeScript Platform License

⬇ Download the latest APK

Transactions Add transaction Stats Budget

Accounts Loans Settings

Features

Transactions

  • Expense, income and transfer entries with a built-in calculator keypad (40+7, 2×120, …)
  • Two-tap categorisation: pick a category, then a subcategory (e.g. Dairy → Milk)
  • Quick date chips (Today / Yesterday) plus a native date picker
  • + Next to log several items in a row without leaving the screen
  • Notes, edit, and delete with confirmation
  • Tags for anything categories can't capture: the item (milk, veggies) and where you bought it (swiggy instamart, bigbasket, dmart). Create them once in Settings → Tags, then tap to pick them on any transaction
  • Swipe left or right to move between months
  • Month-by-month timeline grouped by day with daily totals

Voice entry

  • Hold the mic, say "milk 47, petrol 205 yesterday, salary 60000 to savings", release
  • Google Gemini turns speech into entries with the right category, subcategory, account and date ("yesterday", "last Friday", "on the 5th"), plus any of your existing tags you mention
  • Review screen before anything is saved: fix or remove entries, then save all at once
  • Uses your own free Gemini API key, set up in Settings → Voice entry. The key is checked with Google before it's saved and stored encrypted on the phone, never in backups
  • Clear messages for a wrong or expired key, used-up daily limit, no internet and busy servers

Stats & budgets

  • Monthly and yearly views with income, expense and savings
  • Donut chart by category; tap a category to see its subcategory split
  • Per-category monthly budgets with progress bars (green → amber → red)
  • Month-by-month income vs expense bars for the year
  • Spend per tag for the month or year; tap a tag to see its transactions

Accounts

  • Bank accounts, cash, wallets, credit cards and your own custom types, all created by the user
  • Credit cards, regular or FD-backed: limit, outstanding, available credit, utilisation, statement and due day, with an overview screen and per-card spending/payment history
  • Spending on a card is an expense on the card (your bank isn't touched); Pay bill is a transfer from a bank to the card, so it settles the due without counting as another expense
  • Spending past a card's available credit is blocked
  • Fixed deposits as their own asset type. An FD-backed card links to its FD: the deposit counts once as an asset, the limit is never counted
  • Live balances, net worth, assets vs liabilities. Liabilities are actual card dues and loans; an overpaid card counts as an asset
  • Transfers between accounts; balance corrections are recorded as adjustments, never silent edits
  • Hide accounts you no longer use without losing history

Loans

  • Dedicated tab with outstanding amount, % repaid and projected payoff month
  • Pay EMI pre-fills a transfer from your bank to the loan
  • Paying a loan from New Transaction (Loan category → EMI or Interest) asks which loan and saves the same payment, so the outstanding always updates. Reports show it under Loan → EMI / Interest, counted once
  • Monthly interest is posted automatically at month end on the outstanding balance (reducing-balance method)

Categories

  • Ships with a clean, standard set (Dairy, Meat & Eggs, Groceries, Bills & Utilities, Vehicle, …)
  • Add, rename, hide or delete categories and subcategories, and set budgets
  • Items in use can only be hidden, so history is never orphaned
  • Settings → Tags: add, rename, merge (rename onto an existing tag) or delete tags

Data & backup

  • Search across notes, categories, accounts, tags and amounts, with filters for date range, type, account, category and tags (several tags = must have all)
  • Backup to Google Drive (or anywhere) through the Android share sheet, and restore from a backup file
  • CSV export for spreadsheets, and CSV import with automatic matching and duplicate detection
  • Every destructive action asks for confirmation first

Tech stack

Area Choice
Framework Expo SDK 58, React Native 0.88, React 19
Language TypeScript (strict)
Navigation Expo Router (file-based, tabs + modal stack)
State Zustand
Storage Single JSON file via expo-file-system (no database)
Charts react-native-svg (hand-built donut and bar charts)
Files expo-sharing, expo-document-picker
Native UI @react-native-community/datetimepicker, expo-haptics
Voice expo-audio (recording), Gemini API (generateContent with audio input and JSON schema output), expo-secure-store (API key)
Testing Node assert + tsx (unit), Playwright (end-to-end on the web build)
Tooling ESLint (eslint-config-expo), Prettier

Design notes

  • Money is stored as integer paise. No floating-point drift in balances or interest.
  • Dates are local YYYY-MM-DD strings. Using UTC timestamps in IST would push anything before 05:30 into the previous day.
  • Storage is one compact file. Writes go to a temp file that is then atomically renamed, and the previous version is kept as a fallback. If the file can't be read, the app refuses to overwrite it and asks you to restore. Two years of daily entries is about 200 KB.
  • Saves are debounced and also flushed when the app goes to the background.
  • Cash-flow rules for stats:
    • Transfers between your own accounts are not spending.
    • Payments into a loan count as loan spending.
    • Interest posted on the loan account doesn't touch your cash, so it isn't double-counted.
    • Balance adjustments are excluded.
  • Pure core. All business logic lives in src/lib/ledger.ts as pure functions over plain data, and the store is a thin wrapper. That's what makes it fully unit-testable.

Project structure

src/
├── app/                    Expo Router screens
│   ├── (tabs)/             Transactions, Stats, Accounts, Loans, Settings
│   ├── account/            Account detail and editor
│   ├── category/           Category editor
│   ├── cards.tsx           Credit card overview
│   ├── categories.tsx      Category list
│   ├── search.tsx          Search and filters
│   ├── tags.tsx            Rename, merge, delete tags
│   ├── tx.tsx              Add / edit transaction (modal)
│   ├── voice.tsx           Review entries from voice
│   └── voice-settings.tsx  Gemini API key setup
├── components/
│   ├── ui.tsx              Theme tokens and shared UI primitives
│   └── VoiceButton.tsx     Hold-to-talk recorder
└── lib/
    ├── ai.ts               Gemini request, reply parsing, key checks, error messages
    ├── voice.ts            API key storage, audio file reading
    ├── ledger.ts           Validation, balances, cash flows, loan interest, CRUD
    ├── store.ts            Zustand store + file persistence
    ├── csv.ts              CSV parse / export / import
    ├── io.ts               Backup, restore, share, file picking
    ├── money.ts            Formatting (₹ Indian grouping), calculator, date helpers
    ├── seed.ts             Default categories
    └── types.ts            Data model
scripts/e2e.mjs             End-to-end UI test

Install

Download SmartWallet-vX.Y.Z.apk from Releases on your Android phone (Android 7.0+, arm64) and open it to install. Updating to a newer release keeps your data.

Getting started

Requirements: Node 20+, and either an Android phone with Expo Go or the Android SDK for native builds.

git clone https://github.com/thekirankumarv/SmartWallet.git
cd SmartWallet
npm install
npm start          # scan the QR code with Expo Go
npm run web        # or run in the browser

Build an installable APK

Requires the Android SDK and JDK 17+ (ANDROID_HOME and JAVA_HOME set).

npm run apk        # outputs SmartWallet.apk in the project root

The release build targets arm64-v8a with R8 minification and resource shrinking (~17 MB).

Testing

npm test           # unit tests: calculator, formatting, dates, CSV, ledger, loan interest, voice parsing and API errors
npm run e2e        # UI flow test (start `npm run web` first; run `npx playwright install chromium` once)
npm run typecheck
npm run lint

The end-to-end suite starts from a fresh install and walks through:

  • creating accounts
  • adding, editing and deleting transactions (cancel and confirm)
  • transfers and income
  • adding a loan and paying an EMI
  • regular and FD-backed credit cards: spending, the limit guard, paying a bill, net worth
  • stats
  • the guards that stop deleting accounts and categories still in use
  • category and subcategory management
  • search
  • voice entry setup (key format and rejected-key messages) and the review screen
  • data surviving a reload

CSV format

Export and import use the same columns:

Date,Time,Type,Account,To Account,Category,Subcategory,Note,Amount,Tags
2026-10-24,08:15,Expense,HDFC Bank,,Dairy,Milk,,56,"milk, swiggy instamart"
2026-10-01,,Income,HDFC Bank,,Salary,,,85000,
2026-10-05,,Transfer,HDFC Bank,Home Loan,,,,21500,
  • Required columns: Date, Account, Type (Expense / Income / Transfer) and Amount.
  • Dates: YYYY-MM-DD or DD/MM/YYYY.
  • Matching: accounts, categories and subcategories are matched by name (case and punctuation insensitive). Missing ones are created.
  • Tags: optional Tags column, separated by commas or semicolons. A leading # is ignored and tags match existing ones regardless of case.
  • Duplicates: rows already in the app are skipped, so re-importing the same file is safe.

License

MIT © Kiran Kumar V

About

Offline-first personal finance tracker for Android: expenses, budgets, accounts and loans. Built with Expo, React Native and TypeScript.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages