fix: log previously-swallowed errors in ShopinBit and CakePay flows
What changed, and why it matters
This commit only adds logging to error paths in the ShopinBit and CakePay shopping/payment flows. It does not change how errors are handled or fix any underlying bug; it simply records details that were previously silently ignored. There is no direct security fix here, but better logging can help developers detect and diagnose future problems.
Treat as a routine observability improvement. Review whether any of the newly logged exceptions indicate latent bugs or reliability issues that should be addressed separately, but no immediate security action is required based on this commit alone.
Security signals we found
Previously swallowed exceptions are now logged, which improves observability but does not remediate any vulnerability
No input validation, bounds checking, or authorization changes are present
No cryptographic or secret-handling changes are present
No network or API behavior changes are present
Evidence from the diff
The patch replaces empty catch blocks and debugPrint calls with structured logging using a Logging utility. Affected paths include CakePay order amount parsing, ShopinBit offer refresh, payment amount parsing, payment info fetch, customer key generation/setting, address submission, request submission, and ticket refresh loops. No exception handling logic, validation, or control flow is altered beyond emitting log messages.
Changed components
lib/pages/cakepay/cakepay_order_view.dartlib/pages/shopinbit/shopinbit_offer_view.dartlib/pages/shopinbit/shopinbit_payment_shared.dartlib/pages/shopinbit/shopinbit_settings_view.dartlib/pages/shopinbit/shopinbit_shipping_view.dartlib/pages/shopinbit/step_4_components/shopinbit_step4_submit.dartlib/services/shopinbit/shopinbit_service.dartInspect captured patch +68 / −15
diff --git a/lib/pages/cakepay/cakepay_order_view.dart b/lib/pages/cakepay/cakepay_order_view.dart
index 1f5cead..4232a4e 100644
--- a/lib/pages/cakepay/cakepay_order_view.dart
+++ b/lib/pages/cakepay/cakepay_order_view.dart
@@ -16,6 +16,7 @@ import '../../services/cakepay/src/models/order.dart';
import '../../themes/stack_colors.dart';
import '../../utilities/amount/amount.dart';
import '../../utilities/assets.dart';
+import '../../utilities/logger.dart';
import '../../utilities/text_styles.dart';
import '../../utilities/util.dart';
import '../../wallets/crypto_currency/crypto_currency.dart';
@@ -224,7 +225,13 @@ class _CakePayOrderViewState extends ConsumerState<CakePayOrderView> {
Decimal.parse(option.amountFrom.toString()),
fractionDigits: coin.fractionDigits,
);
- } catch (_) {}
+ } catch (e, s) {
+ Logging.instance.e(
+ "Failed to parse CakePay order amount '${option.amountFrom}'",
+ error: e,
+ stackTrace: s,
+ );
+ }
_navigateToSendFrom(
coin: coin,
diff --git a/lib/pages/shopinbit/shopinbit_offer_view.dart b/lib/pages/shopinbit/shopinbit_offer_view.dart
index 54ac5ba..a8fd750 100644
--- a/lib/pages/shopinbit/shopinbit_offer_view.dart
+++ b/lib/pages/shopinbit/shopinbit_offer_view.dart
@@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../providers/global/shopin_bit_service_provider.dart';
import '../../themes/stack_colors.dart';
+import '../../utilities/logger.dart';
import '../../utilities/show_loading.dart';
import '../../utilities/text_styles.dart';
import '../../utilities/util.dart';
@@ -45,8 +46,13 @@ class _ShopInBitOfferViewState extends ConsumerState<ShopInBitOfferView> {
// Refresh pulls /full (offer product + price) into the ticket row, which
// we then read reactively from the DB stream.
await ref.read(pShopinBitService).refreshOne(widget.apiTicketId);
- } catch (_) {
- // Fall back to whatever the row already has.
+ } catch (e, s) {
+ Logging.instance.w(
+ "Failed to refresh ShopInBit offer ${widget.apiTicketId}, "
+ "using cached data",
+ error: e,
+ stackTrace: s,
+ );
} finally {
if (mounted) setState(() => _loading = false);
}
diff --git a/lib/pages/shopinbit/shopinbit_payment_shared.dart b/lib/pages/shopinbit/shopinbit_payment_shared.dart
index 93a6974..befd4e2 100644
--- a/lib/pages/shopinbit/shopinbit_payment_shared.dart
+++ b/lib/pages/shopinbit/shopinbit_payment_shared.dart
@@ -13,6 +13,7 @@ import '../../themes/stack_colors.dart';
import '../../utilities/address_utils.dart';
import '../../utilities/amount/amount.dart';
import '../../utilities/default_eth_tokens.dart';
+import '../../utilities/logger.dart';
import '../../utilities/text_styles.dart';
import '../../utilities/util.dart';
import '../../wallets/crypto_currency/crypto_currency.dart';
@@ -85,7 +86,13 @@ ShopInBitPaymentTarget parseShopInBitPaymentTarget({
Decimal.parse(amountStr),
fractionDigits: fractionDigits,
);
- } catch (_) {}
+ } catch (e, s) {
+ Logging.instance.e(
+ "Failed to parse ShopInBit payment amount '$amountStr'",
+ error: e,
+ stackTrace: s,
+ );
+ }
}
return ShopInBitPaymentTarget(address: address, amount: amount);
@@ -244,8 +251,12 @@ Future<PaymentInfo?> fetchShopInBitPaymentInfo(
if (!putResp.hasError && putResp.value != null) {
return putResp.value;
}
- } catch (_) {
- // Degrade to polling-only.
+ } catch (e, s) {
+ Logging.instance.w(
+ "fetchShopInBitPaymentInfo failed, degrading to polling-only",
+ error: e,
+ stackTrace: s,
+ );
}
return null;
}
diff --git a/lib/pages/shopinbit/shopinbit_settings_view.dart b/lib/pages/shopinbit/shopinbit_settings_view.dart
index 757c771..fd78339 100644
--- a/lib/pages/shopinbit/shopinbit_settings_view.dart
+++ b/lib/pages/shopinbit/shopinbit_settings_view.dart
@@ -10,6 +10,7 @@ import '../../providers/global/shopin_bit_service_provider.dart';
import '../../providers/providers.dart';
import '../../themes/stack_colors.dart';
import '../../utilities/assets.dart';
+import '../../utilities/logger.dart';
import '../../utilities/text_styles.dart';
import '../../utilities/util.dart';
import '../../widgets/background.dart';
@@ -86,7 +87,12 @@ class _ShopInBitSettingsViewState extends ConsumerState<ShopInBitSettingsView> {
),
);
}
- } catch (e) {
+ } catch (e, s) {
+ Logging.instance.e(
+ "Failed to generate ShopInBit customer key",
+ error: e,
+ stackTrace: s,
+ );
if (mounted) {
await showDialog<void>(
context: context,
@@ -131,7 +137,12 @@ class _ShopInBitSettingsViewState extends ConsumerState<ShopInBitSettingsView> {
),
);
}
- } catch (e) {
+ } catch (e, s) {
+ Logging.instance.e(
+ "Failed to set ShopInBit customer key",
+ error: e,
+ stackTrace: s,
+ );
if (mounted) {
await showDialog<void>(
context: context,
diff --git a/lib/pages/shopinbit/shopinbit_shipping_view.dart b/lib/pages/shopinbit/shopinbit_shipping_view.dart
index 1f3c412..234ccdf 100644
--- a/lib/pages/shopinbit/shopinbit_shipping_view.dart
+++ b/lib/pages/shopinbit/shopinbit_shipping_view.dart
@@ -11,6 +11,7 @@ import '../../services/shopinbit/src/models/payment.dart';
import '../../themes/stack_colors.dart';
import '../../utilities/assets.dart';
import '../../utilities/constants.dart';
+import '../../utilities/logger.dart';
import '../../utilities/text_styles.dart';
import '../../utilities/util.dart';
import '../../widgets/background.dart';
@@ -213,12 +214,12 @@ class _ShopInBitShippingViewState extends ConsumerState<ShopInBitShippingView> {
if (resp.hasError) {
// Sandbox may fail here; continue anyway.
- debugPrint("submitAddress failed: ${resp.exception?.message}");
+ Logging.instance.w("submitAddress failed", error: resp.exception);
}
paymentInfo = await fetchShopInBitPaymentInfo(ref, widget.apiTicketId);
- } catch (e) {
- debugPrint("submitAddress threw: $e");
+ } catch (e, s) {
+ Logging.instance.e("submitAddress threw", error: e, stackTrace: s);
} finally {
if (mounted) setState(() => _submitting = false);
}
diff --git a/lib/pages/shopinbit/step_4_components/shopinbit_step4_submit.dart b/lib/pages/shopinbit/step_4_components/shopinbit_step4_submit.dart
index e432f1e..c0fa9a8 100644
--- a/lib/pages/shopinbit/step_4_components/shopinbit_step4_submit.dart
+++ b/lib/pages/shopinbit/step_4_components/shopinbit_step4_submit.dart
@@ -5,6 +5,7 @@ import "package:flutter/material.dart";
import "../../../models/shopinbit/shopinbit_request_draft.dart";
import "../../../services/shopinbit/shopinbit_service.dart";
import "../../../services/shopinbit/src/models/ticket.dart";
+import "../../../utilities/logger.dart";
import "../../../utilities/util.dart";
import "../../../widgets/stack_dialog.dart";
import "../shopinbit_order_created.dart";
@@ -54,7 +55,12 @@ Future<void> submitShopInBitRequest(
context,
).pushNamed(ShopInBitOrderCreated.routeName, arguments: ref.id),
);
- } catch (e) {
+ } catch (e, s) {
+ Logging.instance.e(
+ "Failed to create ShopInBit request",
+ error: e,
+ stackTrace: s,
+ );
if (context.mounted) {
await showDialog<void>(
context: context,
diff --git a/lib/services/shopinbit/shopinbit_service.dart b/lib/services/shopinbit/shopinbit_service.dart
index 85ef51c..9f39c8a 100644
--- a/lib/services/shopinbit/shopinbit_service.dart
+++ b/lib/services/shopinbit/shopinbit_service.dart
@@ -4,6 +4,7 @@ import "package:drift/drift.dart";
import "../../db/drift/shared_db/shared_database.dart";
import "../../models/shopinbit/shopinbit_enums.dart";
+import "../../utilities/logger.dart";
import "src/api_response.dart";
import "src/client.dart";
import "src/models/message.dart";
@@ -61,7 +62,13 @@ class ShopInBitService {
final ApiResponse<List<TicketRef>> resp = await client.getTicketsByCustomer(
key,
);
- if (resp.hasError || resp.value == null) return;
+ if (resp.hasError || resp.value == null) {
+ Logging.instance.w(
+ "ShopInBitService.refreshAll: failed to fetch ticket list",
+ error: resp.exception,
+ );
+ return;
+ }
await Future.wait(resp.value!.map((ref) => _refreshRef(ref, key)));
}
@@ -145,8 +152,12 @@ class ShopInBitService {
for (final TicketRef ref in candidates) {
try {
await _refreshRef(ref, key);
- } catch (_) {
- // try the next candidate
+ } catch (e, s) {
+ Logging.instance.w(
+ "Failed to refresh candidate ticket ${ref.id}, trying next",
+ error: e,
+ stackTrace: s,
+ );
}
if (await db.shopInBitTicketsDao.getByApiId(ref.id) != null) {
return ref.id;
Why this scored 20/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.