What changed, and why it matters
This commit changes how Stack Wallet's Cardano wallet checks account balances and transaction history. Previously, the app directly asked a Blockfrost service for a list of funds/transactions for the current receiving address. If the address had never been used on the network, that request could fail or behave inconsistently. Now the app first asks Blockfrost whether the address exists, explicitly handles the common '404 Not found' response, and skips the fund/transaction queries for unseen addresses. This is a robustness/cleanup change rather than a clear security fix, but it removes a class of unhandled API errors that could affect wallet behavior.
Treat as a routine robustness improvement. Review whether other wallet implementations have similar unhandled 'address not seen' errors with their API providers, and consider adding tests for the 404 path. No urgent security action is indicated by the diff alone.
Security signals we found
Adds explicit handling for 404 'Not found' from a third-party blockchain API provider
Prevents unhandled exceptions during balance refresh for unused/unseen Cardano addresses
Avoids unnecessary API calls that could leak the current receiving address to the provider when no funds exist
No input validation, cryptography, or authorization logic changed
Evidence from the diff
In lib/wallets/wallet/impl/cardano_wallet.dart, a new private method _checkAddressIsFound() queries Blockfrost for the specific address and catches BlockfrostError with statusCode 404 and error ‘Not found’, returning false in that case and rethrowing other errors. Both updateBalance() and a transaction-list update method now call this helper and supply empty result lists when the address is not yet seen, avoiding BlockfrostRequestAddressUTXOsOfAGivenAsset and BlockfrostRequestAddressTransactions calls on unseen addresses. The change imports BlockfrostError from on_chain/ada/src/provider/exception/blockfrost_api_error.dart.
Changed components
lib/wallets/wallet/impl/cardano_wallet.dartCardanoWallet.updateBalance()CardanoWallet transaction history refresh methodBlockfrost provider integrationInspect captured patch +44 / −13
diff --git a/lib/wallets/wallet/impl/cardano_wallet.dart b/lib/wallets/wallet/impl/cardano_wallet.dart
index 1583123..4654413 100644
--- a/lib/wallets/wallet/impl/cardano_wallet.dart
+++ b/lib/wallets/wallet/impl/cardano_wallet.dart
@@ -8,6 +8,7 @@ import 'package:blockchain_utils/bip/cardano/mnemonic/cardano_icarus_seed_genera
import 'package:blockchain_utils/bip/cardano/shelley/cardano_shelley.dart';
import 'package:isar_community/isar.dart';
import 'package:on_chain/ada/ada.dart';
+import 'package:on_chain/ada/src/provider/exception/blockfrost_api_error.dart';
import 'package:socks5_proxy/socks.dart';
import 'package:tuple/tuple.dart';
@@ -418,19 +419,45 @@ class CardanoWallet extends Bip39Wallet<Cardano> {
});
}
+ Future<bool> _checkAddressIsFound() async {
+ try {
+ await blockfrostProvider!.request(
+ BlockfrostRequestSpecificAddress(
+ ADAAddress.fromAddress((await getCurrentReceivingAddress())!.value),
+ ),
+ );
+ return true;
+ } on BlockfrostError catch (e, s) {
+ if (e.statusCode == 404 && e.error == "Not found") {
+ Logging.instance.i(
+ "Ada address not seen on network yet",
+ error: e,
+ stackTrace: s,
+ );
+ return false;
+ } else {
+ rethrow;
+ }
+ }
+ }
+
@override
Future<void> updateBalance() async {
try {
await updateProvider();
- final addressUtxos = await blockfrostProvider!.request(
- BlockfrostRequestAddressUTXOsOfAGivenAsset(
- address: ADAAddress.fromAddress(
- (await getCurrentReceivingAddress())!.value,
- ),
- asset: "lovelace",
- ),
- );
+ final addressExists = await _checkAddressIsFound();
+
+ final addressUtxos = addressExists
+ ? await blockfrostProvider!.request(
+ BlockfrostRequestAddressUTXOsOfAGivenAsset(
+ address: ADAAddress.fromAddress(
+ (await getCurrentReceivingAddress())!.value,
+ ),
+ asset: "lovelace",
+ ),
+ )
+ : <ADAAccountUTXOResponse>[];
BigInt totalBalanceInLovelace = BigInt.parse("0");
for (final utxo in addressUtxos) {
@@ -498,13 +525,17 @@ class CardanoWallet extends Bip39Wallet<Cardano> {
try {
await updateProvider();
+ final addressExists = await _checkAddressIsFound();
+
final currentAddr = (await getCurrentReceivingAddress())!.value;
- final txsList = await blockfrostProvider!.request(
- BlockfrostRequestAddressTransactions(
- ADAAddress.fromAddress(currentAddr),
- ),
- );
+ final txsList = addressExists
+ ? await blockfrostProvider!.request(
+ BlockfrostRequestAddressTransactions(
+ ADAAddress.fromAddress(currentAddr),
+ ),
+ )
+ : <ADATransactionSummaryInfoResponse>[];
final parsedTxsList = List<Tuple2<isar.Transaction, Address>>.empty(
growable: true,
Why this scored 24/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.