Commit Graph
383 Commits
Author SHA1 Message Date
minibits-cashandClaude Opus 4.8 6d4e9d67f7 Add PERF_TRACKING switch to toggle SQLite query timing logs
A single module-level boolean in connection.ts gates the per-query TRACE
timing. When false, the timer and log calls are skipped entirely (zero added
overhead). Defaults to true for on-device profiling.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 12:23:03 +02:00
minibits-cashandClaude Opus 4.8 b6d3257aeb Add TRACE-level query timing to the op-sqlite connection adapter
Every query funnels through the connection adapter, so instrumenting it once
times the whole DB layer. execute / executeAsync / executeBatch /
executeBatchAsync now log duration (ms), row or statement count, and the SQL
text at TRACE level — useful for profiling the op-sqlite migration on-device.

Only the SQL string (which carries `?` placeholders) is logged, never the
params, which may contain proof secrets. Uses performance.now() when available
(sub-ms resolution) and falls back to Date.now(); SQL is whitespace-collapsed
and truncated to one line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 11:42:06 +02:00
minibits-cashandClaude Opus 4.8 d62ac12dfd Fix mintToCacheDTO call for cashu-ts v4 signature
cashu-ts v4 dropped the leading `unit` parameter from
CashuKeyChain.mintToCacheDTO; the signature is now
(mintUrl, allKeysets, allKeys). Both call sites still passed `unit` first,
shifting mintUrl into the allKeysets slot. At runtime mintToCacheDTO does
allKeysets.map(...) on what is actually the mintUrl string, throwing
"TypeError: undefined is not a function" — which surfaced as a failed topup
mint right after getCachedWalletKeys, before mintProofs logged its counter.

