diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 54f1ecb6f..8a1bb7be5 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -354,7 +354,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 11; + CURRENT_PROJECT_VERSION = 12; DEVELOPMENT_TEAM = 32J6BB6VUS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -494,7 +494,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 11; + CURRENT_PROJECT_VERSION = 12; DEVELOPMENT_TEAM = 32J6BB6VUS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -528,7 +528,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 11; + CURRENT_PROJECT_VERSION = 12; DEVELOPMENT_TEAM = 32J6BB6VUS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( diff --git a/lib/bitcoin/bitcoin_balance.dart b/lib/bitcoin/bitcoin_balance.dart index 3cc66bfe8..5081616ea 100644 --- a/lib/bitcoin/bitcoin_balance.dart +++ b/lib/bitcoin/bitcoin_balance.dart @@ -27,10 +27,10 @@ class BitcoinBalance extends Balance { final int confirmed; final int unconfirmed; - int get total => - confirmed + (unconfirmed < 0 ? unconfirmed * -1 : unconfirmed); + int get total => confirmed + unconfirmed; - int get availableBalance => confirmed + (unconfirmed < 0 ? unconfirmed : 0); + int get availableBalance => + (confirmed ?? 0) + (unconfirmed < 0 ? unconfirmed : 0); String get confirmedFormatted => bitcoinAmountToString(amount: confirmed); diff --git a/lib/bitcoin/electrum.dart b/lib/bitcoin/electrum.dart index 20dc29688..be1aba92e 100644 --- a/lib/bitcoin/electrum.dart +++ b/lib/bitcoin/electrum.dart @@ -22,9 +22,8 @@ String jsonrpcparams(List params) { } String jsonrpc( - {String method, List params, int id, double version = 2.0}) => - '{"jsonrpc": "$version", "method": "$method", "id": "$id", "params": ${json - .encode(params)}}\n'; + {String method, List params, int id, double version = 2.0}) => + '{"jsonrpc": "$version", "method": "$method", "id": "$id", "params": ${json.encode(params)}}\n'; class SocketTask { SocketTask({this.completer, this.isSubscription, this.subject}); @@ -75,7 +74,9 @@ class ElectrumClient { socket.listen((Uint8List event) { try { - _handleResponse(utf8.decode(event.toList())); + final response = + json.decode(utf8.decode(event.toList())) as Map; + _handleResponse(response); } on FormatException catch (e) { final msg = e.message.toLowerCase(); @@ -87,12 +88,33 @@ class ElectrumClient { unterminatedString += e.source as String; } + if (msg.contains("not a subtype of type")) { + unterminatedString += e.source as String; + return; + } + if (isJSONStringCorrect(unterminatedString)) { - _handleResponse(unterminatedString); + final response = + json.decode(unterminatedString) as Map; + _handleResponse(response); + unterminatedString = null; + } + } on TypeError catch (e) { + if (!e.toString().contains('Map')) { + return; + } + + final source = utf8.decode(event.toList()); + unterminatedString += source; + + if (isJSONStringCorrect(unterminatedString)) { + final response = + json.decode(unterminatedString) as Map; + _handleResponse(response); unterminatedString = null; } } catch (e) { - print(e); + print(e.toString()); } }, onError: (Object error) { print(error.toString()); @@ -153,7 +175,7 @@ class ElectrumClient { }); Future>> getListUnspentWithAddress( - String address) => + String address) => call( method: 'blockchain.scripthash.listunspent', params: [scriptHash(address)]).then((dynamic result) { @@ -204,7 +226,7 @@ class ElectrumClient { }); Future> getTransactionRaw( - {@required String hash}) async => + {@required String hash}) async => call(method: 'blockchain.transaction.get', params: [hash, true]) .then((dynamic result) { if (result is Map) { @@ -233,25 +255,25 @@ class ElectrumClient { } Future broadcastTransaction( - {@required String transactionRaw}) async => + {@required String transactionRaw}) async => call(method: 'blockchain.transaction.broadcast', params: [transactionRaw]) .then((dynamic result) { if (result is String) { return result; } - + print(result); return ''; }); Future> getMerkle( - {@required String hash, @required int height}) async => + {@required String hash, @required int height}) async => await call( method: 'blockchain.transaction.get_merkle', params: [hash, height]) as Map; Future> getHeader({@required int height}) async => await call(method: 'blockchain.block.get_header', params: [height]) - as Map; + as Map; Future estimatefee({@required int p}) => call(method: 'blockchain.estimatefee', params: [p]) @@ -275,9 +297,10 @@ class ElectrumClient { params: [scripthash]); } - BehaviorSubject subscribe({@required String id, - @required String method, - List params = const []}) { + BehaviorSubject subscribe( + {@required String id, + @required String method, + List params = const []}) { final subscription = BehaviorSubject(); _regisrySubscription(id, subscription); socket.write(jsonrpc(method: method, id: _id, params: params)); @@ -296,9 +319,10 @@ class ElectrumClient { return completer.future; } - Future callWithTimeout({String method, - List params = const [], - int timeout = 2000}) async { + Future callWithTimeout( + {String method, + List params = const [], + int timeout = 2000}) async { final completer = Completer(); _id += 1; final id = _id; @@ -325,9 +349,8 @@ class ElectrumClient { onConnectionStatusChange = null; } - void _regisryTask(int id, Completer completer) => - _tasks[id.toString()] = - SocketTask(completer: completer, isSubscription: false); + void _regisryTask(int id, Completer completer) => _tasks[id.toString()] = + SocketTask(completer: completer, isSubscription: false); void _regisrySubscription(String id, BehaviorSubject subject) => _tasks[id] = SocketTask(subject: subject, isSubscription: true); @@ -371,22 +394,20 @@ class ElectrumClient { _isConnected = isConnected; } - void _handleResponse(String response) { - print('Response: $response'); - final jsoned = json.decode(response) as Map; - // print(jsoned); - final method = jsoned['method']; - final id = jsoned['id'] as String; - final result = jsoned['result']; + void _handleResponse(Map response) { + final method = response['method']; + final id = response['id'] as String; + final result = response['result']; if (method is String) { - _methodHandler(method: method, request: jsoned); + _methodHandler(method: method, request: response); return; } _finish(id, result); } } + // FIXME: move me bool isJSONStringCorrect(String source) { try { diff --git a/lib/main.dart b/lib/main.dart index 6c1c3127a..38460fcca 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,3 @@ -import 'package:cake_wallet/bitcoin/bitcoin_amount_format.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index 81449fb0e..36e84544d 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -358,7 +358,16 @@ class ExchangeTradeState extends State { }); }); }, - actionLeftButton: () => Navigator.of(context).pop()); + actionLeftButton: () => Navigator.of(context).pop(), + feeFiatAmount: widget.exchangeTradeViewModel.sendViewModel + .pendingTransaction.feeFormatted, + fiatAmountValue: widget.exchangeTradeViewModel.sendViewModel + .pendingTransactionFeeFiatAmount + + ' ' + + widget.exchangeTradeViewModel.sendViewModel.fiat.title, + recipientTitle: S.of(context).recipient_address, + recipientAddress: + widget.exchangeTradeViewModel.sendViewModel.address); }); }); } diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index d2ac05048..1257ebf07 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -310,7 +310,7 @@ abstract class ExchangeViewModelBase with Store { } final amount = availableBalance - fee; - depositAmount = bitcoinAmountToString(amount: amount); + changeDepositAmount(amount: bitcoinAmountToString(amount: amount)); } } diff --git a/pubspec.yaml b/pubspec.yaml index 8be2f91a7..adfdf3db9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: Cake Wallet. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 4.1.0+27 +version: 4.1.0+28 environment: sdk: ">=2.7.0 <3.0.0"