Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/packages/storage/database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:io';

import 'package:drift/drift.dart';
import 'package:drift/native.dart';
import 'package:flutter/foundation.dart' show visibleForTesting;
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:realunit_wallet/packages/storage/asset_storage.dart';
Expand Down Expand Up @@ -51,6 +52,10 @@ Future<bool> tryOpeningDatabase(String encryptionPassword) async {
class AppDatabase extends _$AppDatabase {
AppDatabase(String encryptionPassword) : super(_openDatabase(encryptionPassword));

/// In-memory database for unit tests. Bypasses SQLCipher and path_provider.
@visibleForTesting
AppDatabase.forTesting(super.executor);

@override
int get schemaVersion => 2;

Expand Down
8 changes: 8 additions & 0 deletions lib/screens/buy/cubits/buy_converter/buy_converter_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ class BuyConverterCubit extends Cubit<BuyConverterState> {

_fiatDebounce?.cancel();
_fiatDebounce = Timer(const Duration(milliseconds: 100), () async {
if (isClosed) return;
emit(state.copyWith(loading: true));

try {
final result = await _brokerbotService.getBuyShares(value, state.currency);
if (isClosed) return;
emit(
state.copyWith(
sharesText: result.shares.toString(),
Expand All @@ -34,6 +36,7 @@ class BuyConverterCubit extends Cubit<BuyConverterState> {
);
} catch (e) {
developer.log(e.toString());
if (isClosed) return;
emit(state.copyWith(loading: false));
}
});
Expand All @@ -45,10 +48,12 @@ class BuyConverterCubit extends Cubit<BuyConverterState> {

_sharesDebounce?.cancel();
_sharesDebounce = Timer(const Duration(milliseconds: 100), () async {
if (isClosed) return;
emit(state.copyWith(loading: true));

try {
final result = await _brokerbotService.getBuyPrice(value, state.currency);
if (isClosed) return;
emit(
state.copyWith(
fiatText: result.totalCost.toStringAsFixed(_fractionDigits(value)),
Expand All @@ -57,6 +62,7 @@ class BuyConverterCubit extends Cubit<BuyConverterState> {
);
} catch (e) {
developer.log(e.toString());
if (isClosed) return;
emit(state.copyWith(loading: false));
}
});
Expand All @@ -67,6 +73,7 @@ class BuyConverterCubit extends Cubit<BuyConverterState> {

try {
final result = await _brokerbotService.getBuyShares(state.fiatText, currency);
if (isClosed) return;
emit(
state.copyWith(
sharesText: result.shares.toString(),
Expand All @@ -76,6 +83,7 @@ class BuyConverterCubit extends Cubit<BuyConverterState> {
);
} catch (e) {
developer.log(e.toString());
if (isClosed) return;
emit(
state.copyWith(
loading: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class BuyPaymentInfoCubit extends Cubit<BuyPaymentInfoState> {
);

final newState = await _completer!.value;
if (isClosed) return;
emit(newState);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ class SellBankAccountsCubit extends Cubit<SellBankAccountsState> {
emit(SellBankAccountsLoading(state.accounts));

await _dfxBankAccountService.createBankAccount(iban, label);
if (isClosed) return;
await _loadBankAccounts();
} catch (e) {
developer.log(e.toString());
if (isClosed) return;
emit(SellBankAccountsAddFailure(state.accounts, e.toString()));
}
}
Expand All @@ -37,18 +39,22 @@ class SellBankAccountsCubit extends Cubit<SellBankAccountsState> {
id: bankAccount.id,
isActive: false,
);
if (isClosed) return;
await _loadBankAccounts();
} catch (e) {
developer.log(e.toString());
if (isClosed) return;
emit(SellBankAccountsUpdateFailure(state.accounts));
}
}

Future<void> _loadBankAccounts() async {
if (isClosed) return;
try {
emit(SellBankAccountsLoading(state.accounts));

final dto = await _dfxBankAccountService.getBankAccounts();
if (isClosed) return;
final bankAccounts = dto
.map(
(bankAccount) => BankAccount(
Expand All @@ -63,6 +69,7 @@ class SellBankAccountsCubit extends Cubit<SellBankAccountsState> {
emit(SellBankAccountsSuccess(bankAccounts));
} catch (e) {
developer.log(e.toString());
if (isClosed) return;
emit(const SellBankAccountsLoadFailure());
}
}
Expand Down
2 changes: 2 additions & 0 deletions lib/screens/sell/cubits/sell_confirm/sell_confirm_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ class SellConfirmCubit extends Cubit<SellConfirmState> {
try {
emit(SellConfirmLoading());
await _sellPaymentInfoService.confirmPayment(paymentInfo);
if (isClosed) return;
emit(SellConfirmSuccess());
} catch (e) {
if (isClosed) return;
emit(SellConfirmFailure(e.toString()));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ class SellConverterCubit extends Cubit<SellConverterState> {

_fiatDebounce?.cancel();
_fiatDebounce = Timer(const Duration(milliseconds: 100), () async {
if (isClosed) return;
emit(state.copyWith(loading: true));

try {
final result = await _brokerbotService.getSellShares(value, currency);
if (isClosed) return;
emit(
state.copyWith(
sharesText: result.shares.toString(),
Expand All @@ -34,6 +36,7 @@ class SellConverterCubit extends Cubit<SellConverterState> {
);
} catch (e) {
developer.log(e.toString());
if (isClosed) return;
emit(state.copyWith(loading: false));
}
});
Expand All @@ -45,10 +48,12 @@ class SellConverterCubit extends Cubit<SellConverterState> {

_sharesDebounce?.cancel();
_sharesDebounce = Timer(const Duration(milliseconds: 100), () async {
if (isClosed) return;
emit(state.copyWith(loading: true));

try {
final result = await _brokerbotService.getSellPrice(value, currency);
if (isClosed) return;
emit(
state.copyWith(
fiatText: result.estimatedAmount.toStringAsFixed(_fractionDigits(value)),
Expand All @@ -57,6 +62,7 @@ class SellConverterCubit extends Cubit<SellConverterState> {
);
} catch (e) {
developer.log(e.toString());
if (isClosed) return;
emit(state.copyWith(loading: false));
}
});
Expand All @@ -66,6 +72,7 @@ class SellConverterCubit extends Cubit<SellConverterState> {
emit(state.copyWith(loading: true));
try {
final result = await _brokerbotService.getBuyPrice(state.sharesText, currency);
if (isClosed) return;
emit(
state.copyWith(
fiatText: result.totalCost.toStringAsFixed(_fractionDigits(state.sharesText)),
Expand All @@ -75,6 +82,7 @@ class SellConverterCubit extends Cubit<SellConverterState> {
);
} catch (e) {
developer.log(e.toString());
if (isClosed) return;
emit(
state.copyWith(
loading: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class SellPaymentInfoCubit extends Cubit<SellPaymentInfoState> {
iban,
currency: currency,
);
if (isClosed) return;

// Only the backend knows the current per-currency limits, exchange
// rates and any compliance gating — when it tags the quote
Expand All @@ -70,6 +71,7 @@ class SellPaymentInfoCubit extends Cubit<SellPaymentInfoState> {
final isBitbox = _appStore.wallet.walletType == WalletType.bitbox;
emit(SellPaymentInfoSuccess(paymentInfo, isBitbox: isBitbox));
} on KycLevelRequiredException catch (e) {
if (isClosed) return;
emit(
SellPaymentInfoFailure(
PaymentInfoError.kycRequired,
Expand All @@ -78,13 +80,15 @@ class SellPaymentInfoCubit extends Cubit<SellPaymentInfoState> {
),
);
} on RegistrationRequiredException catch (e) {
if (isClosed) return;
emit(
SellPaymentInfoFailure(
PaymentInfoError.registrationRequired,
message: e.toString(),
),
);
} on BitboxNotConnectedException catch (e) {
if (isClosed) return;
emit(
SellPaymentInfoFailure(
PaymentInfoError.bitboxDisconnected,
Expand All @@ -93,6 +97,7 @@ class SellPaymentInfoCubit extends Cubit<SellPaymentInfoState> {
);
} catch (e) {
developer.log(e.toString());
if (isClosed) return;
emit(
SellPaymentInfoFailure(
PaymentInfoError.unknown,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ class SettingsTaxReportCubit extends Cubit<SettingsTaxReportState> {
currency: currency,
language: language,
);
if (isClosed) return;
final file = await _createFileFromBytes(response.pdfData, date);
if (isClosed) return;

emit(SettingsTaxReportSuccess(file.path));
} catch (e) {
if (isClosed) return;
emit(SettingsTaxReportFailure(e.toString()));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:realunit_wallet/models/asset.dart';
import 'package:realunit_wallet/models/transaction.dart';
Expand All @@ -12,10 +14,13 @@ class TransactionHistoryFilterCubit extends Cubit<TransactionHistoryFilterState>
required String walletAddress,
int? limit,
}) : super(TransactionHistoryFilterState()) {
_repository.watchTransactionsOfAssets([asset], walletAddress).listen(_onTransactionsUpdated);
_subscription = _repository.watchTransactionsOfAssets([asset], walletAddress).listen(
_onTransactionsUpdated,
);
}

final TransactionRepository _repository;
StreamSubscription<List<Transaction>>? _subscription;

void _onTransactionsUpdated(List<Transaction> transactions) {
emit(
Expand Down Expand Up @@ -56,4 +61,10 @@ class TransactionHistoryFilterCubit extends Cubit<TransactionHistoryFilterState>
return afterStart && beforeEnd;
}).toList();
}

@override
Future<void> close() {
_subscription?.cancel();
return super.close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ class TransactionHistoryMultiReceiptCubit extends Cubit<TransactionHistoryMultiR
emit(const TransactionHistoryMultiReceiptLoading());

final response = await _pdfService.getTransactionsReceipt(ids, currency: currency);
if (isClosed) return;
final file = await _createFileFromBytes(response.pdfData);
if (isClosed) return;

emit(TransactionHistoryMultiReceiptSuccess(file.path));
} catch (e) {
if (isClosed) return;
emit(TransactionHistoryMultiReceiptFailure(e.toString()));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ class TransactionHistoryReceiptCubit extends Cubit<TransactionHistoryReceiptStat
emit(const TransactionHistoryReceiptLoading());

final response = await _pdfService.getTransactionReceipt(txId, currency: currency);
if (isClosed) return;
final file = await _createFileFromBytes(response.pdfData, txId);
if (isClosed) return;

emit(TransactionHistoryReceiptSuccess(file.path));
} catch (e) {
if (isClosed) return;
emit(TransactionHistoryReceiptFailure(e.toString()));
}
}
Expand Down
24 changes: 12 additions & 12 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,10 @@ packages:
dependency: "direct main"
description:
name: characters
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev"
source: hosted
version: "1.4.1"
version: "1.4.0"
charcode:
dependency: transitive
description:
Expand Down Expand Up @@ -915,18 +915,18 @@ packages:
dependency: transitive
description:
name: matcher
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev"
source: hosted
version: "0.12.19"
version: "0.12.17"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
version: "0.13.0"
version: "0.11.1"
meta:
dependency: transitive
description:
Expand Down Expand Up @@ -1408,26 +1408,26 @@ packages:
dependency: transitive
description:
name: test
sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7"
sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7"
url: "https://pub.dev"
source: hosted
version: "1.30.0"
version: "1.26.3"
test_api:
dependency: transitive
description:
name: test_api
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
url: "https://pub.dev"
source: hosted
version: "0.7.10"
version: "0.7.7"
test_core:
dependency: transitive
description:
name: test_core
sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51"
sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0"
url: "https://pub.dev"
source: hosted
version: "0.6.16"
version: "0.6.12"
typed_data:
dependency: transitive
description:
Expand Down
11 changes: 11 additions & 0 deletions test/packages/service/balance_service_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,17 @@ void main() {

verifyNever(() => balanceRepository.saveBalance(any()));
});

test('updateBalance with malformed JSON body does not crash', () async {
final appStore = buildAppStore(
(_) async => http.Response('not json', 200),
);

final service = BalanceService(balanceRepository, appStore);
await service.updateBalance('0xTestAddress');

verifyNever(() => balanceRepository.saveBalance(any()));
});
});

test('getBalance delegates to BalanceRepository.getBalance', () async {
Expand Down
Loading
Loading