Verified against the installed runtime (cashu-ts 4.2.1, cashu-ts.es.js): the
impl takes 3 args and cashu-ts calls it internally as
mintToCacheDTO(this.mintUrl, keysets, keys). Sibling of the earlier
loadMintFromCache v4 signature fix (c61e73a); unrelated to the op-sqlite
migration (the DB layer raises AppError, never a bare TypeError).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 23:42:53 +02:00
minibits-cashandClaude Opus 4.8 7bf7685ec6 Fix jest test suite: scope testMatch, mock quick-crypto, drop dead tests
- testMatch now only picks up *.test/*.spec files so the i18n scripts
  (run via `yarn test:i18n`) are no longer globbed as empty suites
- Allowlist react-native-flash-message for transform and map
  react-native-quick-crypto to a Node crypto shim, unblocking the 11
  cashuDleq tests that load it transitively via @scure/bip32
- Remove orphaned storage.test.ts (module + async-storage dep gone) and
  the boilerplate App.test.tsx smoke test that mounted the full native tree

Suite now: 12 suites / 136 tests passing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 22:31:36 +02:00
minibits-cashandClaude Opus 4.8 90b9c8043f Open the db at quick-sqlite's legacy path so existing data is found
op-sqlite's default database directory differs from react-native-quick-sqlite's
on BOTH platforms, so a naive swap would open an empty db and orphan every
existing wallet:

  platform | quick-sqlite (old)        | op-sqlite default
  iOS      | NSDocumentDirectory       | NSLibraryDirectory
  Android  | filesDir (getFilesDir)    | databases/ (getDatabasePath)

The connection adapter now passes an absolute `location` matching the old
directory — IOS_DOCUMENT_PATH on iOS, ANDROID_FILES_PATH (= context.filesDir)
on Android. op-sqlite fully overrides its base path when location starts with
'/' (verified in cpp/OPSqlite.cpp open proxy), so the file resolves to exactly
<Documents|files>/minibits.db — the same file quick-sqlite created. No copy or
data migration needed; the -wal/-shm sidecars in the same dir are picked up too.
A caller-supplied location still wins over this default.

Must still be confirmed on a device: upgrade an install with existing data and
verify the balance/history persist (db.getDbPath() prints the resolved path).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 22:19:42 +02:00
minibits-cashandClaude Opus 4.8 245ffd943e Split getDatabaseVersion into a pure read and an explicit seed
getDatabaseVersion previously read the version and, on a fresh database,
also inserted the seed row as a side effect. Split into:
  - readDatabaseVersion(db): pure read, returns null when unseeded
  - seedDatabaseVersion(db): explicit write
  - getDatabaseVersion(db): pure, reports _dbVersion when unseeded (kept on the
    facade for display callers)

First-run seeding now happens explicitly in _createOrUpdateSchema. Behavior is
unchanged: fresh installs seed at _dbVersion and skip migrations; existing
installs read their stored version and migrate. A "get" no longer mutates.

Tests: 125/125 pass, no regressions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 22:00:09 +02:00
minibits-cashandClaude Opus 4.8 a18772df7d Harden DB layer: fail-loud migrations and parameterized IN clause
Tier 3 correctness hardening (two low-risk, high-value items; the reservation
db.transaction() rewrite remains a separate follow-up).

Migrations now fail loudly. runMigrations previously swallowed any batch error
with a low-severity log, so a failed migration left the app running on a schema
that didn't match the code — the silent-corruption class this whole effort is
about. It now throws (the batch is atomic, so a failure rolls back cleanly,
including the version bump, and the next launch retries from the same point).
This is consistent with instance.ts, where a failed CREATE TABLE already aborts
startup.

To make that safe, the v19 `DROP TABLE usersettings` becomes `DROP TABLE IF
EXISTS usersettings`. On devices that never had that table the DROP used to
error (swallowed), which also rolled back the version bump and left the
migration permanently stuck; making it defensive lets those devices migrate
forward cleanly. This is a behavior change for that specific upgrade cohort.

updateStatusesAsync no longer interpolates transaction ids into the SQL
(transactionIds.join(',')); the ids are bound as ? placeholders in both the
SELECT and UPDATE, matching the parameterized style used elsewhere. Empty input
now returns early instead of producing invalid `IN ()` SQL.

Tests: 125/125 pass, no regressions. (The migration runner itself has no unit
test because migrations.ts -> logService pulls Sentry/RN/store; covering it
would need a logger-injection refactor.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:52:11 +02:00
minibits-cashandClaude Opus 4.8 63d89bb6f8 Split SQLite monolith into focused db/ modules
Pure reorganization behind the existing Database facade — no behavior change.
The 1646-line services/sqlite.ts is broken into services/db/:

  errors.ts          dbError() helper
  connection.ts      op-sqlite adapter (from previous commit)
  schema.ts          table column definitions (single source of truth)
  migrations.ts      _dbVersion, getDatabaseVersion, ordered migration registry
  mappers.ts         transaction row normalizers
  instance.ts        _db singleton, getInstance, schema bootstrap, cleanAll
  transactionsRepo.ts / proofsRepo.ts / reservationsRepo.ts
  index.ts           assembles the Database facade, re-exports public types

services/sqlite.ts is now a thin `export * from './db'` barrel so every
existing import path (services, services/sqlite, ../../sqlite) resolves
unchanged. The Database.* contract and the exported types
(TransactionSearchFilters, LockedProofSnapshot, ReservationRow,
ReservationTransactionUpdate) are preserved.

Notable refactors folded in:
  - schema single source of truth: proofs/reservations columns are defined
    once; first-run CREATE and the v25 rebuild / v26 add are generated from
    them so they cannot drift. PROOFS_COLUMN_NAMES (drives the v25 copy) is
    tested to stay in sync with the table.
  - migration if-chain replaced by an ordered MIGRATIONS registry; adding a
    migration is now a one-line append.
  - updateStatusesAsync and expireAllAfterRecovery now use getInstance()
    instead of reaching for the module-global _db directly (the only two
    functions that did; behavior-equivalent, more robust before init).

New: __tests__/dbSchema.test.ts validates the generated DDL against node:sqlite.
Tests: 125/125 pass (was 121 + 4 new), no regressions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:46:15 +02:00
minibits-cashandClaude Opus 4.8 686b21a5bb Migrate SQLite from react-native-quick-sqlite to op-sqlite
Replaces react-native-quick-sqlite (8.2.7) with @op-engineering/op-sqlite
(16.2.0). The motivating bug: quick-sqlite's JSI binding silently dropped
non-bindable JS objects (e.g. a cashu-ts Amount instance), shifting the
parameter array and corrupting proof rows with no exception.

A new connection adapter (services/db/connection.ts) is the single seam to
the native library and reconciles op-sqlite's API differences so sqlite.ts
is nearly untouched:
  - op-sqlite execute() is async; sync is executeSync() -> our execute maps
    to executeSync, executeAsync maps to execute
  - executeBatch() is async-only with no insertId -> synchronous atomic batch
    emulated with BEGIN/COMMIT/ROLLBACK over executeSync
  - rows is a plain array -> re-wrapped into the WebSQL { _array, length,
    item() } shape the existing query code expects

The adapter also centralizes parameter sanitization (sanitizeParams): every
bind is coerced deliberately (Date -> ISO, numeric-like objects -> Number) or
rejected loudly, so the silent-skip footgun is structurally impossible.

Also collapses 33 repetitive try/catch AppError blocks into a dbError()
helper, which uniformly passes deliberate AppErrors (e.g. NOTFOUND_ERROR)
through instead of flattening them to DATABASE_ERROR (-109 net lines).

Tests: 121/121 pass, no regressions. Note: native rebuild and on-device
verification of the minibits.db file location are still required before ship.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:34:28 +02:00
minibits-cash c61e73a786 Fix loadMintFromCache 2026-05-29 13:40:54 +02:00
minibits-cash 872a602a31 Optimize ecash denominations per mint 2026-05-28 17:14:17 +02:00
minibits-cash 662d080b44 Basic transaction search 2026-05-26 23:18:39 +02:00
minibits-cash 3b91194025 Transaction lifecycle methods 2026-05-26 00:08:47 +02:00
minibits-cash 586f5c098d Fix wrong assignement of tId 2026-05-22 22:38:18 +02:00
minibits-cash 25330d3b73 Proofs reservation and rollback 2026-05-22 22:03:18 +02:00
minibits-cash 6d388947ef Error modal fix 2026-05-20 17:29:54 +02:00
minibits-cash 5e9a48d7c2 Fix nwc and donation flows 2026-05-20 16:56:21 +02:00
KeshavandGitHub a20044e4f7 NUT-12: validate offline ecash DLEQ proofs (#198) 2026-05-20 16:42:43 +02:00
minibits-cash afc1f0fbb6 Decode creqB payment requests, bump to v0.4.2-beta.5 2026-05-12 13:35:40 +02:00
minibits-cash 6e09ba95a7 Force swap if ecash notes to be used for payment overshoot amount a lot 2026-05-12 09:31:47 +02:00
minibits-cash 2e4d9328bb Upgrade to cashu-ts v4 2026-05-11 22:33:22 +02:00
tomaiooandGitHub 86f4525bf4 fix: remove dead code (#197)
Signed-off-by: tomaioo <203048277+tomaioo@users.noreply.github.com>
2026-05-11 15:16:31 +02:00
minibits-cash 6e63e941f3 Smooth resultModal transitions 2026-05-10 23:31:29 +02:00
minibits-cash 15c6fa7a43 Fix melt quote change recovery and async retrieval 2026-05-10 23:17:58 +02:00
minibits-cash 27734a1032 prepfer-async mode for melting 2026-05-09 23:40:27 +02:00
minibits-cash aa682ae3ad Refactor CashuPaymentRequest screen 2026-04-15 16:20:26 +02:00
minibits-cash 713e35fd7c Fix receive screen 2026-04-15 16:12:23 +02:00
minibits-cash 5a9293bed6 Refactor Topup screen 2026-04-15 15:56:51 +02:00
minibits-cash 8c2a363c36 Refactor TransferScreen state management 2026-04-15 15:30:58 +02:00
minibits-cash bb44c49797 Refactor SendScreen state management 2026-04-15 14:28:22 +02:00
minibits-cash a08f9945f0 Fix payment request pay with POST transport, Optimze ecash menu item. 2026-04-14 22:38:24 +02:00
minibits-cash e3ec278e28 Finalize keysets V2, bug fixes 2026-04-13 12:51:18 +02:00
minibits-cash 2c9d5c1cf9 Keysets v2 support 2026-04-12 23:06:28 +02:00
minibits-cash c0d425c0fd Fix swapByDenominationTask 2026-04-03 23:30:25 +02:00
minibits-cash 5be8148097 Fix InfoModal not showing 2026-04-01 13:28:32 +02:00
minibits-cash 3b286a20a6 Fix js error in iOS 2026-04-01 11:54:26 +02:00
minibits-cash dcc12ea006 Remove duplicate import 2026-03-31 13:21:42 +02:00
f14e04b8b1 Add CHF currency support (#195)
Co-authored-by: User <user@example.com>
Co-authored-by: Minibits <138401554+minibits-cash@users.noreply.github.com>
2026-03-31 13:19:04 +02:00
minibits-cash 85eca1d267 Upgrade rn change icon, finally fix app open on push tap 2026-03-30 23:26:12 +02:00
minibits-cash c67b48993f Add CHF rate 2026-03-28 23:19:09 +01:00
minibits-cash 41bf281519 Fix app opening on notfification tap 2026-03-28 22:07:29 +01:00
minibits-cash 98a4fb5073 Fix race condition in revert transaction, causing aceess to dead mobx proof models. Patch hotUpdater 2026-03-26 16:16:35 +01:00
minibits-cash 26aac2dee8 Fix error and info modal on Android 2026-03-24 15:20:39 +01:00
minibits-cash 9aca87f66a Amount style update, iOS icon fix 2026-03-23 14:59:26 +01:00
minibits-cash c0312d770c Android navigation bar theming, hotupdater switch to fingerprint deployment 2026-03-18 05:47:10 -07:00
minibits-cash 6bd42db350 Tune Optimize ecash screen UI 2026-03-16 18:48:38 -07:00
minibits-cash 81ce599a1d New optimize ecash screen, backup to a file 2026-03-16 18:24:48 -07:00
minibits-cash 8e40d75050 Terms link 2026-03-16 15:52:18 -07:00
minibits-cash 380aaa54a7 Fix welcome screen tet overflow 2026-03-16 15:26:39 -07:00
minibits-cash 80b4c30416 Revert some font changes 2026-03-16 07:49:12 -07:00