fix(export): write the transaction CSV atomically and report failures

The transaction export streamed rows straight into an ofstream. A write
that failed partway, on a full disk or removable media, left a truncated
CSV on disk behind a success toast. The CSV formatting also lived inline
in the dialog with no test coverage.

- The CSV is now built in memory and written atomically (temp file plus
  rename), so a write failure is reported with an error toast and leaves
  no partial file.
- Formatting moves into a reusable helper, and the timestamp conversions
  use the thread-safe localtime variants and tolerate a conversion
  failure rather than dereferencing a null result.

Tests: field escaping neutralises formula-injection prefixes and quotes
special characters, and the full CSV has the expected header and rows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-13 16:00:10 -05:00
co-authored by Claude Opus 4.8
parent f76d71fede
commit bbe2bf94dc
5 changed files with 124 additions and 58 deletions
+2
View File
@@ -513,6 +513,7 @@ set(APP_SOURCES
src/wallet/lite_wallet_server_selection_adapter.cpp
src/wallet/lite_wallet_lifecycle_service.cpp
src/data/wallet_state.cpp
src/data/transaction_csv.cpp
src/data/transaction_history_cache.cpp
src/data/transaction_history_store_policy.cpp
src/ui/theme.cpp
@@ -1261,6 +1262,7 @@ if(BUILD_TESTING)
src/util/text_format.cpp
src/util/image_decode_core.cpp
src/data/wallet_state.cpp
src/data/transaction_csv.cpp
src/data/transaction_history_cache.cpp
src/data/transaction_history_store_policy.cpp
src/data/address_book.cpp