diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index 82422ab3c..4494790cc 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -1,12 +1,17 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart'; import 'package:stackwallet/pages/send_view/sub_widgets/sending_transaction_dialog.dart'; import 'package:stackwallet/pages/wallet_view/wallet_view.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/route_generator.dart'; +import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart'; import 'package:stackwallet/utilities/cfcolors.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/flush_bar_type.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; @@ -40,25 +45,25 @@ class _ConfirmTransactionViewState late final String routeOnSuccessName; Future _attemptSend(BuildContext context) async { - showDialog( + unawaited(showDialog( context: context, useSafeArea: false, barrierDismissible: false, builder: (context) { return const SendingTransactionDialog(); }, - ); + )); final note = transactionInfo["note"] as String? ?? ""; final manager = - ref.read(walletsChangeNotifierProvider).getManager(walletId); + ref.read(walletsChangeNotifierProvider).getManager(walletId); try { final txid = await manager.confirmSend(txData: transactionInfo); - manager.refresh(); + unawaited(manager.refresh()); // save note - ref + await ref .read(notesServiceChangeNotifierProvider(walletId)) .editOrAddNote(txid: txid, note: note); @@ -66,12 +71,26 @@ class _ConfirmTransactionViewState if (mounted) { Navigator.of(context).popUntil(ModalRoute.withName(routeOnSuccessName)); } + } on BadEpicHttpAddressException catch (_) { + if (mounted) { + // pop building dialog + Navigator.of(context).pop(); + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: + "Connection failed. Please check the address and try again.", + context: context, + ), + ); + return; + } } catch (e, s) { debugPrint("$e\n$s"); // pop sending dialog Navigator.of(context).pop(); - showDialog( + await showDialog( context: context, useSafeArea: false, barrierDismissible: true, @@ -81,10 +100,10 @@ class _ConfirmTransactionViewState message: e.toString(), rightButton: TextButton( style: Theme.of(context).textButtonTheme.style?.copyWith( - backgroundColor: MaterialStateProperty.all( - CFColors.buttonGray, - ), - ), + backgroundColor: MaterialStateProperty.all( + CFColors.buttonGray, + ), + ), child: Text( "Ok", style: STextStyles.button.copyWith( @@ -193,9 +212,9 @@ class _ConfirmTransactionViewState .select((value) => value.locale), ), )} ${ref.watch( - managerProvider - .select((value) => value.coin), - ).ticker}", + managerProvider + .select((value) => value.coin), + ).ticker}", style: STextStyles.itemSubtitle12, textAlign: TextAlign.right, ), @@ -221,9 +240,9 @@ class _ConfirmTransactionViewState .select((value) => value.locale), ), )} ${ref.watch( - managerProvider - .select((value) => value.coin), - ).ticker}", + managerProvider + .select((value) => value.coin), + ).ticker}", style: STextStyles.itemSubtitle12, textAlign: TextAlign.right, ), @@ -273,9 +292,9 @@ class _ConfirmTransactionViewState .select((value) => value.locale), ), )} ${ref.watch( - managerProvider - .select((value) => value.coin), - ).ticker}", + managerProvider + .select((value) => value.coin), + ).ticker}", style: STextStyles.itemSubtitle12, textAlign: TextAlign.right, ), @@ -287,18 +306,18 @@ class _ConfirmTransactionViewState ), TextButton( style: - Theme.of(context).textButtonTheme.style?.copyWith( - backgroundColor: - MaterialStateProperty.all( - CFColors.stackAccent, - ), - ), + Theme.of(context).textButtonTheme.style?.copyWith( + backgroundColor: + MaterialStateProperty.all( + CFColors.stackAccent, + ), + ), onPressed: () async { final unlocked = await Navigator.push( context, RouteGenerator.getRoute( shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, + RouteGenerator.useMaterialPageRoute, builder: (_) => const LockscreenView( showBackButton: true, popOnSuccess: true, @@ -306,9 +325,9 @@ class _ConfirmTransactionViewState routeOnSuccess: "", biometricsCancelButtonString: "CANCEL", biometricsLocalizedReason: - "Authenticate to send transaction", + "Authenticate to send transaction", biometricsAuthenticationTitle: - "Confirm Transaction", + "Confirm Transaction", ), settings: const RouteSettings( name: "/confirmsendlockscreen"), @@ -316,7 +335,7 @@ class _ConfirmTransactionViewState ); if (unlocked is bool && unlocked && mounted) { - _attemptSend(context); + unawaited(_attemptSend(context)); } }, child: Text( diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart index 4c3f7863d..53a320666 100644 --- a/lib/services/coins/epiccash/epiccash_wallet.dart +++ b/lib/services/coins/epiccash/epiccash_wallet.dart @@ -40,6 +40,17 @@ const int MINIMUM_CONFIRMATIONS = 10; const String GENESIS_HASH_MAINNET = ""; const String GENESIS_HASH_TESTNET = ""; +class BadEpicHttpAddressException implements Exception { + final String? message; + + BadEpicHttpAddressException({this.message}); + + @override + String toString() { + return "BadEpicHttpAddressException: $message"; + } +} + // isolate Map isolates = {}; @@ -185,6 +196,29 @@ Future executeNative(Map arguments) async { sendPort.send(result); return; } + } else if (function == "txHttpSend") { + final wallet = arguments['wallet'] as String?; + final selectionStrategyIsAll = arguments['selectionStrategyIsAll'] as int?; + final minimumConfirmations = arguments['minimumConfirmations'] as int?; + final message = arguments['message'] as String?; + final amount = arguments['amount'] as int?; + final address = arguments['address'] as String?; + + Map result = {}; + + if (!(wallet == null || + selectionStrategyIsAll == null || + minimumConfirmations == null || + message == null || + amount == null || + address == null)) { + var res = await txHttpSend(wallet, selectionStrategyIsAll, + minimumConfirmations, message, amount, address); + result['result'] = res; + sendPort.send(result); + return; + } + } Logging.instance.log( "Error Arguments for $function not formatted correctly", @@ -717,32 +751,67 @@ class EpicCashWallet extends CoinServiceAPI { // TODO determine whether it is worth sending change to a change address. dynamic message; - await m.protect(() async { - ReceivePort receivePort = await getIsolate({ - "function": "createTransaction", - "wallet": wallet!, - "amount": txData['recipientAmt'], - "address": txData['addresss'], - "secretKeyIndex": 0, - "epicboxConfig": epicboxConfig!, - "minimumConfirmations": MINIMUM_CONFIRMATIONS, - }, name: walletName); - message = await receivePort.first; - if (message is String) { - Logging.instance - .log("this is a string $message", level: LogLevel.Error); + String receiverAddress = txData['addresss'] as String; + await m.protect(() async { + + if (receiverAddress.startsWith("http://") || receiverAddress.startsWith("https://")) { + const int selectionStrategyIsAll = 0; + ReceivePort receivePort = await getIsolate({ + "function": "txHttpSend", + "wallet": wallet!, + "selectionStrategyIsAll": selectionStrategyIsAll, + "minimumConfirmations": MINIMUM_CONFIRMATIONS, + "message": "", + "amount": txData['recipientAmt'], + "address": txData['addresss'] + }, name: walletName); + + message = await receivePort.first; + if (message is String) { + Logging.instance + .log("this is a string $message", level: LogLevel.Error); + stop(receivePort); + throw Exception("txHttpSend isolate failed"); + } stop(receivePort); - throw Exception("createTransaction isolate failed"); + Logging.instance.log('Closing txHttpSend!\n $message', + level: LogLevel.Info); + + } else { + ReceivePort receivePort = await getIsolate({ + "function": "createTransaction", + "wallet": wallet!, + "amount": txData['recipientAmt'], + "address": txData['addresss'], + "secretKeyIndex": 0, + "epicboxConfig": epicboxConfig!, + "minimumConfirmations": MINIMUM_CONFIRMATIONS, + }, name: walletName); + + message = await receivePort.first; + if (message is String) { + Logging.instance + .log("this is a string $message", level: LogLevel.Error); + stop(receivePort); + throw Exception("createTransaction isolate failed"); + } + stop(receivePort); + Logging.instance.log('Closing createTransaction!\n $message', + level: LogLevel.Info); } - stop(receivePort); - Logging.instance.log('Closing createTransaction!\n $message', - level: LogLevel.Info); }); // return message; final String sendTx = message['result'] as String; - await putSendToAddresses(sendTx); + if (sendTx.contains("Error")) { + throw BadEpicHttpAddressException(message: sendTx); + } + + if (!(receiverAddress.startsWith("http://") || receiverAddress.startsWith("https://"))) { + await putSendToAddresses(sendTx); + } + Logging.instance.log("CONFIRM_RESULT_IS $sendTx", level: LogLevel.Info); @@ -752,11 +821,16 @@ class EpicCashWallet extends CoinServiceAPI { String errorMessage = decodeData[1] as String; throw Exception("Transaction failed with error code $errorMessage"); } else { - final postSlateRequest = decodeData[1]; - final postToServer = await postSlate( - txData['addresss'] as String, postSlateRequest as String); - Logging.instance - .log("POST_SLATE_IS $postToServer", level: LogLevel.Info); + + //If it's HTTP send no need to post to epicbox + if (!(receiverAddress.startsWith("http://") || receiverAddress.startsWith("https://"))) { + final postSlateRequest = decodeData[1]; + final postToServer = await postSlate( + txData['addresss'] as String, postSlateRequest as String); + Logging.instance + .log("POST_SLATE_IS $postToServer", level: LogLevel.Info); + } + final txCreateResult = decodeData[0]; // //TODO: second problem final transaction = json.decode(txCreateResult as String); @@ -2195,6 +2269,12 @@ class EpicCashWallet extends CoinServiceAPI { @override bool validateAddress(String address) { + if (address.startsWith("http://") || address.startsWith("https://")) { + if (Uri.tryParse(address) != null) { + return true; + } + } + String validate = validateSendAddress(address); if (int.parse(validate) == 1) { return true;