From c5af0313546fda72f83bc2964dd5f4e145b260f8 Mon Sep 17 00:00:00 2001 From: fosse Date: Mon, 21 Aug 2023 14:42:53 -0400 Subject: [PATCH 1/4] fix manage pow nodes setting appearing on other wallets --- lib/view_model/dashboard/dashboard_view_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 701105b91..bd0d50b18 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -312,7 +312,7 @@ abstract class DashboardViewModelBase with Store { bool isOutdatedElectrumWallet; @computed - bool get hasPowNodes => wallet.type == WalletType.nano || wallet.type != WalletType.banano; + bool get hasPowNodes => wallet.type == WalletType.nano || wallet.type == WalletType.banano; Future reconnect() async { final node = appStore.settingsStore.getCurrentNode(wallet.type); From ad3ff94bccc123f12e46f2b776da75c1c2f61dfa Mon Sep 17 00:00:00 2001 From: fosse Date: Mon, 21 Aug 2023 15:01:33 -0400 Subject: [PATCH 2/4] fix contact bug --- cw_nano/lib/nano_wallet.dart | 1 + .../contact_list/contact_list_view_model.dart | 24 ++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index ffe26ce43..ea6ab816e 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -238,6 +238,7 @@ abstract class NanoWalletBase _isTransactionUpdating = true; final transactions = await fetchTransactions(); + transactionHistory.clear(); transactionHistory.addMany(transactions); await transactionHistory.save(); _isTransactionUpdating = false; diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart index c99984ebc..5abb4674f 100644 --- a/lib/view_model/contact_list/contact_list_view_model.dart +++ b/lib/view_model/contact_list/contact_list_view_model.dart @@ -13,25 +13,29 @@ import 'package:cw_core/crypto_currency.dart'; part 'contact_list_view_model.g.dart'; -class ContactListViewModel = ContactListViewModelBase - with _$ContactListViewModel; +class ContactListViewModel = ContactListViewModelBase with _$ContactListViewModel; abstract class ContactListViewModelBase with Store { - ContactListViewModelBase(this.contactSource, this.walletInfoSource, - this._currency, this.settingsStore) + ContactListViewModelBase( + this.contactSource, this.walletInfoSource, this._currency, this.settingsStore) : contacts = ObservableList(), walletContacts = [] { walletInfoSource.values.forEach((info) { if (info.addresses?.isNotEmpty ?? false) { info.addresses?.forEach((address, label) { final name = label.isNotEmpty ? info.name + ' ($label)' : info.name; - walletContacts.add(WalletContact( address, name, walletTypeToCryptoCurrency(info.type), )); }); + } else if (info.address != null) { + walletContacts.add(WalletContact( + info.address, + info.name, + walletTypeToCryptoCurrency(info.type), + )); } }); @@ -57,14 +61,12 @@ abstract class ContactListViewModelBase with Store { Future delete(ContactRecord contact) async => contact.original.delete(); @computed - List get contactsToShow => contacts - .where((element) => _isValidForCurrency(element)) - .toList(); + List get contactsToShow => + contacts.where((element) => _isValidForCurrency(element)).toList(); @computed - List get walletContactsToShow => walletContacts - .where((element) => _isValidForCurrency(element)) - .toList(); + List get walletContactsToShow => + walletContacts.where((element) => _isValidForCurrency(element)).toList(); bool _isValidForCurrency(ContactBase element) { return _currency == null || element.type == _currency || element.type.title == _currency!.tag; From cf429918915c4d077aa640e71b4014e8c103617e Mon Sep 17 00:00:00 2001 From: fosse Date: Mon, 21 Aug 2023 15:16:52 -0400 Subject: [PATCH 3/4] fixes --- cw_core/lib/node.dart | 23 +++++++++ cw_core/lib/pow_node.dart | 101 ++++++++------------------------------ 2 files changed, 44 insertions(+), 80 deletions(-) diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 42f7a68b3..3f221a695 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -138,6 +138,8 @@ class Node extends HiveObject with Keyable { return requestMoneroNode(); case WalletType.ethereum: return requestElectrumServer(); + case WalletType.nano: + return requestNanoNode(); default: return false; } @@ -178,6 +180,27 @@ class Node extends HiveObject with Keyable { } } + Future requestNanoNode() async { + return http + .post( + uri, + headers: {'Content-type': 'application/json'}, + body: json.encode( + { + "action": "account_balance", + "account": "nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579" + }, + ), + ) + .then((http.Response response) { + if (response.statusCode == 200) { + return true; + } else { + return false; + } + }); + } + Future requestNodeWithProxy(String proxy) async { if (proxy.isEmpty || !proxy.contains(':')) { return false; diff --git a/cw_core/lib/pow_node.dart b/cw_core/lib/pow_node.dart index 3b8d523f6..1e98bc323 100644 --- a/cw_core/lib/pow_node.dart +++ b/cw_core/lib/pow_node.dart @@ -126,18 +126,8 @@ class PowNode extends HiveObject with Keyable { Future requestNode() async { try { switch (type) { - case WalletType.monero: - return useSocksProxy - ? requestNodeWithProxy(socksProxyAddress ?? '') - : requestMoneroNode(); - case WalletType.bitcoin: - return requestElectrumServer(); - case WalletType.litecoin: - return requestElectrumServer(); - case WalletType.haven: - return requestMoneroNode(); - case WalletType.ethereum: - return requestElectrumServer(); + case WalletType.nano: + return requestNanoPowNode(); default: return false; } @@ -146,73 +136,24 @@ class PowNode extends HiveObject with Keyable { } } - Future requestMoneroNode() async { - final path = '/json_rpc'; - final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path); - final realm = 'monero-rpc'; - final body = {'jsonrpc': '2.0', 'id': '0', 'method': 'get_info'}; - - try { - final authenticatingClient = HttpClient(); - - authenticatingClient.addCredentials( - rpcUri, - realm, - HttpClientDigestCredentials(login ?? '', password ?? ''), - ); - - final http.Client client = ioc.IOClient(authenticatingClient); - - final response = await client.post( - rpcUri, - headers: {'Content-Type': 'application/json'}, - body: json.encode(body), - ); - - client.close(); - - final resBody = json.decode(response.body) as Map; - return !(resBody['result']['offline'] as bool); - } catch (_) { - return false; - } - } - - Future requestNodeWithProxy(String proxy) async { - if (proxy.isEmpty || !proxy.contains(':')) { - return false; - } - final proxyAddress = proxy.split(':')[0]; - final proxyPort = int.parse(proxy.split(':')[1]); - try { - final socket = await Socket.connect(proxyAddress, proxyPort, timeout: Duration(seconds: 5)); - socket.destroy(); - return true; - } catch (_) { - return false; - } - } - - Future requestElectrumServer() async { - try { - await SecureSocket.connect(uri.host, uri.port, - timeout: Duration(seconds: 5), onBadCertificate: (_) => true); - return true; - } catch (_) { - return false; - } - } - - Future requestEthereumServer() async { - try { - final response = await http.get( - uri, - headers: {'Content-Type': 'application/json'}, - ); - - return response.statusCode >= 200 && response.statusCode < 300; - } catch (_) { - return false; - } + Future requestNanoPowNode() async { + return http + .post( + uri, + headers: {'Content-type': 'application/json'}, + body: json.encode( + { + "action": "work_generate", + "hash": "0000000000000000000000000000000000000000000000000000000000000000", + }, + ), + ) + .then((http.Response response) { + if (response.statusCode == 200) { + return true; + } else { + return false; + } + }); } } From 53a1ffe40f8823b3c30a023d1978df904d813a8e Mon Sep 17 00:00:00 2001 From: fosse Date: Mon, 21 Aug 2023 16:10:22 -0400 Subject: [PATCH 4/4] fiat fixes --- cw_nano/lib/nano_util.dart | 1 - cw_nano/lib/nano_wallet.dart | 6 +- cw_nano/lib/pending_nano_transaction.dart | 5 + lib/src/screens/send/send_page.dart | 119 ++++++++------------ lib/src/screens/send/widgets/send_card.dart | 15 ++- lib/view_model/send/send_view_model.dart | 16 +-- 6 files changed, 77 insertions(+), 85 deletions(-) diff --git a/cw_nano/lib/nano_util.dart b/cw_nano/lib/nano_util.dart index ee283ab35..257a2e5c5 100644 --- a/cw_nano/lib/nano_util.dart +++ b/cw_nano/lib/nano_util.dart @@ -119,7 +119,6 @@ class NanoUtil { // static String hdSeedToAddress(String seed, int index) { // // return NanoAccounts.createAccount(NanoAccountType.NANO, NanoKeys.createPublicKey(seedToPrivate(seed, index))); - // return ""; // } diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index ea6ab816e..f440624a2 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -177,11 +177,15 @@ abstract class NanoWalletBase BigInt.zero; } + if (balance[currency]?.currentBalance != null && amt > balance[currency]!.currentBalance) { + throw Exception("Trying to send more than entire balance!"); + } + runningBalance = runningBalance - amt; final block = await _client.constructSendBlock( amountRaw: amt.toString(), - destinationAddress: txOut.address, + destinationAddress: txOut.extractedAddress ?? txOut.address, privateKey: _privateKey!, balanceAfterTx: runningBalance, previousHash: previousHash, diff --git a/cw_nano/lib/pending_nano_transaction.dart b/cw_nano/lib/pending_nano_transaction.dart index a2b1989b8..478288754 100644 --- a/cw_nano/lib/pending_nano_transaction.dart +++ b/cw_nano/lib/pending_nano_transaction.dart @@ -20,6 +20,11 @@ class PendingNanoTransaction with PendingTransaction { @override String get amountFormatted { + final String amt = NanoUtil.getRawAsUsableString(amount.toString(), NanoUtil.rawPerNano); + return amt; + } + + String get accurateAmountFormatted { final String amt = NanoUtil.getRawAsUsableString(amount.toString(), NanoUtil.rawPerNano); final String acc = NanoUtil.getRawAccuracy(amount.toString(), NanoUtil.rawPerNano); return "$acc$amt"; diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 4a2559902..df148e83b 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -66,9 +66,8 @@ class SendPage extends BasePage { color: titleColor(context), size: 16, ); - final _closeButton = currentTheme.type == ThemeType.dark - ? closeButtonImageDarkTheme - : closeButtonImage; + final _closeButton = + currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage; bool isMobileView = ResponsiveLayoutUtil.instance.isMobile; @@ -79,13 +78,10 @@ class SendPage extends BasePage { child: ButtonTheme( minWidth: double.minPositive, child: Semantics( - label: !isMobileView - ? S.of(context).close - : S.of(context).seed_alert_back, + label: !isMobileView ? S.of(context).close : S.of(context).seed_alert_back, child: TextButton( style: ButtonStyle( - overlayColor: MaterialStateColor.resolveWith( - (states) => Colors.transparent), + overlayColor: MaterialStateColor.resolveWith((states) => Colors.transparent), ), onPressed: () => onClose(context), child: !isMobileView ? _closeButton : _backButton, @@ -123,8 +119,7 @@ class SendPage extends BasePage { Padding( padding: const EdgeInsets.only(right: 8.0), child: Observer( - builder: (_) => - SyncIndicatorIcon(isSynced: sendViewModel.isReadyForSend), + builder: (_) => SyncIndicatorIcon(isSynced: sendViewModel.isReadyForSend), ), ), if (supMiddle != null) supMiddle @@ -158,10 +153,10 @@ class SendPage extends BasePage { _setEffects(context); return GestureDetector( - onLongPress: () => sendViewModel.balanceViewModel.isReversing = - !sendViewModel.balanceViewModel.isReversing, - onLongPressUp: () => sendViewModel.balanceViewModel.isReversing = - !sendViewModel.balanceViewModel.isReversing, + onLongPress: () => + sendViewModel.balanceViewModel.isReversing = !sendViewModel.balanceViewModel.isReversing, + onLongPressUp: () => + sendViewModel.balanceViewModel.isReversing = !sendViewModel.balanceViewModel.isReversing, child: Form( key: _formKey, child: ScrollableWithBottomSection( @@ -191,8 +186,7 @@ class SendPage extends BasePage { }, )), Padding( - padding: EdgeInsets.only( - top: 10, left: 24, right: 24, bottom: 10), + padding: EdgeInsets.only(top: 10, left: 24, right: 24, bottom: 10), child: Container( height: 10, child: Observer( @@ -208,8 +202,12 @@ class SendPage extends BasePage { radius: 6.0, dotWidth: 6.0, dotHeight: 6.0, - dotColor: Theme.of(context).extension()!.indicatorDotColor, - activeDotColor: Theme.of(context).extension()!.templateBackgroundColor), + dotColor: Theme.of(context) + .extension()! + .indicatorDotColor, + activeDotColor: Theme.of(context) + .extension()! + .templateBackgroundColor), ) : Offstage(); }, @@ -230,8 +228,7 @@ class SendPage extends BasePage { return Row( children: [ AddTemplateButton( - onTap: () => Navigator.of(context) - .pushNamed(Routes.sendTemplate), + onTap: () => Navigator.of(context).pushNamed(Routes.sendTemplate), currentTemplatesLength: templates.length, ), ListView.builder( @@ -244,9 +241,8 @@ class SendPage extends BasePage { return TemplateTile( key: UniqueKey(), to: template.name, - hasMultipleRecipients: - template.additionalRecipients != null && - template.additionalRecipients!.length > 1, + hasMultipleRecipients: template.additionalRecipients != null && + template.additionalRecipients!.length > 1, amount: template.isCurrencySelected ? template.amount : template.amountFiat, @@ -257,7 +253,9 @@ class SendPage extends BasePage { if (template.additionalRecipients?.isNotEmpty ?? false) { sendViewModel.clearOutputs(); - for (int i = 0;i < template.additionalRecipients!.length;i++) { + for (int i = 0; + i < template.additionalRecipients!.length; + i++) { Output output; try { output = sendViewModel.outputs[i]; @@ -286,26 +284,17 @@ class SendPage extends BasePage { context: context, builder: (dialogContext) { return AlertWithTwoActions( - alertTitle: - S.of(context).template, - alertContent: S - .of(context) - .confirm_delete_template, - rightButtonText: - S.of(context).delete, - leftButtonText: - S.of(context).cancel, + alertTitle: S.of(context).template, + alertContent: S.of(context).confirm_delete_template, + rightButtonText: S.of(context).delete, + leftButtonText: S.of(context).cancel, actionRightButton: () { - Navigator.of(dialogContext) - .pop(); - sendViewModel - .sendTemplateViewModel - .removeTemplate( - template: template); + Navigator.of(dialogContext).pop(); + sendViewModel.sendTemplateViewModel + .removeTemplate(template: template); }, actionLeftButton: () => - Navigator.of(dialogContext) - .pop()); + Navigator.of(dialogContext).pop()); }, ); }, @@ -321,8 +310,7 @@ class SendPage extends BasePage { ], ), ), - bottomSectionPadding: - EdgeInsets.only(left: 24, right: 24, bottom: 24), + bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), bottomSection: Column( children: [ if (sendViewModel.hasCurrecyChanger) @@ -331,10 +319,10 @@ class SendPage extends BasePage { padding: EdgeInsets.only(bottom: 12), child: PrimaryButton( onPressed: () => presentCurrencyPicker(context), - text: - 'Change your asset (${sendViewModel.selectedCryptoCurrency})', + text: 'Change your asset (${sendViewModel.selectedCryptoCurrency})', color: Colors.transparent, - textColor: Theme.of(context).extension()!.hintTextColor, + textColor: + Theme.of(context).extension()!.hintTextColor, ))), if (sendViewModel.sendTemplateViewModel.hasMultiRecipient) Padding( @@ -343,22 +331,21 @@ class SendPage extends BasePage { onPressed: () { sendViewModel.addOutput(); Future.delayed(const Duration(milliseconds: 250), () { - controller - .jumpToPage(sendViewModel.outputs.length - 1); + controller.jumpToPage(sendViewModel.outputs.length - 1); }); }, text: S.of(context).add_receiver, color: Colors.transparent, textColor: Theme.of(context).extension()!.hintTextColor, isDottedBorder: true, - borderColor: Theme.of(context).extension()!.templateDottedBorderColor, + borderColor: + Theme.of(context).extension()!.templateDottedBorderColor, )), Observer( builder: (_) { return LoadingPrimaryButton( onPressed: () async { - if (_formKey.currentState != null && - !_formKey.currentState!.validate()) { + if (_formKey.currentState != null && !_formKey.currentState!.validate()) { if (sendViewModel.outputs.length > 1) { showErrorValidationAlert(context); } @@ -367,9 +354,7 @@ class SendPage extends BasePage { } final notValidItems = sendViewModel.outputs - .where((item) => - item.address.isEmpty || - item.cryptoAmount.isEmpty) + .where((item) => item.address.isEmpty || item.cryptoAmount.isEmpty) .toList(); if (notValidItems.isNotEmpty) { @@ -389,8 +374,7 @@ class SendPage extends BasePage { ); }, text: S.of(context).send, - color: - Theme.of(context).primaryColor, + color: Theme.of(context).primaryColor, textColor: Colors.white, isLoading: sendViewModel.state is IsExecutingState || sendViewModel.state is TransactionCommitting, @@ -433,14 +417,11 @@ class SendPage extends BasePage { return ConfirmSendingAlert( alertTitle: S.of(context).confirm_sending, amount: S.of(context).send_amount, - amountValue: - sendViewModel.pendingTransaction!.amountFormatted, - fiatAmountValue: - sendViewModel.pendingTransactionFiatAmountFormatted, + amountValue: sendViewModel.pendingTransaction!.amountFormatted, + fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted, fee: S.of(context).send_fee, feeValue: sendViewModel.pendingTransaction!.feeFormatted, - feeFiatAmount: sendViewModel - .pendingTransactionFeeFiatAmountFormatted, + feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted, outputs: sendViewModel.outputs, rightButtonText: S.of(context).ok, leftButtonText: S.of(context).cancel, @@ -461,8 +442,7 @@ class SendPage extends BasePage { return AlertWithOneAction( alertTitle: '', alertContent: S.of(context).send_success( - sendViewModel.selectedCryptoCurrency - .toString()), + sendViewModel.selectedCryptoCurrency.toString()), buttonText: S.of(context).ok, buttonAction: () { Navigator.of(context).pop(); @@ -492,8 +472,8 @@ class SendPage extends BasePage { Future _setInputsFromTemplate(BuildContext context, {required Output output, required Template template}) async { - final fiatFromTemplate = FiatCurrency.all - .singleWhere((element) => element.title == template.fiatCurrency); + final fiatFromTemplate = + FiatCurrency.all.singleWhere((element) => element.title == template.fiatCurrency); output.address = template.address; @@ -534,12 +514,11 @@ class SendPage extends BasePage { builder: (_) => Picker( items: sendViewModel.currencies, displayItem: (Object item) => item.toString(), - selectedAtIndex: sendViewModel.currencies - .indexOf(sendViewModel.selectedCryptoCurrency), + selectedAtIndex: + sendViewModel.currencies.indexOf(sendViewModel.selectedCryptoCurrency), title: S.of(context).please_select, mainAxisAlignment: MainAxisAlignment.center, - onItemSelected: (CryptoCurrency cur) => - sendViewModel.selectedCryptoCurrency = cur, + onItemSelected: (CryptoCurrency cur) => sendViewModel.selectedCryptoCurrency = cur, ), context: context); } diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index d8bd4482c..61e8d2f86 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -167,8 +167,10 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin()!.textFieldButtonColor, - borderColor: Theme.of(context).extension()!.textFieldBorderColor, + buttonColor: + Theme.of(context).extension()!.textFieldButtonColor, + borderColor: + Theme.of(context).extension()!.textFieldBorderColor, textStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white), hintStyle: TextStyle( @@ -419,11 +421,13 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin()!.textFieldBorderColor, + borderColor: + Theme.of(context).extension()!.textFieldBorderColor, textStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white), placeholderTextStyle: TextStyle( - color: Theme.of(context).extension()!.textFieldHintColor, + color: + Theme.of(context).extension()!.textFieldHintColor, fontWeight: FontWeight.w500, fontSize: 14), ), @@ -434,7 +438,8 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin()!.textFieldBorderColor, + borderColor: + Theme.of(context).extension()!.textFieldBorderColor, textStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white), hintText: S.of(context).note_optional, diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 7a5f0eca0..015b9c82a 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -96,15 +96,15 @@ abstract class SendViewModelBase with Store { @computed String get pendingTransactionFiatAmount { + if (pendingTransaction == null) { + return '0.00'; + } + try { - if (pendingTransaction != null) { - final fiat = calculateFiatAmount( - price: _fiatConversationStore.prices[selectedCryptoCurrency]!, - cryptoAmount: pendingTransaction!.amountFormatted); - return fiat; - } else { - return '0.00'; - } + final fiat = calculateFiatAmount( + price: _fiatConversationStore.prices[selectedCryptoCurrency]!, + cryptoAmount: pendingTransaction!.amountFormatted); + return fiat; } catch (_) { return '0.00'; }