From ae9efb0ae8ae35e0c33bcfe7ba3473ddc9b4d0ae Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Tue, 20 Apr 2021 20:49:53 +0300 Subject: [PATCH 01/18] CAKE-192 | implemented unstoppable domain address to the app --- android/app/build.gradle | 5 +- .../cakewallet/cake_wallet/MainActivity.java | 46 ++++++++++- android/build.gradle | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 4 +- ios/Podfile | 3 +- ios/Podfile.lock | 18 ++++- ios/Runner/AppDelegate.swift | 40 +++++++++ lib/entities/unstoppable_domain_address.dart | 22 +++++ lib/src/screens/exchange/exchange_page.dart | 81 +++++++++++++++++-- .../exchange/exchange_template_page.dart | 11 ++- .../exchange/widgets/exchange_card.dart | 10 ++- lib/src/screens/send/send_page.dart | 34 ++++++-- lib/src/screens/send/send_template_page.dart | 4 +- .../unstoppable_domain_address_alert.dart | 17 ++++ lib/src/widgets/address_text_field.dart | 6 +- .../exchange/exchange_view_model.dart | 5 ++ lib/view_model/send/send_view_model.dart | 5 ++ res/values/strings_de.arb | 5 +- res/values/strings_en.arb | 5 +- res/values/strings_es.arb | 5 +- res/values/strings_hi.arb | 5 +- res/values/strings_ja.arb | 5 +- res/values/strings_ko.arb | 5 +- res/values/strings_nl.arb | 5 +- res/values/strings_pl.arb | 5 +- res/values/strings_pt.arb | 5 +- res/values/strings_ru.arb | 5 +- res/values/strings_uk.arb | 5 +- res/values/strings_zh.arb | 5 +- 29 files changed, 327 insertions(+), 46 deletions(-) create mode 100644 lib/entities/unstoppable_domain_address.dart create mode 100644 lib/src/screens/send/widgets/unstoppable_domain_address_alert.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 0c6a46dc..cef66608 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -81,6 +81,7 @@ flutter { dependencies { testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + androidTestImplementation 'androidx.test:runner:1.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + implementation 'com.unstoppabledomains:resolution:1.13.0' } diff --git a/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java b/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java index cf650375..7efe1606 100644 --- a/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java +++ b/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java @@ -5,11 +5,55 @@ import io.flutter.embedding.android.FlutterFragmentActivity; import io.flutter.embedding.engine.FlutterEngine; import io.flutter.plugins.GeneratedPluginRegistrant; +import com.unstoppabledomains.resolution.DomainResolution; +import com.unstoppabledomains.resolution.Resolution; + +import android.os.AsyncTask; +import android.os.Handler; +import android.os.Looper; + +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; public class MainActivity extends FlutterFragmentActivity { - + final String UNSTOPPABLE_DOMAIN_CHANNEL = "com.cakewallet.cake_wallet/unstoppable-domain"; + @Override public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine); + + MethodChannel unstoppableDomainChannel = + new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), + UNSTOPPABLE_DOMAIN_CHANNEL); + + unstoppableDomainChannel.setMethodCallHandler(this::handle); + } + + private void handle(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { + try { + if (call.method.equals("getUnstoppableDomainAddress")) { + getUnstoppableDomainAddress(call, result); + } else { + result.notImplemented(); + } + } catch (Exception e) { + result.error("UNCAUGHT_ERROR", e.getMessage(), null); + } + } + + private void getUnstoppableDomainAddress(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { + DomainResolution resolution = new Resolution(); + Handler handler = new Handler(Looper.getMainLooper()); + String domain = call.argument("domain"); + String ticker = call.argument("ticker"); + + AsyncTask.execute(() -> { + try { + String address = resolution.getAddress(domain, ticker); + handler.post(() -> result.success(address)); + } catch (Exception e) { + handler.post(() -> result.error("INVALID DOMAIN", e.getMessage(), null)); + } + }); } } diff --git a/android/build.gradle b/android/build.gradle index 0baed694..fab3c2e1 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.5.4' + classpath 'com.android.tools.build:gradle:4.1.3' } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 296b146b..b7ca2e6d 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Jun 23 08:50:38 CEST 2017 +#Mon Apr 19 18:19:26 EEST 2021 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip diff --git a/ios/Podfile b/ios/Podfile index e26de900..8248dde4 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '9.0' +platform :ios, '11.0' source 'https://github.com/CocoaPods/Specs.git' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. @@ -36,6 +36,7 @@ target 'Runner' do # Cake Wallet (Legacy) pod 'CryptoSwift' + pod 'UnstoppableDomainsResolution', '~> 0.3.6' end post_install do |installer| diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 03302eab..f627ed23 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -3,6 +3,7 @@ PODS: - Flutter - MTBBarcodeScanner - SwiftProtobuf + - BigInt (5.2.0) - connectivity (0.0.1): - Flutter - Reachability @@ -59,6 +60,8 @@ PODS: - SwiftyGif - esys_flutter_share (0.0.1): - Flutter + - EthereumAddress (1.3.0): + - CryptoSwift (~> 1.0) - file_picker (0.0.1): - DKImagePickerController/PhotoGallery - Flutter @@ -84,6 +87,10 @@ PODS: - Flutter - SwiftProtobuf (1.12.0) - SwiftyGif (5.3.0) + - UnstoppableDomainsResolution (0.3.6): + - BigInt + - CryptoSwift (~> 1.0) + - EthereumAddress (~> 1.3) - url_launcher (0.0.1): - Flutter - webview_flutter (0.0.1): @@ -105,19 +112,23 @@ DEPENDENCIES: - permission_handler (from `.symlinks/plugins/permission_handler/ios`) - share (from `.symlinks/plugins/share/ios`) - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) + - UnstoppableDomainsResolution (~> 0.3.6) - url_launcher (from `.symlinks/plugins/url_launcher/ios`) - webview_flutter (from `.symlinks/plugins/webview_flutter/ios`) SPEC REPOS: https://github.com/CocoaPods/Specs.git: + - BigInt - CryptoSwift - DKImagePickerController - DKPhotoGallery + - EthereumAddress - MTBBarcodeScanner - Reachability - SDWebImage - SwiftProtobuf - SwiftyGif + - UnstoppableDomainsResolution EXTERNAL SOURCES: barcode_scan: @@ -155,6 +166,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: barcode_scan: a5c27959edfafaa0c771905bad0b29d6d39e4479 + BigInt: f668a80089607f521586bbe29513d708491ef2f7 connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467 CryptoSwift: 093499be1a94b0cae36e6c26b70870668cb56060 cw_monero: 2e1f79929880cc2293b5bc1b25e28152e4d84649 @@ -162,6 +174,7 @@ SPEC CHECKSUMS: DKImagePickerController: b5eb7f7a388e4643264105d648d01f727110fc3d DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 esys_flutter_share: 403498dab005b36ce1f8d7aff377e81f0621b0b4 + EthereumAddress: 39fe8e11cf04e4e9902b55ae653dbc4e0aee5f30 file_picker: 3e6c3790de664ccf9b882732d9db5eaf6b8d4eb1 Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec @@ -176,9 +189,10 @@ SPEC CHECKSUMS: shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d SwiftProtobuf: 4ef85479c18ca85b5482b343df9c319c62bda699 SwiftyGif: e466e86c660d343357ab944a819a101c4127cb40 + UnstoppableDomainsResolution: 63abb84858d3e91eb838a5bfa6f7e3c0e0593f24 url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef webview_flutter: 9f491a9b5a66f2573946a389b2677987b0ff8c0b -PODFILE CHECKSUM: 5b5f101b119a1b6eb857c967d462832a9062dec4 +PODFILE CHECKSUM: 2172f10eb8ff8378f8d6e3e2c1366a0e6cdea018 -COCOAPODS: 1.9.3 +COCOAPODS: 1.10.1 diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 01aa1419..8b6264a0 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -1,8 +1,13 @@ import UIKit import Flutter +import UnstoppableDomainsResolution @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { + lazy var resolution : Resolution? = { + return try? Resolution() + }() + override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? @@ -10,6 +15,8 @@ import Flutter let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let batteryChannel = FlutterMethodChannel(name: "com.cakewallet.cakewallet/legacy_wallet_migration", binaryMessenger: controller.binaryMessenger) + let unstoppableDomainChannel = FlutterMethodChannel(name: "com.cakewallet.cake_wallet/unstoppable-domain", binaryMessenger: controller.binaryMessenger) + batteryChannel.setMethodCallHandler({ (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in @@ -52,6 +59,39 @@ import Flutter } }) + unstoppableDomainChannel.setMethodCallHandler({ [weak self] + (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in + switch call.method { + case "getUnstoppableDomainAddress": + guard let args = call.arguments as? Dictionary, + let domain = args["domain"], + let ticker = args["ticker"] else { + result(nil) + return + } + + guard let resolution = self?.resolution else { + result(nil) + return + } + + resolution.addr(domain: domain, ticker: ticker) { addrResult in + var address : String = "" + + switch addrResult { + case .success(let returnValue): + address = returnValue + case .failure(let error): + print("Expected Address, but got \(error)") + } + + result(address) + } + default: + result(FlutterMethodNotImplemented) + } + }) + GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } diff --git a/lib/entities/unstoppable_domain_address.dart b/lib/entities/unstoppable_domain_address.dart new file mode 100644 index 00000000..494782d5 --- /dev/null +++ b/lib/entities/unstoppable_domain_address.dart @@ -0,0 +1,22 @@ +import 'package:flutter/services.dart'; + +const channel = MethodChannel('com.cakewallet.cake_wallet/unstoppable-domain'); + +Future fetchUnstoppableDomainAddress(String domain, String ticker) async { + String address; + + try { + address = await channel.invokeMethod( + 'getUnstoppableDomainAddress', + { + 'domain' : domain, + 'ticker' : ticker + } + ); + } catch (e) { + print('Unstoppable domain error: ${e.toString()}'); + address = ''; + } + + return address; +} \ No newline at end of file diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 82d7dd80..853ff987 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -1,7 +1,7 @@ import 'dart:ui'; import 'package:cake_wallet/entities/sync_status.dart'; import 'package:cake_wallet/entities/wallet_type.dart'; -import 'package:cake_wallet/exchange/changenow/changenow_exchange_provider.dart'; +import 'package:cake_wallet/src/screens/send/widgets/unstoppable_domain_address_alert.dart'; import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:flutter/cupertino.dart'; @@ -9,8 +9,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; -import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/exchange/exchange_template.dart'; import 'package:cake_wallet/exchange/exchange_trade_state.dart'; import 'package:cake_wallet/exchange/limits_state.dart'; @@ -23,7 +21,6 @@ import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/entities/crypto_currency.dart'; -import 'package:cake_wallet/exchange/xmrto/xmrto_exchange_provider.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; @@ -42,7 +39,9 @@ class ExchangePage extends BasePage { final checkBoxKey = GlobalKey(); final _formKey = GlobalKey(); final _depositAmountFocus = FocusNode(); + final _depositAddressFocus = FocusNode(); final _receiveAmountFocus = FocusNode(); + final _receiveAddressFocus = FocusNode(); var _isReactionsSet = false; @override @@ -52,7 +51,7 @@ class ExchangePage extends BasePage { Color get titleColor => Colors.white; @override - bool get resizeToAvoidBottomPadding => false; + bool get resizeToAvoidBottomInset => false; @override bool get extendBodyBehindAppBar => true; @@ -171,6 +170,7 @@ class ExchangePage extends BasePage { .calculateDepositAllAmount() : null, amountFocusNode: _depositAmountFocus, + addressFocusNode: _depositAddressFocus, key: depositKey, title: S.of(context).you_will_send, initialCurrency: @@ -223,6 +223,15 @@ class ExchangePage extends BasePage { type: exchangeViewModel.wallet.type), addressTextFieldValidator: AddressValidator( type: exchangeViewModel.depositCurrency), + onPushPasteButton: (context) async { + final domain = + exchangeViewModel.depositAddress; + final ticker = + exchangeViewModel.depositCurrency.title; + exchangeViewModel.depositAddress = + await applyUnstoppableDomainAddress( + context, domain, ticker); + }, ), ), ), @@ -232,6 +241,7 @@ class ExchangePage extends BasePage { child: Observer( builder: (_) => ExchangeCard( amountFocusNode: _receiveAmountFocus, + addressFocusNode: _receiveAddressFocus, key: receiveKey, title: S.of(context).you_will_get, initialCurrency: @@ -268,6 +278,15 @@ class ExchangePage extends BasePage { AddressValidator( type: exchangeViewModel .receiveCurrency), + onPushPasteButton: (context) async { + final domain = + exchangeViewModel.receiveAddress; + final ticker = + exchangeViewModel.receiveCurrency.title; + exchangeViewModel.receiveAddress = + await applyUnstoppableDomainAddress( + context, domain, ticker); + }, )), ) ], @@ -371,7 +390,7 @@ class ExchangePage extends BasePage { from: template.depositCurrency, to: template.receiveCurrency, onTap: () { - applyTemplate( + applyTemplate(context, exchangeViewModel, template); }, onRemove: () { @@ -472,8 +491,8 @@ class ExchangePage extends BasePage { )); } - void applyTemplate( - ExchangeViewModel exchangeViewModel, ExchangeTemplate template) { + void applyTemplate(BuildContext context, + ExchangeViewModel exchangeViewModel, ExchangeTemplate template) async { exchangeViewModel.changeDepositCurrency( currency: CryptoCurrency.fromString(template.depositCurrency)); exchangeViewModel.changeReceiveCurrency( @@ -491,6 +510,16 @@ class ExchangePage extends BasePage { exchangeViewModel.receiveAddress = template.receiveAddress; exchangeViewModel.isReceiveAmountEntered = false; exchangeViewModel.isFixedRateMode = false; + + var domain = template.depositAddress; + var ticker = template.depositCurrency; + exchangeViewModel.depositAddress = + await applyUnstoppableDomainAddress(context, domain, ticker); + + domain = template.receiveAddress; + ticker = template.receiveCurrency; + exchangeViewModel.receiveAddress = + await applyUnstoppableDomainAddress(context, domain, ticker); } void _setReactions( @@ -656,6 +685,26 @@ class ExchangePage extends BasePage { } }); + _depositAddressFocus.addListener(() async { + if (!_depositAddressFocus.hasFocus && + depositAddressController.text.isNotEmpty) { + final domain = depositAddressController.text; + final ticker = exchangeViewModel.depositCurrency.title; + exchangeViewModel.depositAddress = + await applyUnstoppableDomainAddress(context, domain, ticker); + } + }); + + _receiveAddressFocus.addListener(() async { + if (!_receiveAddressFocus.hasFocus && + receiveAddressController.text.isNotEmpty) { + final domain = receiveAddressController.text; + final ticker = exchangeViewModel.receiveCurrency.title; + exchangeViewModel.receiveAddress = + await applyUnstoppableDomainAddress(context, domain, ticker); + } + }); + _receiveAmountFocus.addListener(() { if (_receiveAmountFocus.hasFocus && !exchangeViewModel.isFixedRateMode) { showPopUp( @@ -726,4 +775,20 @@ class ExchangePage extends BasePage { key.currentState.addressController.text = null; } } + + Future applyUnstoppableDomainAddress(BuildContext context, + String domain, String ticker) async { + try { + final address = + await exchangeViewModel.getUnstoppableDomainAddress(domain, ticker); + if ((address != null)&&address.isNotEmpty) { + unstoppableDomainAddressAlert(context, domain); + return address; + } + } catch (e) { + print(e.toString()); + } + + return domain; + } } diff --git a/lib/src/screens/exchange/exchange_template_page.dart b/lib/src/screens/exchange/exchange_template_page.dart index 5437703c..1be8d1d6 100644 --- a/lib/src/screens/exchange/exchange_template_page.dart +++ b/lib/src/screens/exchange/exchange_template_page.dart @@ -37,7 +37,7 @@ class ExchangeTemplatePage extends BasePage { Color get titleColor => Colors.white; @override - bool get resizeToAvoidBottomPadding => false; + bool get resizeToAvoidBottomInset => false; @override bool get extendBodyBehindAppBar => true; @@ -150,9 +150,8 @@ class ExchangeTemplatePage extends BasePage { .color, currencyValueValidator: AmountValidator( type: exchangeViewModel.wallet.type), - addressTextFieldValidator: AddressValidator( - type: - exchangeViewModel.depositCurrency), + //addressTextFieldValidator: AddressValidator( + // type: exchangeViewModel.depositCurrency), ), ), ), @@ -190,8 +189,8 @@ class ExchangeTemplatePage extends BasePage { .decorationColor, currencyValueValidator: AmountValidator( type: exchangeViewModel.wallet.type), - addressTextFieldValidator: AddressValidator( - type: exchangeViewModel.receiveCurrency), + //addressTextFieldValidator: AddressValidator( + // type: exchangeViewModel.receiveCurrency), )), ) ], diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index 7af57e28..f534ccca 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -28,8 +28,10 @@ class ExchangeCard extends StatefulWidget { this.currencyValueValidator, this.addressTextFieldValidator, this.amountFocusNode, + this.addressFocusNode, this.hasAllAmount = false, - this.allAmount}) + this.allAmount, + this.onPushPasteButton}) : super(key: key); final List currencies; @@ -49,8 +51,10 @@ class ExchangeCard extends StatefulWidget { final FormFieldValidator currencyValueValidator; final FormFieldValidator addressTextFieldValidator; final FocusNode amountFocusNode; + final FocusNode addressFocusNode; final bool hasAllAmount; - Function allAmount; + final Function allAmount; + final Function(BuildContext context) onPushPasteButton; @override ExchangeCardState createState() => ExchangeCardState(); @@ -288,6 +292,7 @@ class ExchangeCardState extends State { ? Padding( padding: EdgeInsets.only(top: 20), child: AddressTextField( + focusNode: widget.addressFocusNode, controller: addressController, placeholder: widget.hasRefundAddress ? S.of(context).refund_address @@ -311,6 +316,7 @@ class ExchangeCardState extends State { .decorationColor), buttonColor: widget.addressButtonsColor, validator: widget.addressTextFieldValidator, + onPushPasteButton: widget.onPushPasteButton, ), ) : Padding( diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 9fae0ec2..e40657b1 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,6 +1,6 @@ import 'dart:ui'; -import 'package:cake_wallet/entities/monero_transaction_priority.dart'; import 'package:cake_wallet/entities/transaction_priority.dart'; +import 'package:cake_wallet/src/screens/send/widgets/unstoppable_domain_address_alert.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; @@ -38,9 +38,10 @@ class SendPage extends BasePage { _cryptoAmountFocus = FocusNode(), _fiatAmountFocus = FocusNode(), _addressFocusNode = FocusNode() { - _addressFocusNode.addListener(() { + _addressFocusNode.addListener(() async { if (!_addressFocusNode.hasFocus && _addressController.text.isNotEmpty) { - getOpenaliasRecord(_addressFocusNode.context); + await getOpenaliasRecord(_addressFocusNode.context); + await applyUnstoppableDomainAddress(_addressFocusNode.context); } }); } @@ -67,7 +68,7 @@ class SendPage extends BasePage { Color get titleColor => Colors.white; @override - bool get resizeToAvoidBottomPadding => false; + bool get resizeToAvoidBottomInset => false; @override bool get extendBodyBehindAppBar => true; @@ -173,6 +174,10 @@ class SendPage extends BasePage { .headline .decorationColor), validator: sendViewModel.addressValidator, + onPushPasteButton: (context) async { + await getOpenaliasRecord(context); + await applyUnstoppableDomainAddress(context); + }, ), Observer( builder: (_) => Padding( @@ -513,12 +518,13 @@ class SendPage extends BasePage { to: template.name, amount: template.amount, from: template.cryptoCurrency, - onTap: () { + onTap: () async { _addressController.text = template.address; _cryptoAmountController.text = template.amount; - getOpenaliasRecord(context); + await getOpenaliasRecord(context); + await applyUnstoppableDomainAddress(context); }, onRemove: () { showPopUp( @@ -770,4 +776,20 @@ class SendPage extends BasePage { ), context: context); } + + Future applyUnstoppableDomainAddress(BuildContext context) async { + try { + final address = await sendViewModel + .getUnstoppableDomainAddress( + _addressController.text); + + if ((address != null)&&address.isNotEmpty) { + unstoppableDomainAddressAlert( + context, _addressController.text); + _addressController.text = address; + } + } catch (e) { + print(e.toString()); + } + } } diff --git a/lib/src/screens/send/send_template_page.dart b/lib/src/screens/send/send_template_page.dart index 6d3ac713..3880bd2f 100644 --- a/lib/src/screens/send/send_template_page.dart +++ b/lib/src/screens/send/send_template_page.dart @@ -34,7 +34,7 @@ class SendTemplatePage extends BasePage { Color get titleColor => Colors.white; @override - bool get resizeToAvoidBottomPadding => false; + bool get resizeToAvoidBottomInset => false; @override bool get extendBodyBehindAppBar => true; @@ -145,7 +145,7 @@ class SendTemplatePage extends BasePage { .primaryTextTheme .headline .decorationColor), - validator: sendViewModel.addressValidator, + //validator: sendViewModel.addressValidator, ), ), Observer(builder: (_) { diff --git a/lib/src/screens/send/widgets/unstoppable_domain_address_alert.dart b/lib/src/screens/send/widgets/unstoppable_domain_address_alert.dart new file mode 100644 index 00000000..011a3679 --- /dev/null +++ b/lib/src/screens/send/widgets/unstoppable_domain_address_alert.dart @@ -0,0 +1,17 @@ +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/generated/i18n.dart'; + +void unstoppableDomainAddressAlert(BuildContext context, String domain) async { + await showPopUp( + context: context, + builder: (BuildContext context) { + + return AlertWithOneAction( + alertTitle: S.of(context).address_detected, + alertContent: S.of(context).address_from_domain(domain), + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); +} \ No newline at end of file diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart index 8e2c069f..130912a2 100644 --- a/lib/src/widgets/address_text_field.dart +++ b/lib/src/widgets/address_text_field.dart @@ -24,7 +24,8 @@ class AddressTextField extends StatelessWidget { this.iconColor, this.textStyle, this.hintStyle, - this.validator}); + this.validator, + this.onPushPasteButton}); static const prefixIconWidth = 34.0; static const prefixIconHeight = 34.0; @@ -43,6 +44,7 @@ class AddressTextField extends StatelessWidget { final TextStyle textStyle; final TextStyle hintStyle; final FocusNode focusNode; + final Function(BuildContext context) onPushPasteButton; @override Widget build(BuildContext context) { @@ -225,5 +227,7 @@ class AddressTextField extends StatelessWidget { if (address?.isNotEmpty ?? false) { controller.text = address; } + + onPushPasteButton?.call(context); } } diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index fc860e01..2bcec356 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart'; import 'package:cake_wallet/core/wallet_base.dart'; import 'package:cake_wallet/entities/crypto_currency.dart'; import 'package:cake_wallet/entities/sync_status.dart'; +import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; import 'package:cake_wallet/entities/wallet_type.dart'; import 'package:cake_wallet/exchange/exchange_provider.dart'; import 'package:cake_wallet/exchange/limits.dart'; @@ -417,4 +418,8 @@ abstract class ExchangeViewModelBase with Store { }*/ isReceiveAmountEditable = false; } + + Future getUnstoppableDomainAddress(String domain, String ticker) async { + return await fetchUnstoppableDomainAddress(domain, ticker.toLowerCase()); + } } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index b92672ff..f36261f7 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/entities/balance_display_mode.dart'; import 'package:cake_wallet/entities/calculate_fiat_amount_raw.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; import 'package:cake_wallet/entities/transaction_priority.dart'; +import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; import 'package:cake_wallet/monero/monero_amount_format.dart'; import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:hive/hive.dart'; @@ -267,6 +268,10 @@ abstract class SendViewModelBase with Store { return record.name != name ? record : null; } + Future getUnstoppableDomainAddress(String domain) async { + return await fetchUnstoppableDomainAddress(domain, currency.title.toLowerCase()); + } + @action void _updateFiatAmount() { try { diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 6d1d66b8..34cef607 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Unbestätigt", "displayable" : "Anzeigebar", - "submit_request" : "Einen Antrag stellen" + "submit_request" : "Einen Antrag stellen", + + "address_detected" : "Adresse erkannt", + "address_from_domain" : "Sie haben die Adresse von der unaufhaltsamen Domain ${domain} erhalten" } \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index b0d98b7c..a641fabf 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Unconfirmed", "displayable" : "Displayable", - "submit_request" : "submit a request" + "submit_request" : "submit a request", + + "address_detected" : "Address detected", + "address_from_domain" : "You got address from unstoppable domain ${domain}" } \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 190ad430..95a34e23 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Inconfirmado", "displayable" : "Visualizable", - "submit_request" : "presentar una solicitud" + "submit_request" : "presentar una solicitud", + + "address_detected" : "Dirección detectada", + "address_from_domain" : "Tienes la dirección de unstoppable domain ${domain}" } \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 6eac14e9..0db4e721 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -469,5 +469,8 @@ "unconfirmed" : "अपुष्ट", "displayable" : "प्रदर्शन योग्य", - "submit_request" : "एक अनुरोध सबमिट करें" + "submit_request" : "एक अनुरोध सबमिट करें", + + "address_detected" : "पता लग गया", + "address_from_domain" : "आपको अजेय डोमेन ${domain} से पता मिला है" } \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 291d5afd..89556602 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -469,5 +469,8 @@ "unconfirmed" : "未確認", "displayable" : "表示可能", - "submit_request" : "リクエストを送信する" + "submit_request" : "リクエストを送信する", + + "address_detected" : "アドレスが検出されました", + "address_from_domain" : "あなたはからアドレスを得ました unstoppable domain ${domain}" } \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 781df8d8..9433a418 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -469,5 +469,8 @@ "unconfirmed" : "미확인", "displayable" : "표시 가능", - "submit_request" : "요청을 제출" + "submit_request" : "요청을 제출", + + "address_detected" : "주소 감지", + "address_from_domain" : "주소는 unstoppable domain ${domain}" } \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 9a6183ef..8b8bef45 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Niet bevestigd", "displayable" : "Weer te geven", - "submit_request" : "een verzoek indienen" + "submit_request" : "een verzoek indienen", + + "address_detected" : "Adres gedetecteerd", + "address_from_domain" : "Je adres is van unstoppable domain ${domain}" } \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 6db66958..b5291e22 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Niepotwierdzony", "displayable" : "Wyświetlane", - "submit_request" : "złożyć wniosek" + "submit_request" : "złożyć wniosek", + + "address_detected" : "Wykryto adres", + "address_from_domain" : "Dostałeś adres od unstoppable domain ${domain}" } \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 631be8f4..8e955310 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Não confirmado", "displayable" : "Exibível", - "submit_request" : "enviar um pedido" + "submit_request" : "enviar um pedido", + + "address_detected" : "Endereço detectado", + "address_from_domain" : "Você obteve o endereço de unstoppable domain ${domain}" } \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 333a823d..142ae0dd 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Неподтвержденный", "displayable" : "Отображаемый", - "submit_request" : "отправить запрос" + "submit_request" : "отправить запрос", + + "address_detected" : "Обнаружен адрес", + "address_from_domain" : "Вы получили адрес из unstoppable domain ${domain}" } \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index cc10a2d8..6c659bce 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Непідтверджений", "displayable" : "Відображуваний", - "submit_request" : "надіслати запит" + "submit_request" : "надіслати запит", + + "address_detected" : "Виявлено адресу", + "address_from_domain" : "Ви отримали адресу від unstoppable domain ${domain}" } \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 639babcb..f1560941 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -469,5 +469,8 @@ "unconfirmed" : "未经证实", "displayable" : "可显示", - "submit_request" : "提交請求" + "submit_request" : "提交請求", + + "address_detected" : "檢測到地址", + "address_from_domain" : "您有以下地址 unstoppable domain ${domain}" } \ No newline at end of file From 2e22dc814a5177838169a07657b812557515a08b Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Wed, 21 Apr 2021 20:05:38 +0300 Subject: [PATCH 02/18] CAKE-192 | configured build.gradle --- android/app/build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index cef66608..e8d8aa31 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -67,7 +67,8 @@ android { release { signingConfig signingConfigs.release - minifyEnabled true + shrinkResources false + minifyEnabled false useProguard true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' From 9f1f4575ddaaa9db3f6ab70d887f8e69daf7fd5e Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Thu, 22 Apr 2021 19:16:47 +0300 Subject: [PATCH 03/18] CAKE-192 | configured build.gradle --- android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index e8d8aa31..8c89aee5 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -69,7 +69,7 @@ android { shrinkResources false minifyEnabled false - useProguard true + useProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } From 4d6cc87529cb25f860d227992a962ea70c623cd7 Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Mon, 24 May 2021 21:06:12 +0300 Subject: [PATCH 04/18] CAKE-192 | merged main branch into current; fixed call unstoppable domains api for different sdk versions; fixed italian and croatian locales --- .../cakewallet/cake_wallet/MainActivity.java | 68 +++++++--------- ios/Runner/AppDelegate.swift | 78 +++++++++---------- pubspec.lock | 6 +- res/values/strings_de.arb | 2 +- res/values/strings_en.arb | 2 +- res/values/strings_es.arb | 2 +- res/values/strings_hi.arb | 2 +- res/values/strings_hr.arb | 5 +- res/values/strings_it.arb | 5 +- res/values/strings_ja.arb | 2 +- res/values/strings_ko.arb | 2 +- res/values/strings_zh.arb | 1 + 12 files changed, 85 insertions(+), 90 deletions(-) diff --git a/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java b/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java index 074ce247..f796e541 100644 --- a/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java +++ b/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java @@ -10,29 +10,29 @@ import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import android.os.AsyncTask; +import android.os.Build; import android.os.Handler; import android.os.Looper; -import java.security.SecureRandom; import com.unstoppabledomains.resolution.DomainResolution; import com.unstoppabledomains.resolution.Resolution; -import android.os.AsyncTask; -import android.os.Handler; -import android.os.Looper; - -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; +import java.security.SecureRandom; public class MainActivity extends FlutterFragmentActivity { final String UTILS_CHANNEL = "com.cake_wallet/native_utils"; - final String UNSTOPPABLE_DOMAIN_CHANNEL = "com.cakewallet.cake_wallet/unstoppable-domain"; @Override public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine); + MethodChannel utilsChannel = + new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), + UTILS_CHANNEL); + + utilsChannel.setMethodCallHandler(this::handle); + MethodChannel unstoppableDomainChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), UNSTOPPABLE_DOMAIN_CHANNEL); @@ -41,14 +41,30 @@ public class MainActivity extends FlutterFragmentActivity { } private void handle(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { + Handler handler = new Handler(Looper.getMainLooper()); + try { - if (call.method.equals("getUnstoppableDomainAddress")) { - getUnstoppableDomainAddress(call, result); - } else { - result.notImplemented(); + switch (call.method) { + case "sec_random": + int count = call.argument("count"); + SecureRandom random = new SecureRandom(); + byte bytes[] = new byte[count]; + random.nextBytes(bytes); + handler.post(() -> result.success(bytes)); + break; + case "getUnstoppableDomainAddress": + int version = Build.VERSION.SDK_INT; + if (version >= 24) { + getUnstoppableDomainAddress(call, result); + } else { + handler.post(() -> result.success("")); + } + break; + default: + handler.post(() -> result.notImplemented()); } } catch (Exception e) { - result.error("UNCAUGHT_ERROR", e.getMessage(), null); + handler.post(() -> result.error("UNCAUGHT_ERROR", e.getMessage(), null)); } } @@ -66,29 +82,5 @@ public class MainActivity extends FlutterFragmentActivity { handler.post(() -> result.error("INVALID DOMAIN", e.getMessage(), null)); } }); - - MethodChannel utilsChannel = - new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), - UTILS_CHANNEL); - - utilsChannel.setMethodCallHandler(this::handle); - } - - private void handle(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { - Handler handler = new Handler(Looper.getMainLooper()); - - try { - if (call.method.equals("sec_random")) { - int count = call.argument("count"); - SecureRandom random = new SecureRandom(); - byte bytes[] = new byte[count]; - random.nextBytes(bytes); - handler.post(() -> result.success(bytes)); - } else { - handler.post(() -> result.notImplemented()); - } - } catch (Exception e) { - handler.post(() -> result.error("UNCAUGHT_ERROR", e.getMessage(), null)); - } } -} +} \ No newline at end of file diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index dbd93531..5a50892e 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -5,9 +5,9 @@ import UnstoppableDomainsResolution @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { lazy var resolution : Resolution? = { - return try? Resolution() - }() - + return try? Resolution() + }() + override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? @@ -17,11 +17,6 @@ import UnstoppableDomainsResolution name: "com.cakewallet.cakewallet/legacy_wallet_migration", binaryMessenger: controller.binaryMessenger) legacyMigrationChannel.setMethodCallHandler({ - let batteryChannel = FlutterMethodChannel(name: "com.cakewallet.cakewallet/legacy_wallet_migration", - binaryMessenger: controller.binaryMessenger) - let unstoppableDomainChannel = FlutterMethodChannel(name: "com.cakewallet.cake_wallet/unstoppable-domain", binaryMessenger: controller.binaryMessenger) - - batteryChannel.setMethodCallHandler({ (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in switch call.method { @@ -62,7 +57,7 @@ import UnstoppableDomainsResolution result(FlutterMethodNotImplemented) } }) - + let utilsChannel = FlutterMethodChannel( name: "com.cake_wallet/native_utils", binaryMessenger: controller.binaryMessenger) @@ -80,40 +75,41 @@ import UnstoppableDomainsResolution result(FlutterMethodNotImplemented) } }) - + + let unstoppableDomainChannel = FlutterMethodChannel(name: "com.cakewallet.cake_wallet/unstoppable-domain", binaryMessenger: controller.binaryMessenger) unstoppableDomainChannel.setMethodCallHandler({ [weak self] - (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in - switch call.method { - case "getUnstoppableDomainAddress": - guard let args = call.arguments as? Dictionary, - let domain = args["domain"], - let ticker = args["ticker"] else { - result(nil) - return - } - - guard let resolution = self?.resolution else { - result(nil) - return - } - - resolution.addr(domain: domain, ticker: ticker) { addrResult in - var address : String = "" - - switch addrResult { - case .success(let returnValue): - address = returnValue - case .failure(let error): - print("Expected Address, but got \(error)") + (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in + switch call.method { + case "getUnstoppableDomainAddress": + guard let args = call.arguments as? Dictionary, + let domain = args["domain"], + let ticker = args["ticker"] else { + result(nil) + return + } + + guard let resolution = self?.resolution else { + result(nil) + return + } + + resolution.addr(domain: domain, ticker: ticker) { addrResult in + var address : String = "" + + switch addrResult { + case .success(let returnValue): + address = returnValue + case .failure(let error): + print("Expected Address, but got \(error)") + } + + result(address) + } + default: + result(FlutterMethodNotImplemented) } - - result(address) - } - default: - result(FlutterMethodNotImplemented) - } - }) - + }) + GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } diff --git a/pubspec.lock b/pubspec.lock index 3ff59607..207f4b18 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -70,7 +70,7 @@ packages: path: "." ref: cake resolved-ref: "02fef082f20af13de00b4e64efb93a2c1e5e1cf2" - url: "git@github.com:cake-tech/bech32.git" + url: "https://github.com/cake-tech/bech32.git" source: git version: "0.2.0" bip32: @@ -92,8 +92,8 @@ packages: description: path: "." ref: cake - resolved-ref: b3ab2926c665f0e68b74a4a5f31059f7fcd817b7 - url: "git@github.com:cake-tech/bitcoin_flutter.git" + resolved-ref: cbabfd87b6ce3cae6051a3e86ddb56e7a934e188 + url: "https://github.com/cake-tech/bitcoin_flutter.git" source: git version: "2.0.2" boolean_selector: diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index da4d4975..fe64bc85 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -474,7 +474,7 @@ "buy_alert_content" : "Derzeit unterstützen wir nur den Kauf von Bitcoin. Um Bitcoin zu kaufen, erstellen Sie bitte Ihre Bitcoin-Brieftasche oder wechseln Sie zu dieser", "outdated_electrum_wallet_desceription" : "New Bitcoin wallets created in Cake now have a 24-word seed. It is mandatory that you create a new Bitcoin wallet and transfer all of your funds to the new 24-word wallet, and stop using wallets with a 12-word seed. Please do this immediately to secure your funds.", - "understand" : "I understand" + "understand" : "I understand", "address_detected" : "Adresse erkannt", "address_from_domain" : "Sie haben die Adresse von der unaufhaltsamen Domain ${domain} erhalten" diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index e43ec731..e0e25476 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -474,7 +474,7 @@ "buy_alert_content" : "Currently we only support the purchase of Bitcoin. To buy Bitcoin, please create or switch to your Bitcoin wallet", "outdated_electrum_wallet_desceription" : "New Bitcoin wallets created in Cake now have a 24-word seed. It is mandatory that you create a new Bitcoin wallet and transfer all of your funds to the new 24-word wallet, and stop using wallets with a 12-word seed. Please do this immediately to secure your funds.", - "understand" : "I understand" + "understand" : "I understand", "address_detected" : "Address detected", "address_from_domain" : "You got address from unstoppable domain ${domain}" diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 09dae1e3..a1efe9c9 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -474,7 +474,7 @@ "buy_alert_content" : "Actualmente solo apoyamos la compra de Bitcoin. Para comprar Bitcoin, cree o cambie a su billetera Bitcoin", "outdated_electrum_wallet_desceription" : "New Bitcoin wallets created in Cake now have a 24-word seed. It is mandatory that you create a new Bitcoin wallet and transfer all of your funds to the new 24-word wallet, and stop using wallets with a 12-word seed. Please do this immediately to secure your funds.", - "understand" : "I understand" + "understand" : "I understand", "address_detected" : "Dirección detectada", "address_from_domain" : "Tienes la dirección de unstoppable domain ${domain}" diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index b9a87326..899a6d9a 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -474,7 +474,7 @@ "buy_alert_content" : "वर्तमान में हम केवल बिटकॉइन की खरीद का समर्थन करते हैं। बिटकॉइन खरीदने के लिए, कृपया अपना बिटकॉइन वॉलेट बनाएं या स्विच करें", "outdated_electrum_wallet_desceription" : "New Bitcoin wallets created in Cake now have a 24-word seed. It is mandatory that you create a new Bitcoin wallet and transfer all of your funds to the new 24-word wallet, and stop using wallets with a 12-word seed. Please do this immediately to secure your funds.", - "understand" : "I understand" + "understand" : "I understand", "address_detected" : "पता लग गया", "address_from_domain" : "आपको अजेय डोमेन ${domain} से पता मिला है" diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index d449fca1..857bb790 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -474,5 +474,8 @@ "buy_alert_content" : "Currently we only support the purchase of Bitcoin. To buy Bitcoin, please create or switch to your Bitcoin wallet", "outdated_electrum_wallet_desceription" : "New Bitcoin wallets created in Cake now have a 24-word seed. It is mandatory that you create a new Bitcoin wallet and transfer all of your funds to the new 24-word wallet, and stop using wallets with a 12-word seed. Please do this immediately to secure your funds.", - "understand" : "I understand" + "understand" : "I understand", + + "address_detected" : "Adresa je otkrivena", + "address_from_domain" : "Dobili ste adresu od unstoppable domain ${domain}" } \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index e8c4da26..7d5fd783 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -474,5 +474,8 @@ "buy_alert_content" : "Currently we only support the purchase of Bitcoin. To buy Bitcoin, please create or switch to your Bitcoin wallet", "outdated_electrum_wallet_desceription" : "New Bitcoin wallets created in Cake now have a 24-word seed. It is mandatory that you create a new Bitcoin wallet and transfer all of your funds to the new 24-word wallet, and stop using wallets with a 12-word seed. Please do this immediately to secure your funds.", - "understand" : "I understand" + "understand" : "I understand", + + "address_detected" : "Indirizzo rilevato", + "address_from_domain" : "Hai l'indirizzo da unstoppable domain ${domain}" } \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 5fb87557..94ddea3d 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -474,7 +474,7 @@ "buy_alert_content" : "現在、ビットコインの購入のみをサポートしています。 ビットコインを購入するには、ビットコインウォレットを作成するか切り替えてください", "outdated_electrum_wallet_desceription" : "New Bitcoin wallets created in Cake now have a 24-word seed. It is mandatory that you create a new Bitcoin wallet and transfer all of your funds to the new 24-word wallet, and stop using wallets with a 12-word seed. Please do this immediately to secure your funds.", - "understand" : "I understand" + "understand" : "I understand", "address_detected" : "アドレスが検出されました", "address_from_domain" : "あなたはからアドレスを得ました unstoppable domain ${domain}" diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 0d64ea4f..836e36d5 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -474,7 +474,7 @@ "buy_alert_content" : "현재 우리는 비트 코인 구매 만 지원합니다. 비트 코인을 구매하려면 비트 코인 지갑을 생성하거나 전환하십시오", "outdated_electrum_wallet_desceription" : "New Bitcoin wallets created in Cake now have a 24-word seed. It is mandatory that you create a new Bitcoin wallet and transfer all of your funds to the new 24-word wallet, and stop using wallets with a 12-word seed. Please do this immediately to secure your funds.", - "understand" : "I understand" + "understand" : "I understand", "address_detected" : "주소 감지", "address_from_domain" : "주소는 unstoppable domain ${domain}" diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index ce831a4b..274108fc 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -469,6 +469,7 @@ "displayable" : "可显示", "submit_request" : "提交请求", + "buy_alert_content" : "目前,我們僅支持購買比特幣。 要購買比特幣,請創建或切換到您的比特幣錢包", "outdated_electrum_wallet_desceription" : "New Bitcoin wallets created in Cake now have a 24-word seed. It is mandatory that you create a new Bitcoin wallet and transfer all of your funds to the new 24-word wallet, and stop using wallets with a 12-word seed. Please do this immediately to secure your funds.", From f324d6599d1e1c4fa634f0fc80ed17ac45365ce4 Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Tue, 25 May 2021 16:53:35 +0300 Subject: [PATCH 05/18] CAKE-192 | added final int UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK to MainActivity.java --- .../src/main/java/com/cakewallet/cake_wallet/MainActivity.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java b/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java index f796e541..fa6930a0 100644 --- a/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java +++ b/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java @@ -22,6 +22,7 @@ import java.security.SecureRandom; public class MainActivity extends FlutterFragmentActivity { final String UTILS_CHANNEL = "com.cake_wallet/native_utils"; final String UNSTOPPABLE_DOMAIN_CHANNEL = "com.cakewallet.cake_wallet/unstoppable-domain"; + final int UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK = 24; @Override public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { @@ -54,7 +55,7 @@ public class MainActivity extends FlutterFragmentActivity { break; case "getUnstoppableDomainAddress": int version = Build.VERSION.SDK_INT; - if (version >= 24) { + if (version >= UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK) { getUnstoppableDomainAddress(call, result); } else { handler.post(() -> result.success("")); From 7ddbc6b8f420cea82b10291b7408ffdfaf617fdc Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Tue, 15 Jun 2021 22:43:50 +0300 Subject: [PATCH 06/18] CAKE-192 | added verification of open alias and unstoppable domains in exchange_page.dart and send_page.dart --- lib/src/screens/exchange/exchange_page.dart | 23 +++++++++------ lib/src/screens/send/send_page.dart | 31 +++++++++++++++------ res/values/strings_de.arb | 2 +- res/values/strings_en.arb | 2 +- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 853ff987..7b57c251 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -778,15 +778,22 @@ class ExchangePage extends BasePage { Future applyUnstoppableDomainAddress(BuildContext context, String domain, String ticker) async { - try { - final address = - await exchangeViewModel.getUnstoppableDomainAddress(domain, ticker); - if ((address != null)&&address.isNotEmpty) { - unstoppableDomainAddressAlert(context, domain); - return address; + const topLevelDomain = 'crypto'; + + if (domain.contains('.')) { + final name = domain.split('.').last; + if (name.isNotEmpty && (name == topLevelDomain)) { + try { + final address = + await exchangeViewModel.getUnstoppableDomainAddress(domain, ticker); + if ((address != null)&&address.isNotEmpty) { + unstoppableDomainAddressAlert(context, domain); + return address; + } + } catch (e) { + print(e.toString()); + } } - } catch (e) { - print(e.toString()); } return domain; diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index e40657b1..c3072b72 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -38,10 +38,9 @@ class SendPage extends BasePage { _cryptoAmountFocus = FocusNode(), _fiatAmountFocus = FocusNode(), _addressFocusNode = FocusNode() { - _addressFocusNode.addListener(() async { + _addressFocusNode.addListener(() { if (!_addressFocusNode.hasFocus && _addressController.text.isNotEmpty) { - await getOpenaliasRecord(_addressFocusNode.context); - await applyUnstoppableDomainAddress(_addressFocusNode.context); + applyOpenaliasOrUnstoppableDomains(_addressFocusNode.context); } }); } @@ -174,9 +173,8 @@ class SendPage extends BasePage { .headline .decorationColor), validator: sendViewModel.addressValidator, - onPushPasteButton: (context) async { - await getOpenaliasRecord(context); - await applyUnstoppableDomainAddress(context); + onPushPasteButton: (context) { + applyOpenaliasOrUnstoppableDomains(context); }, ), Observer( @@ -518,13 +516,12 @@ class SendPage extends BasePage { to: template.name, amount: template.amount, from: template.cryptoCurrency, - onTap: () async { + onTap: () { _addressController.text = template.address; _cryptoAmountController.text = template.amount; - await getOpenaliasRecord(context); - await applyUnstoppableDomainAddress(context); + applyOpenaliasOrUnstoppableDomains(context); }, onRemove: () { showPopUp( @@ -792,4 +789,20 @@ class SendPage extends BasePage { print(e.toString()); } } + + void applyOpenaliasOrUnstoppableDomains(BuildContext context) async { + const topLevelDomain = 'crypto'; + final address = _addressController.text; + + if (address.contains('.')) { + final name = address.split('.').last; + if (name.isNotEmpty) { + if (name == topLevelDomain) { + await applyUnstoppableDomainAddress(context); + } else { + await getOpenaliasRecord(context); + } + } + } + } } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 5df364ff..99c6f53b 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -480,7 +480,7 @@ "moonpay_alert_text" : "Der Wert des Betrags muss größer oder gleich sein ${minAmount} ${fiatCurrency}", "outdated_electrum_wallet_receive_warning": "Wenn diese Brieftasche einen 12-Wort-Seed hat und in Cake erstellt wurde, zahlen Sie KEINE Bitcoins in diese Brieftasche ein. Alle auf diese Wallet übertragenen BTC können verloren gehen. Erstellen Sie eine neue 24-Wort-Wallet (tippen Sie auf das Menü oben rechts, wählen Sie Wallets, wählen Sie Create New Wallet und dann Bitcoin) und verschieben Sie Ihre BTC SOFORT dorthin. Neue (24 Wörter) BTC-Wallets von Cake sind sicher", - "do_not_show_me": "Zeig mir das nicht noch einmal" + "do_not_show_me": "Zeig mir das nicht noch einmal", "outdated_electrum_wallet_description" : "Neue Bitcoin-Geldbörsen, die in Cake erstellt wurden, haben jetzt einen Startwert von 24 Wörtern. Es ist obligatorisch, dass Sie eine neue Bitcoin-Brieftasche erstellen, Ihr gesamtes Geld in die neue 24-Wörter-Brieftasche überweisen und keine Brieftaschen mit einem 12-Wörter-Startwert mehr verwenden. Bitte tun Sie dies sofort, um Ihr Geld zu sichern.", "understand" : "Ich verstehe", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 3dd03a13..922e00f6 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -483,7 +483,7 @@ "moonpay_alert_text" : "Value of the amount must be more or equal to ${minAmount} ${fiatCurrency}", "outdated_electrum_wallet_receive_warning": "If this wallet has a 12-word seed and was created in Cake, DO NOT deposit Bitcoin into this wallet. Any BTC transferred to this wallet may be lost. Create a new 24-word wallet (tap the menu at the top right, select Wallets, choose Create New Wallet, then select Bitcoin) and IMMEDIATELY move your BTC there. New (24-word) BTC wallets from Cake are secure", - "do_not_show_me": "Do not show me this again" + "do_not_show_me": "Do not show me this again", "address_detected" : "Address detected", "address_from_domain" : "You got address from unstoppable domain ${domain}" From 3a5932f3dfc629209536004f7fae26d2d2546268 Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Wed, 16 Jun 2021 11:44:20 +0300 Subject: [PATCH 07/18] CAKE-192 | renamed applyUnstoppableDomainAddress() to getUnstoppableDomainAddress() in the send_page.dart; fixed applyOpenaliasOrUnstoppableDomains() (send_page.dart) and applyUnstoppableDomainAddress() (exchange_page.dart) --- lib/src/screens/exchange/exchange_page.dart | 2 +- lib/src/screens/send/send_page.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 7b57c251..aa81bd1d 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -782,7 +782,7 @@ class ExchangePage extends BasePage { if (domain.contains('.')) { final name = domain.split('.').last; - if (name.isNotEmpty && (name == topLevelDomain)) { + if (name == topLevelDomain) { try { final address = await exchangeViewModel.getUnstoppableDomainAddress(domain, ticker); diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index c3072b72..5a755f26 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -774,7 +774,7 @@ class SendPage extends BasePage { context: context); } - Future applyUnstoppableDomainAddress(BuildContext context) async { + Future getUnstoppableDomainAddress(BuildContext context) async { try { final address = await sendViewModel .getUnstoppableDomainAddress( @@ -798,7 +798,7 @@ class SendPage extends BasePage { final name = address.split('.').last; if (name.isNotEmpty) { if (name == topLevelDomain) { - await applyUnstoppableDomainAddress(context); + await getUnstoppableDomainAddress(context); } else { await getOpenaliasRecord(context); } From 6709b7779a9692cfafd8186439b7e9ca1dfdfde0 Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Fri, 18 Jun 2021 15:36:49 +0300 Subject: [PATCH 08/18] CAKE-343 | applied subaddresses for contact book; added addresses field to wallet_info.dart; added updateAddressesInfo() to wallet_base.dart; applied updateAddressesInfo() to wallet services and view models --- lib/bitcoin/bitcoin_wallet_service.dart | 1 + lib/bitcoin/electrum_wallet.dart | 2 ++ lib/bitcoin/litecoin_wallet_service.dart | 1 + lib/core/wallet_base.dart | 9 +++++++ lib/di.dart | 1 + lib/entities/wallet_info.dart | 3 +++ lib/monero/monero_wallet.dart | 22 +++++++++++++++++ lib/monero/monero_wallet_service.dart | 1 + .../screens/contact/contact_list_page.dart | 24 ++++++++++--------- .../contact_list/contact_list_view_model.dart | 22 +++++++++++++---- ...ero_account_edit_or_create_view_model.dart | 10 ++++++-- ...let_address_edit_or_create_view_model.dart | 2 ++ lib/view_model/wallet_creation_vm.dart | 1 + 13 files changed, 81 insertions(+), 18 deletions(-) diff --git a/lib/bitcoin/bitcoin_wallet_service.dart b/lib/bitcoin/bitcoin_wallet_service.dart index aefe0fad..2cd3310f 100644 --- a/lib/bitcoin/bitcoin_wallet_service.dart +++ b/lib/bitcoin/bitcoin_wallet_service.dart @@ -44,6 +44,7 @@ class BitcoinWalletService extends WalletService< final wallet = await BitcoinWalletBase.open( password: password, name: name, walletInfo: walletInfo); await wallet.init(); + await wallet.updateAddressesInfo(); return wallet; } diff --git a/lib/bitcoin/electrum_wallet.dart b/lib/bitcoin/electrum_wallet.dart index bf3dfd54..bb0ee3c3 100644 --- a/lib/bitcoin/electrum_wallet.dart +++ b/lib/bitcoin/electrum_wallet.dart @@ -125,6 +125,8 @@ abstract class ElectrumWalletBase extends WalletBase rescan({int height}); void close(); + + Future updateAddressesInfo() async { + try { + walletInfo.address = address; + await walletInfo.save(); + } catch (e) { + print(e.toString()); + } + } } diff --git a/lib/di.dart b/lib/di.dart index 37b6c596..1f535037 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -362,6 +362,7 @@ Future setup( AccountListItem, void>( (AccountListItem account, _) => MoneroAccountEditOrCreateViewModel( (getIt.get().wallet as MoneroWallet).accountList, + wallet: getIt.get().wallet, accountListItem: account)); getIt.registerFactoryParam addresses; + DateTime get date => DateTime.fromMillisecondsSinceEpoch(timestamp); } diff --git a/lib/monero/monero_wallet.dart b/lib/monero/monero_wallet.dart index e902f108..753dff53 100644 --- a/lib/monero/monero_wallet.dart +++ b/lib/monero/monero_wallet.dart @@ -445,4 +445,26 @@ abstract class MoneroWalletBase extends WalletBase updateAddressesInfo() async { + final Map _addresses = {}; + final _subaddressList = MoneroSubaddressList(); + + accountList.accounts.forEach((account) { + _subaddressList.update(accountIndex: account.id); + _subaddressList.subaddresses.forEach((subaddress) { + _addresses.addAll({subaddress.address:subaddress.label}); + }); + }); + + try { + walletInfo.addresses = _addresses; + walletInfo.address = address; + + await walletInfo.save(); + } catch (e) { + print(e.toString()); + } + } } diff --git a/lib/monero/monero_wallet_service.dart b/lib/monero/monero_wallet_service.dart index 7795b870..17b02dcb 100644 --- a/lib/monero/monero_wallet_service.dart +++ b/lib/monero/monero_wallet_service.dart @@ -126,6 +126,7 @@ class MoneroWalletService extends WalletService< } await wallet.init(); + await wallet.updateAddressesInfo(); return wallet; } catch (e) { diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index bf2b593e..fd126981 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -151,17 +151,19 @@ class ContactListPage extends BasePage { crossAxisAlignment: CrossAxisAlignment.center, children: [ image ?? Offstage(), - Padding( - padding: image != null - ? EdgeInsets.only(left: 12) - : EdgeInsets.only(left: 0), - child: Text( - contact.name, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: Theme.of(context).primaryTextTheme.title.color), - ), + Expanded( + child: Padding( + padding: image != null + ? EdgeInsets.only(left: 12) + : EdgeInsets.only(left: 0), + child: Text( + contact.name, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: Theme.of(context).primaryTextTheme.title.color), + ), + ) ) ], ), 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 17083efe..fd6196c8 100644 --- a/lib/view_model/contact_list/contact_list_view_model.dart +++ b/lib/view_model/contact_list/contact_list_view_model.dart @@ -16,11 +16,23 @@ class ContactListViewModel = ContactListViewModelBase abstract class ContactListViewModelBase with Store { ContactListViewModelBase(this.contactSource, this.walletInfoSource) : contacts = ObservableList(), - walletContacts = walletInfoSource.values - .where((info) => info.address?.isNotEmpty ?? false) - .map((info) => WalletContact( - info.address, info.name, walletTypeToCryptoCurrency(info.type))) - .toList() { + walletContacts = [] { + walletInfoSource.values.forEach((info) { + if (info.address?.isNotEmpty ?? false) { + if (info.addresses != null) { + info.addresses.forEach((address, label) { + walletContacts.add(WalletContact( + address, + info.name + ' ($label)', + walletTypeToCryptoCurrency(info.type))); + }); + } else { + walletContacts.add(WalletContact(info.address, info.name, + walletTypeToCryptoCurrency(info.type))); + } + } + }); + _subscription = contactSource.bindToListWithTransform( contacts, (Contact contact) => ContactRecord(contactSource, contact), initialFire: true); diff --git a/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart b/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart index d32f8ead..cf999e41 100644 --- a/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart +++ b/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/core/wallet_base.dart'; +import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/monero/monero_account_list.dart'; @@ -10,11 +12,12 @@ class MoneroAccountEditOrCreateViewModel = MoneroAccountEditOrCreateViewModelBas abstract class MoneroAccountEditOrCreateViewModelBase with Store { MoneroAccountEditOrCreateViewModelBase(this._moneroAccountList, - {AccountListItem accountListItem}) + {@required WalletBase wallet, AccountListItem accountListItem}) : state = InitialExecutionState(), isEdit = accountListItem != null, label = accountListItem?.label??'', - _accountListItem = accountListItem; + _accountListItem = accountListItem, + _wallet = wallet; final bool isEdit; @@ -26,6 +29,7 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store { final MoneroAccountList _moneroAccountList; final AccountListItem _accountListItem; + final WalletBase _wallet; Future save() async { try { @@ -38,6 +42,8 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store { await _moneroAccountList.addAccount(label: label); } + await _wallet.updateAddressesInfo(); + state = ExecutedSuccessfullyState(); } catch (e) { state = FailureState(e.toString()); diff --git a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart index b018c542..6b6873cd 100644 --- a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart @@ -54,6 +54,8 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { await _createNew(); } + await _wallet.updateAddressesInfo(); + state = AddressSavedSuccessfully(); } catch (e) { state = AddressEditOrCreateStateFailure(error: e.toString()); diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 58ee2408..54cad29c 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -54,6 +54,7 @@ abstract class WalletCreationVMBase with Store { await _walletInfoSource.add(walletInfo); _appStore.changeCurrentWallet(wallet); _appStore.authenticationStore.allowed(); + await wallet.updateAddressesInfo(); state = ExecutedSuccessfullyState(); } catch (e) { state = FailureState(e.toString()); From bb219e4da27b9cbf5bcd6198be6e1e653b5fc9ac Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Tue, 22 Jun 2021 11:29:30 +0300 Subject: [PATCH 09/18] CAKE-192 | created parse_address_from_domain.dart; applied parseAddressFromDomain() to send_page.dart and exchange_page.dart; deleted unstoppable_domain_address_alert.dart --- lib/src/screens/exchange/exchange_page.dart | 53 +++++------------- .../send/parse_address_from_domain.dart | 53 ++++++++++++++++++ lib/src/screens/send/send_page.dart | 55 ++----------------- .../unstoppable_domain_address_alert.dart | 17 ------ .../exchange/exchange_view_model.dart | 5 -- lib/view_model/send/send_view_model.dart | 15 ----- res/values/strings_zh.arb | 8 +-- 7 files changed, 77 insertions(+), 129 deletions(-) create mode 100644 lib/src/screens/send/parse_address_from_domain.dart delete mode 100644 lib/src/screens/send/widgets/unstoppable_domain_address_alert.dart diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index aa81bd1d..fa69d5da 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -1,7 +1,7 @@ import 'dart:ui'; import 'package:cake_wallet/entities/sync_status.dart'; import 'package:cake_wallet/entities/wallet_type.dart'; -import 'package:cake_wallet/src/screens/send/widgets/unstoppable_domain_address_alert.dart'; +import 'package:cake_wallet/src/screens/send/parse_address_from_domain.dart'; import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:flutter/cupertino.dart'; @@ -226,10 +226,10 @@ class ExchangePage extends BasePage { onPushPasteButton: (context) async { final domain = exchangeViewModel.depositAddress; - final ticker = - exchangeViewModel.depositCurrency.title; + final ticker = exchangeViewModel + .depositCurrency.title.toLowerCase(); exchangeViewModel.depositAddress = - await applyUnstoppableDomainAddress( + await parseAddressFromDomain( context, domain, ticker); }, ), @@ -281,10 +281,10 @@ class ExchangePage extends BasePage { onPushPasteButton: (context) async { final domain = exchangeViewModel.receiveAddress; - final ticker = - exchangeViewModel.receiveCurrency.title; + final ticker = exchangeViewModel + .receiveCurrency.title.toLowerCase(); exchangeViewModel.receiveAddress = - await applyUnstoppableDomainAddress( + await parseAddressFromDomain( context, domain, ticker); }, )), @@ -512,14 +512,14 @@ class ExchangePage extends BasePage { exchangeViewModel.isFixedRateMode = false; var domain = template.depositAddress; - var ticker = template.depositCurrency; + var ticker = template.depositCurrency.toLowerCase(); exchangeViewModel.depositAddress = - await applyUnstoppableDomainAddress(context, domain, ticker); + await parseAddressFromDomain(context, domain, ticker); domain = template.receiveAddress; - ticker = template.receiveCurrency; + ticker = template.receiveCurrency.toLowerCase(); exchangeViewModel.receiveAddress = - await applyUnstoppableDomainAddress(context, domain, ticker); + await parseAddressFromDomain(context, domain, ticker); } void _setReactions( @@ -689,9 +689,9 @@ class ExchangePage extends BasePage { if (!_depositAddressFocus.hasFocus && depositAddressController.text.isNotEmpty) { final domain = depositAddressController.text; - final ticker = exchangeViewModel.depositCurrency.title; + final ticker = exchangeViewModel.depositCurrency.title.toLowerCase(); exchangeViewModel.depositAddress = - await applyUnstoppableDomainAddress(context, domain, ticker); + await parseAddressFromDomain(context, domain, ticker); } }); @@ -699,9 +699,9 @@ class ExchangePage extends BasePage { if (!_receiveAddressFocus.hasFocus && receiveAddressController.text.isNotEmpty) { final domain = receiveAddressController.text; - final ticker = exchangeViewModel.receiveCurrency.title; + final ticker = exchangeViewModel.receiveCurrency.title.toLowerCase(); exchangeViewModel.receiveAddress = - await applyUnstoppableDomainAddress(context, domain, ticker); + await parseAddressFromDomain(context, domain, ticker); } }); @@ -775,27 +775,4 @@ class ExchangePage extends BasePage { key.currentState.addressController.text = null; } } - - Future applyUnstoppableDomainAddress(BuildContext context, - String domain, String ticker) async { - const topLevelDomain = 'crypto'; - - if (domain.contains('.')) { - final name = domain.split('.').last; - if (name == topLevelDomain) { - try { - final address = - await exchangeViewModel.getUnstoppableDomainAddress(domain, ticker); - if ((address != null)&&address.isNotEmpty) { - unstoppableDomainAddressAlert(context, domain); - return address; - } - } catch (e) { - print(e.toString()); - } - } - } - - return domain; - } } diff --git a/lib/src/screens/send/parse_address_from_domain.dart b/lib/src/screens/send/parse_address_from_domain.dart new file mode 100644 index 00000000..b114ef88 --- /dev/null +++ b/lib/src/screens/send/parse_address_from_domain.dart @@ -0,0 +1,53 @@ +import 'package:cake_wallet/entities/openalias_record.dart'; +import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/generated/i18n.dart'; + +const topLevelDomain = 'crypto'; + +Future parseAddressFromDomain( + BuildContext context, String domain, String ticker) async { + try { + final name = domain.split('.').last; + + if (name.contains(topLevelDomain)) { + final address = await fetchUnstoppableDomainAddress(domain, ticker); + if (address.isNotEmpty) { + showAddressAlert( + context, + S.of(context).address_detected, + S.of(context).address_from_domain(domain)); + return address; + } + } else if (name.isNotEmpty) { + final record = await OpenaliasRecord.fetchAddressAndName( + OpenaliasRecord.formatDomainName(domain)); + if (record.name != null && record.name != domain) { + showAddressAlert( + context, + S.of(context).openalias_alert_title, + S.of(context).openalias_alert_content(domain)); + return record.address; + } + } + } catch (e) { + print(e.toString()); + } + + return domain; +} + +void showAddressAlert(BuildContext context, String title, String content) async { + await showPopUp( + context: context, + builder: (BuildContext context) { + + return AlertWithOneAction( + alertTitle: title, + alertContent: content, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); +} \ No newline at end of file diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 5a755f26..92b6c54d 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,6 +1,6 @@ import 'dart:ui'; import 'package:cake_wallet/entities/transaction_priority.dart'; -import 'package:cake_wallet/src/screens/send/widgets/unstoppable_domain_address_alert.dart'; +import 'package:cake_wallet/src/screens/send/parse_address_from_domain.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; @@ -736,26 +736,6 @@ class SendPage extends BasePage { _effectsInstalled = true; } - Future getOpenaliasRecord(BuildContext context) async { - final record = - await sendViewModel.decodeOpenaliasRecord(_addressController.text); - - if (record != null) { - _addressController.text = record.address; - - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: S.of(context).openalias_alert_title, - alertContent: - S.of(context).openalias_alert_content(record.name), - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); - } - } - Future _setTransactionPriority(BuildContext context) async { final items = priorityForWalletType(sendViewModel.walletType); final selectedItem = items.indexOf(sendViewModel.transactionPriority); @@ -774,35 +754,10 @@ class SendPage extends BasePage { context: context); } - Future getUnstoppableDomainAddress(BuildContext context) async { - try { - final address = await sendViewModel - .getUnstoppableDomainAddress( - _addressController.text); - - if ((address != null)&&address.isNotEmpty) { - unstoppableDomainAddressAlert( - context, _addressController.text); - _addressController.text = address; - } - } catch (e) { - print(e.toString()); - } - } - void applyOpenaliasOrUnstoppableDomains(BuildContext context) async { - const topLevelDomain = 'crypto'; - final address = _addressController.text; - - if (address.contains('.')) { - final name = address.split('.').last; - if (name.isNotEmpty) { - if (name == topLevelDomain) { - await getUnstoppableDomainAddress(context); - } else { - await getOpenaliasRecord(context); - } - } - } + final domain = _addressController.text; + final ticker = sendViewModel.currency.title.toLowerCase(); + _addressController.text = + await parseAddressFromDomain(context, domain, ticker); } } diff --git a/lib/src/screens/send/widgets/unstoppable_domain_address_alert.dart b/lib/src/screens/send/widgets/unstoppable_domain_address_alert.dart deleted file mode 100644 index 011a3679..00000000 --- a/lib/src/screens/send/widgets/unstoppable_domain_address_alert.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:flutter/material.dart'; -import 'package:cake_wallet/generated/i18n.dart'; - -void unstoppableDomainAddressAlert(BuildContext context, String domain) async { - await showPopUp( - context: context, - builder: (BuildContext context) { - - return AlertWithOneAction( - alertTitle: S.of(context).address_detected, - alertContent: S.of(context).address_from_domain(domain), - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); -} \ No newline at end of file diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 7f0f601a..f3f00cd7 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -4,7 +4,6 @@ import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart'; import 'package:cake_wallet/core/wallet_base.dart'; import 'package:cake_wallet/entities/crypto_currency.dart'; import 'package:cake_wallet/entities/sync_status.dart'; -import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; import 'package:cake_wallet/entities/wallet_type.dart'; import 'package:cake_wallet/exchange/exchange_provider.dart'; import 'package:cake_wallet/exchange/limits.dart'; @@ -423,8 +422,4 @@ abstract class ExchangeViewModelBase with Store { }*/ isReceiveAmountEditable = false; } - - Future getUnstoppableDomainAddress(String domain, String ticker) async { - return await fetchUnstoppableDomainAddress(domain, ticker.toLowerCase()); - } } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 850ec0b3..3fdcbc52 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -1,17 +1,14 @@ import 'package:cake_wallet/bitcoin/bitcoin_amount_format.dart'; import 'package:cake_wallet/bitcoin/bitcoin_transaction_priority.dart'; import 'package:cake_wallet/bitcoin/electrum_wallet.dart'; -import 'package:cake_wallet/entities/balance_display_mode.dart'; import 'package:cake_wallet/entities/calculate_fiat_amount_raw.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; import 'package:cake_wallet/entities/transaction_priority.dart'; -import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; import 'package:cake_wallet/monero/monero_amount_format.dart'; import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:hive/hive.dart'; import 'package:intl/intl.dart'; import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/entities/openalias_record.dart'; import 'package:cake_wallet/entities/template.dart'; import 'package:cake_wallet/store/templates/send_template_store.dart'; import 'package:cake_wallet/core/template_validator.dart'; @@ -21,7 +18,6 @@ import 'package:cake_wallet/core/pending_transaction.dart'; import 'package:cake_wallet/core/validator.dart'; import 'package:cake_wallet/core/wallet_base.dart'; import 'package:cake_wallet/core/execution_state.dart'; -import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart'; import 'package:cake_wallet/bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cake_wallet/monero/monero_wallet.dart'; import 'package:cake_wallet/monero/monero_transaction_creation_credentials.dart'; @@ -265,17 +261,6 @@ abstract class SendViewModelBase with Store { void setTransactionPriority(TransactionPriority priority) => _settingsStore.priority[_wallet.type] = priority; - Future decodeOpenaliasRecord(String name) async { - final record = await OpenaliasRecord.fetchAddressAndName( - OpenaliasRecord.formatDomainName(name)); - - return record.name != name ? record : null; - } - - Future getUnstoppableDomainAddress(String domain) async { - return await fetchUnstoppableDomainAddress(domain, currency.title.toLowerCase()); - } - @action void _updateFiatAmount() { try { diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index b5a76f9a..d7867ca4 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -482,9 +482,9 @@ "buy_with" : "一起购买", "moonpay_alert_text" : "金额的价值必须大于或等于 ${minAmount} ${fiatCurrency}", - "address_detected" : "檢測到地址", - "address_from_domain" : "您有以下地址 unstoppable domain ${domain}", - "outdated_electrum_wallet_receive_warning": "如果这个钱包有一个 12 字的种子并且是在 Cake 中创建的,不要将比特币存入这个钱包。 任何转移到此钱包的 BTC 都可能丢失。 创建一个新的 24 字钱包(点击右上角的菜单,选择钱包,选择创建新钱包,然后选择比特币)并立即将您的 BTC 移到那里。 Cake 的新(24 字)BTC 钱包是安全的", - "do_not_show_me": "不再提示" + "do_not_show_me": "不再提示", + + "address_detected" : "檢測到地址", + "address_from_domain" : "您有以下地址 unstoppable domain ${domain}" } \ No newline at end of file From 1e3b53d2cf2dcaf3f2786d430d2497dcb25a2637 Mon Sep 17 00:00:00 2001 From: M Date: Tue, 6 Jul 2021 13:51:54 +0300 Subject: [PATCH 10/18] Added backups for monero wallet files. --- lib/monero/monero_wallet.dart | 2 + lib/monero/monero_wallet_service.dart | 16 ++--- lib/monero/monero_wallet_utils.dart | 88 +++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 lib/monero/monero_wallet_utils.dart diff --git a/lib/monero/monero_wallet.dart b/lib/monero/monero_wallet.dart index e902f108..4105e5de 100644 --- a/lib/monero/monero_wallet.dart +++ b/lib/monero/monero_wallet.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/transaction_priority.dart'; import 'package:cake_wallet/monero/monero_amount_format.dart'; import 'package:cake_wallet/monero/monero_transaction_creation_exception.dart'; import 'package:cake_wallet/monero/monero_transaction_info.dart'; +import 'package:cake_wallet/monero/monero_wallet_utils.dart'; import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_monero/transaction_history.dart' @@ -246,6 +247,7 @@ abstract class MoneroWalletBase extends WalletBase getNodeHeight() async => monero_wallet.getNodeHeight(); diff --git a/lib/monero/monero_wallet_service.dart b/lib/monero/monero_wallet_service.dart index 7795b870..824daf41 100644 --- a/lib/monero/monero_wallet_service.dart +++ b/lib/monero/monero_wallet_service.dart @@ -1,5 +1,6 @@ import 'dart:io'; import 'package:cake_wallet/core/wallet_base.dart'; +import 'package:cake_wallet/monero/monero_wallet_utils.dart'; import 'package:hive/hive.dart'; import 'package:cw_monero/wallet_manager.dart' as monero_wallet_manager; import 'package:cw_monero/wallet.dart' as monero_wallet; @@ -55,16 +56,7 @@ class MoneroWalletService extends WalletService< MoneroWalletService(this.walletInfoSource); final Box walletInfoSource; - - static Future _removeCache(String name) async { - final path = await pathForWallet(name: name, type: WalletType.monero); - final cacheFile = File(path); - - if (cacheFile.existsSync()) { - cacheFile.deleteSync(); - } - } - + static bool walletFilesExist(String path) => !File(path).existsSync() && !File('$path.keys').existsSync(); @@ -120,7 +112,7 @@ class MoneroWalletService extends WalletService< final isValid = wallet.validate(); if (!isValid) { - await _removeCache(name); + await restoreOrResetWalletFiles(name); wallet.close(); return openWallet(name, password); } @@ -135,7 +127,7 @@ class MoneroWalletService extends WalletService< (e is WalletOpeningException && (e.message == 'std::bad_alloc' || e.message.contains('bad_alloc')))) { - await _removeCache(name); + await restoreOrResetWalletFiles(name); return openWallet(name, password); } diff --git a/lib/monero/monero_wallet_utils.dart b/lib/monero/monero_wallet_utils.dart new file mode 100644 index 00000000..b0e50908 --- /dev/null +++ b/lib/monero/monero_wallet_utils.dart @@ -0,0 +1,88 @@ +import 'dart:io'; +import 'package:cake_wallet/entities/pathForWallet.dart'; +import 'package:cake_wallet/entities/wallet_type.dart'; + +String backupFileName(String originalPath) { + final pathParts = originalPath.split('/'); + final newName = '#_${pathParts.last}'; + pathParts.removeLast(); + pathParts.add(newName); + return pathParts.join('/'); +} + +Future backupWalletFiles(String name) async { + final path = await pathForWallet(name: name, type: WalletType.monero); + final cacheFile = File(path); + final keysFile = File('$path.keys'); + final addressListFile = File('$path.address.txt'); + final newCacheFilePath = backupFileName(cacheFile.path); + final newKeysFilePath = backupFileName(keysFile.path); + final newAddressListFilePath = backupFileName(addressListFile.path); + + if (cacheFile.existsSync()) { + await cacheFile.copy(newCacheFilePath); + } + + if (keysFile.existsSync()) { + await keysFile.copy(newKeysFilePath); + } + + if (addressListFile.existsSync()) { + await addressListFile.copy(newAddressListFilePath); + } +} + +Future restoreWalletFiles(String name) async { + final walletDirPath = await pathForWalletDir(name: name, type: WalletType.monero); + final cacheFilePath = '$walletDirPath/$name'; + final keysFilePath = '$walletDirPath/$name.keys'; + final addressListFilePath = '$walletDirPath/$name.address.txt'; + final backupCacheFile = File(backupFileName(cacheFilePath)); + final backupKeysFile = File(backupFileName(keysFilePath)); + final backupAddressListFile = File(backupFileName(addressListFilePath)); + + if (backupCacheFile.existsSync()) { + await backupCacheFile.copy(cacheFilePath); + } + + if (backupKeysFile.existsSync()) { + await backupKeysFile.copy(keysFilePath); + } + + if (backupAddressListFile.existsSync()) { + await backupAddressListFile.copy(addressListFilePath); + } +} + +Future backupWalletFilesExists(String name) async { + final walletDirPath = await pathForWalletDir(name: name, type: WalletType.monero); + final cacheFilePath = '$walletDirPath/$name'; + final keysFilePath = '$walletDirPath/$name.keys'; + final addressListFilePath = '$walletDirPath/$name.address.txt'; + final backupCacheFile = File(backupFileName(cacheFilePath)); + final backupKeysFile = File(backupFileName(keysFilePath)); + final backupAddressListFile = File(backupFileName(addressListFilePath)); + + return backupCacheFile.existsSync() + && backupKeysFile.existsSync() + && backupAddressListFile.existsSync(); +} + +Future removeCache(String name) async { + final path = await pathForWallet(name: name, type: WalletType.monero); + final cacheFile = File(path); + + if (cacheFile.existsSync()) { + cacheFile.deleteSync(); + } +} + +Future restoreOrResetWalletFiles(String name) async { + final backupsExists = await backupWalletFilesExists(name); + + if (backupsExists) { + await restoreWalletFiles(name); + } + + removeCache(name); +} \ No newline at end of file From c72245d90463e460de6fa91a826ef54d4857b371 Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Wed, 7 Jul 2021 12:29:33 +0300 Subject: [PATCH 11/18] CAKE-343 | fixed contact_list_view_model.dart and updateAddressInfo() in the monero_wallet.dart --- lib/monero/monero_wallet.dart | 2 +- lib/view_model/contact_list/contact_list_view_model.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/monero/monero_wallet.dart b/lib/monero/monero_wallet.dart index 753dff53..c9ea9e03 100644 --- a/lib/monero/monero_wallet.dart +++ b/lib/monero/monero_wallet.dart @@ -454,7 +454,7 @@ abstract class MoneroWalletBase extends WalletBase Date: Wed, 7 Jul 2021 16:50:55 +0300 Subject: [PATCH 12/18] CAKE-192 | parse_address_from_domain.dart fixed and split on 2 files (current and parse_address_from_domain_alert.dart), then moved to the entities directory; used one channel for native calls; removed unneeded spaces; fixed handle of unstoppable domain error in the MainActivity.java --- .../cakewallet/cake_wallet/MainActivity.java | 10 +--- ios/Runner/AppDelegate.swift | 57 +++++++------------ lib/entities/parse_address_from_domain.dart | 52 +++++++++++++++++ lib/entities/unstoppable_domain_address.dart | 4 +- lib/src/screens/exchange/exchange_page.dart | 2 +- .../send/parse_address_from_domain.dart | 53 ----------------- lib/src/screens/send/send_page.dart | 2 +- .../parse_address_from_domain_alert.dart | 17 ++++++ 8 files changed, 97 insertions(+), 100 deletions(-) create mode 100644 lib/entities/parse_address_from_domain.dart delete mode 100644 lib/src/screens/send/parse_address_from_domain.dart create mode 100644 lib/src/screens/send/widgets/parse_address_from_domain_alert.dart diff --git a/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java b/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java index fa6930a0..3afdc111 100644 --- a/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java +++ b/android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java @@ -21,7 +21,6 @@ import java.security.SecureRandom; public class MainActivity extends FlutterFragmentActivity { final String UTILS_CHANNEL = "com.cake_wallet/native_utils"; - final String UNSTOPPABLE_DOMAIN_CHANNEL = "com.cakewallet.cake_wallet/unstoppable-domain"; final int UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK = 24; @Override @@ -33,12 +32,6 @@ public class MainActivity extends FlutterFragmentActivity { UTILS_CHANNEL); utilsChannel.setMethodCallHandler(this::handle); - - MethodChannel unstoppableDomainChannel = - new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), - UNSTOPPABLE_DOMAIN_CHANNEL); - - unstoppableDomainChannel.setMethodCallHandler(this::handle); } private void handle(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { @@ -80,7 +73,8 @@ public class MainActivity extends FlutterFragmentActivity { String address = resolution.getAddress(domain, ticker); handler.post(() -> result.success(address)); } catch (Exception e) { - handler.post(() -> result.error("INVALID DOMAIN", e.getMessage(), null)); + System.out.println("Expected Address, but got " + e.getMessage()); + handler.post(() -> result.success("")); } }); } diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 859a6e62..50b6e39d 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -5,7 +5,7 @@ import UnstoppableDomainsResolution @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { lazy var resolution : Resolution? = { - return try? Resolution() + return try? Resolution() }() override func application( @@ -75,45 +75,32 @@ import UnstoppableDomainsResolution } result(secRandom(count: count)) + case "getUnstoppableDomainAddress": + guard let args = call.arguments as? Dictionary, + let domain = args["domain"], + let ticker = args["ticker"], + let resolution = self?.resolution else { + result(nil) + return + } + + resolution.addr(domain: domain, ticker: ticker) { addrResult in + var address : String = "" + + switch addrResult { + case .success(let returnValue): + address = returnValue + case .failure(let error): + print("Expected Address, but got \(error)") + } + + result(address) + } default: result(FlutterMethodNotImplemented) } }) - let unstoppableDomainChannel = FlutterMethodChannel(name: "com.cakewallet.cake_wallet/unstoppable-domain", binaryMessenger: controller.binaryMessenger) - unstoppableDomainChannel.setMethodCallHandler({ [weak self] - (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in - switch call.method { - case "getUnstoppableDomainAddress": - guard let args = call.arguments as? Dictionary, - let domain = args["domain"], - let ticker = args["ticker"] else { - result(nil) - return - } - - guard let resolution = self?.resolution else { - result(nil) - return - } - - resolution.addr(domain: domain, ticker: ticker) { addrResult in - var address : String = "" - - switch addrResult { - case .success(let returnValue): - address = returnValue - case .failure(let error): - print("Expected Address, but got \(error)") - } - - result(address) - } - default: - result(FlutterMethodNotImplemented) - } - }) - GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart new file mode 100644 index 00000000..b8112036 --- /dev/null +++ b/lib/entities/parse_address_from_domain.dart @@ -0,0 +1,52 @@ +import 'package:cake_wallet/entities/openalias_record.dart'; +import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; +import 'package:cake_wallet/src/screens/send/widgets/parse_address_from_domain_alert.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/generated/i18n.dart'; + +const topLevelDomain = 'crypto'; + +Future parseAddressFromDomain( + BuildContext context, String domain, String ticker) async { + try { + final domainParts = domain.split('.'); + final name = domainParts.last; + + if (domainParts.length <= 1 || domainParts.first.isEmpty || name.isEmpty) { + return domain; + } + + if (name.contains(topLevelDomain)) { + final address = await fetchUnstoppableDomainAddress(domain, ticker); + + if (address?.isEmpty ?? true) { + return domain; + } + + showAddressAlert( + context, + S.of(context).address_detected, + S.of(context).address_from_domain(domain)); + + return address; + } + + final record = await OpenaliasRecord.fetchAddressAndName( + OpenaliasRecord.formatDomainName(domain)); + + if (record == null || record.address.contains(domain)) { + return domain; + } + + showAddressAlert( + context, + S.of(context).openalias_alert_title, + S.of(context).openalias_alert_content(domain)); + + return record.address; + } catch (e) { + print(e.toString()); + } + + return domain; +} \ No newline at end of file diff --git a/lib/entities/unstoppable_domain_address.dart b/lib/entities/unstoppable_domain_address.dart index 494782d5..792f9a34 100644 --- a/lib/entities/unstoppable_domain_address.dart +++ b/lib/entities/unstoppable_domain_address.dart @@ -1,9 +1,9 @@ import 'package:flutter/services.dart'; -const channel = MethodChannel('com.cakewallet.cake_wallet/unstoppable-domain'); +const channel = MethodChannel('com.cake_wallet/native_utils'); Future fetchUnstoppableDomainAddress(String domain, String ticker) async { - String address; + var address = ''; try { address = await channel.invokeMethod( diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index fa69d5da..2209fe01 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -1,7 +1,7 @@ import 'dart:ui'; import 'package:cake_wallet/entities/sync_status.dart'; import 'package:cake_wallet/entities/wallet_type.dart'; -import 'package:cake_wallet/src/screens/send/parse_address_from_domain.dart'; +import 'package:cake_wallet/entities/parse_address_from_domain.dart'; import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:flutter/cupertino.dart'; diff --git a/lib/src/screens/send/parse_address_from_domain.dart b/lib/src/screens/send/parse_address_from_domain.dart deleted file mode 100644 index b114ef88..00000000 --- a/lib/src/screens/send/parse_address_from_domain.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:cake_wallet/entities/openalias_record.dart'; -import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:flutter/material.dart'; -import 'package:cake_wallet/generated/i18n.dart'; - -const topLevelDomain = 'crypto'; - -Future parseAddressFromDomain( - BuildContext context, String domain, String ticker) async { - try { - final name = domain.split('.').last; - - if (name.contains(topLevelDomain)) { - final address = await fetchUnstoppableDomainAddress(domain, ticker); - if (address.isNotEmpty) { - showAddressAlert( - context, - S.of(context).address_detected, - S.of(context).address_from_domain(domain)); - return address; - } - } else if (name.isNotEmpty) { - final record = await OpenaliasRecord.fetchAddressAndName( - OpenaliasRecord.formatDomainName(domain)); - if (record.name != null && record.name != domain) { - showAddressAlert( - context, - S.of(context).openalias_alert_title, - S.of(context).openalias_alert_content(domain)); - return record.address; - } - } - } catch (e) { - print(e.toString()); - } - - return domain; -} - -void showAddressAlert(BuildContext context, String title, String content) async { - await showPopUp( - context: context, - builder: (BuildContext context) { - - return AlertWithOneAction( - alertTitle: title, - alertContent: content, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); -} \ No newline at end of file diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 92b6c54d..3d7e011e 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,6 +1,6 @@ import 'dart:ui'; import 'package:cake_wallet/entities/transaction_priority.dart'; -import 'package:cake_wallet/src/screens/send/parse_address_from_domain.dart'; +import 'package:cake_wallet/entities/parse_address_from_domain.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; diff --git a/lib/src/screens/send/widgets/parse_address_from_domain_alert.dart b/lib/src/screens/send/widgets/parse_address_from_domain_alert.dart new file mode 100644 index 00000000..76009161 --- /dev/null +++ b/lib/src/screens/send/widgets/parse_address_from_domain_alert.dart @@ -0,0 +1,17 @@ +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/generated/i18n.dart'; + +void showAddressAlert(BuildContext context, String title, String content) async { + await showPopUp( + context: context, + builder: (BuildContext context) { + + return AlertWithOneAction( + alertTitle: title, + alertContent: content, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); +} \ No newline at end of file From bac491c44f33e6ba0b69fd74dc2fd7bb378b3c5e Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Wed, 7 Jul 2021 17:31:16 +0300 Subject: [PATCH 13/18] CAKE-192 | created ParsedAddress class; applied this class to parse_address_from_domain.dart, send_page.dart and exchange_page.dart --- lib/entities/parse_address_from_domain.dart | 30 +++++----------- lib/entities/parsed_address.dart | 8 +++++ lib/src/screens/exchange/exchange_page.dart | 38 +++++++++++++++++---- lib/src/screens/send/send_page.dart | 23 +++++++++++-- 4 files changed, 70 insertions(+), 29 deletions(-) create mode 100644 lib/entities/parsed_address.dart diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index b8112036..0c2b864d 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -1,52 +1,40 @@ import 'package:cake_wallet/entities/openalias_record.dart'; +import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; -import 'package:cake_wallet/src/screens/send/widgets/parse_address_from_domain_alert.dart'; -import 'package:flutter/material.dart'; -import 'package:cake_wallet/generated/i18n.dart'; const topLevelDomain = 'crypto'; -Future parseAddressFromDomain( - BuildContext context, String domain, String ticker) async { +Future parseAddressFromDomain( + String domain, String ticker) async { try { final domainParts = domain.split('.'); final name = domainParts.last; if (domainParts.length <= 1 || domainParts.first.isEmpty || name.isEmpty) { - return domain; + return ParsedAddress(domain, ParseFrom.notParsed); } if (name.contains(topLevelDomain)) { final address = await fetchUnstoppableDomainAddress(domain, ticker); if (address?.isEmpty ?? true) { - return domain; + return ParsedAddress(domain, ParseFrom.notParsed); } - showAddressAlert( - context, - S.of(context).address_detected, - S.of(context).address_from_domain(domain)); - - return address; + return ParsedAddress(address, ParseFrom.unstoppableDomains); } final record = await OpenaliasRecord.fetchAddressAndName( OpenaliasRecord.formatDomainName(domain)); if (record == null || record.address.contains(domain)) { - return domain; + return ParsedAddress(domain, ParseFrom.notParsed); } - showAddressAlert( - context, - S.of(context).openalias_alert_title, - S.of(context).openalias_alert_content(domain)); - - return record.address; + return ParsedAddress(record.address, ParseFrom.openAlias); } catch (e) { print(e.toString()); } - return domain; + return ParsedAddress(domain, ParseFrom.notParsed); } \ No newline at end of file diff --git a/lib/entities/parsed_address.dart b/lib/entities/parsed_address.dart new file mode 100644 index 00000000..f293d99c --- /dev/null +++ b/lib/entities/parsed_address.dart @@ -0,0 +1,8 @@ +enum ParseFrom {unstoppableDomains, openAlias, notParsed} + +class ParsedAddress { + ParsedAddress(this.address, this.parseFrom); + + final String address; + final ParseFrom parseFrom; +} \ No newline at end of file diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 2209fe01..693eade7 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -1,7 +1,9 @@ import 'dart:ui'; +import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/entities/sync_status.dart'; import 'package:cake_wallet/entities/wallet_type.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; +import 'package:cake_wallet/src/screens/send/widgets/parse_address_from_domain_alert.dart'; import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:flutter/cupertino.dart'; @@ -229,7 +231,7 @@ class ExchangePage extends BasePage { final ticker = exchangeViewModel .depositCurrency.title.toLowerCase(); exchangeViewModel.depositAddress = - await parseAddressFromDomain( + await applyOpenaliasOrUnstoppableDomains( context, domain, ticker); }, ), @@ -284,7 +286,7 @@ class ExchangePage extends BasePage { final ticker = exchangeViewModel .receiveCurrency.title.toLowerCase(); exchangeViewModel.receiveAddress = - await parseAddressFromDomain( + await applyOpenaliasOrUnstoppableDomains( context, domain, ticker); }, )), @@ -514,12 +516,12 @@ class ExchangePage extends BasePage { var domain = template.depositAddress; var ticker = template.depositCurrency.toLowerCase(); exchangeViewModel.depositAddress = - await parseAddressFromDomain(context, domain, ticker); + await applyOpenaliasOrUnstoppableDomains(context, domain, ticker); domain = template.receiveAddress; ticker = template.receiveCurrency.toLowerCase(); exchangeViewModel.receiveAddress = - await parseAddressFromDomain(context, domain, ticker); + await applyOpenaliasOrUnstoppableDomains(context, domain, ticker); } void _setReactions( @@ -691,7 +693,7 @@ class ExchangePage extends BasePage { final domain = depositAddressController.text; final ticker = exchangeViewModel.depositCurrency.title.toLowerCase(); exchangeViewModel.depositAddress = - await parseAddressFromDomain(context, domain, ticker); + await applyOpenaliasOrUnstoppableDomains(context, domain, ticker); } }); @@ -701,7 +703,7 @@ class ExchangePage extends BasePage { final domain = receiveAddressController.text; final ticker = exchangeViewModel.receiveCurrency.title.toLowerCase(); exchangeViewModel.receiveAddress = - await parseAddressFromDomain(context, domain, ticker); + await applyOpenaliasOrUnstoppableDomains(context, domain, ticker); } }); @@ -775,4 +777,28 @@ class ExchangePage extends BasePage { key.currentState.addressController.text = null; } } + + Future applyOpenaliasOrUnstoppableDomains( + BuildContext context, String domain, String ticker) async { + final parsedAddress = await parseAddressFromDomain(domain, ticker); + + switch (parsedAddress.parseFrom) { + case ParseFrom.unstoppableDomains: + showAddressAlert( + context, + S.of(context).address_detected, + S.of(context).address_from_domain(domain)); + break; + case ParseFrom.openAlias: + showAddressAlert( + context, + S.of(context).openalias_alert_title, + S.of(context).openalias_alert_content(domain)); + break; + case ParseFrom.notParsed: + break; + } + + return parsedAddress.address; + } } diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 3d7e011e..2aa4ebb8 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,6 +1,8 @@ import 'dart:ui'; +import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/entities/transaction_priority.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; +import 'package:cake_wallet/src/screens/send/widgets/parse_address_from_domain_alert.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; @@ -757,7 +759,24 @@ class SendPage extends BasePage { void applyOpenaliasOrUnstoppableDomains(BuildContext context) async { final domain = _addressController.text; final ticker = sendViewModel.currency.title.toLowerCase(); - _addressController.text = - await parseAddressFromDomain(context, domain, ticker); + final parsedAddress = await parseAddressFromDomain(domain, ticker); + _addressController.text = parsedAddress.address; + + switch (parsedAddress.parseFrom) { + case ParseFrom.unstoppableDomains: + showAddressAlert( + context, + S.of(context).address_detected, + S.of(context).address_from_domain(domain)); + break; + case ParseFrom.openAlias: + showAddressAlert( + context, + S.of(context).openalias_alert_title, + S.of(context).openalias_alert_content(domain)); + break; + case ParseFrom.notParsed: + break; + } } } From e03f0ce4d3cf3e072a4ed4ef4e72655421cf065a Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Thu, 8 Jul 2021 17:52:48 +0300 Subject: [PATCH 14/18] CAKE-343 | added wallet_addresses.dart, monero_wallet_addresses.dart, electrum_wallet_addresses.dart, wallet_addresses_credentials.dart, monero_wallet_addresses_credentials.dart and electrum_wallet_addresses_credentials.dart to the app; applied ElectrumWalletAddresses to electrum_wallet.dart and MoneroWalletAddresses to monero_wallet.dart; fixed contact_list_view_model.dart, other view models and services --- lib/bitcoin/bitcoin_wallet_service.dart | 1 - lib/bitcoin/electrum_wallet.dart | 16 +++++++- lib/bitcoin/electrum_wallet_addresses.dart | 32 ++++++++++++++++ ...electrum_wallet_addresses_credentials.dart | 7 ++++ lib/bitcoin/litecoin_wallet_service.dart | 1 - lib/core/wallet_base.dart | 10 ----- lib/entities/wallet_addresses.dart | 30 +++++++++++++++ .../wallet_addresses_credentials.dart | 1 + lib/monero/monero_wallet.dart | 37 +++++++++--------- lib/monero/monero_wallet_addresses.dart | 38 +++++++++++++++++++ .../monero_wallet_addresses_credentials.dart | 9 +++++ lib/monero/monero_wallet_service.dart | 1 - .../contact_list/contact_list_view_model.dart | 21 +++++----- ...ero_account_edit_or_create_view_model.dart | 3 +- ...let_address_edit_or_create_view_model.dart | 2 - lib/view_model/wallet_creation_vm.dart | 1 - 16 files changed, 159 insertions(+), 51 deletions(-) create mode 100644 lib/bitcoin/electrum_wallet_addresses.dart create mode 100644 lib/bitcoin/electrum_wallet_addresses_credentials.dart create mode 100644 lib/entities/wallet_addresses.dart create mode 100644 lib/entities/wallet_addresses_credentials.dart create mode 100644 lib/monero/monero_wallet_addresses.dart create mode 100644 lib/monero/monero_wallet_addresses_credentials.dart diff --git a/lib/bitcoin/bitcoin_wallet_service.dart b/lib/bitcoin/bitcoin_wallet_service.dart index 2cd3310f..aefe0fad 100644 --- a/lib/bitcoin/bitcoin_wallet_service.dart +++ b/lib/bitcoin/bitcoin_wallet_service.dart @@ -44,7 +44,6 @@ class BitcoinWalletService extends WalletService< final wallet = await BitcoinWalletBase.open( password: password, name: name, walletInfo: walletInfo); await wallet.init(); - await wallet.updateAddressesInfo(); return wallet; } diff --git a/lib/bitcoin/electrum_wallet.dart b/lib/bitcoin/electrum_wallet.dart index bb0ee3c3..d0b1c9a6 100644 --- a/lib/bitcoin/electrum_wallet.dart +++ b/lib/bitcoin/electrum_wallet.dart @@ -1,5 +1,7 @@ import 'dart:async'; import 'dart:convert'; +import 'package:cake_wallet/bitcoin/electrum_wallet_addresses.dart'; +import 'package:cake_wallet/bitcoin/electrum_wallet_addresses_credentials.dart'; import 'package:mobx/mobx.dart'; import 'package:rxdart/subjects.dart'; import 'package:flutter/foundation.dart'; @@ -63,6 +65,8 @@ abstract class ElectrumWalletBase extends WalletBase @@ -93,6 +97,9 @@ abstract class ElectrumWalletBase extends WalletBase hd.base58; + ElectrumWalletAddresses _walletAddressInBox; + ElectrumWalletAddressesCredentials _walletAddressInBoxCredentials; + @override String get seed => mnemonic; @@ -113,6 +120,7 @@ abstract class ElectrumWalletBase extends WalletBase @@ -466,4 +473,9 @@ abstract class ElectrumWalletBase extends WalletBase _updateWalletAddressInBox() async { + _walletAddressInBoxCredentials.address = address; + await _walletAddressInBox.update(_walletAddressInBoxCredentials); + } } diff --git a/lib/bitcoin/electrum_wallet_addresses.dart b/lib/bitcoin/electrum_wallet_addresses.dart new file mode 100644 index 00000000..ac4895ae --- /dev/null +++ b/lib/bitcoin/electrum_wallet_addresses.dart @@ -0,0 +1,32 @@ +import 'package:cake_wallet/bitcoin/electrum_wallet_addresses_credentials.dart'; +import 'package:cake_wallet/entities/wallet_addresses.dart'; +import 'package:cake_wallet/entities/wallet_addresses_credentials.dart'; +import 'package:cake_wallet/entities/wallet_info.dart'; + +class ElectrumWalletAddresses extends WalletAddresses { + ElectrumWalletAddresses(WalletInfo walletInfo) : super(walletInfo); + + @override + Future update(WalletAddressesCredentials credentials) async { + try { + if (credentials == null) { + return; + } + + final _credentials = credentials as ElectrumWalletAddressesCredentials; + final _address = _credentials.address; + final _label = ''; + + if (_address == null || _address.isEmpty) { + return; + } + + addresses.clear(); + addresses[_address] = _label; + + await save(); + } catch (e) { + print(e.toString()); + } + } +} \ No newline at end of file diff --git a/lib/bitcoin/electrum_wallet_addresses_credentials.dart b/lib/bitcoin/electrum_wallet_addresses_credentials.dart new file mode 100644 index 00000000..30a41f8f --- /dev/null +++ b/lib/bitcoin/electrum_wallet_addresses_credentials.dart @@ -0,0 +1,7 @@ +import 'package:cake_wallet/entities/wallet_addresses_credentials.dart'; + +class ElectrumWalletAddressesCredentials extends WalletAddressesCredentials { + ElectrumWalletAddressesCredentials(); + + String address; +} \ No newline at end of file diff --git a/lib/bitcoin/litecoin_wallet_service.dart b/lib/bitcoin/litecoin_wallet_service.dart index 071baf4a..053fd785 100644 --- a/lib/bitcoin/litecoin_wallet_service.dart +++ b/lib/bitcoin/litecoin_wallet_service.dart @@ -45,7 +45,6 @@ class LitecoinWalletService extends WalletService< final wallet = await LitecoinWalletBase.open( password: password, name: name, walletInfo: walletInfo); await wallet.init(); - await wallet.updateAddressesInfo(); return wallet; } diff --git a/lib/core/wallet_base.dart b/lib/core/wallet_base.dart index 9e7b89e8..f6ed6414 100644 --- a/lib/core/wallet_base.dart +++ b/lib/core/wallet_base.dart @@ -6,7 +6,6 @@ import 'package:cake_wallet/entities/wallet_info.dart'; import 'package:cake_wallet/core/pending_transaction.dart'; import 'package:cake_wallet/core/transaction_history.dart'; import 'package:cake_wallet/entities/currency_for_wallet_type.dart'; -import 'package:cake_wallet/entities/monero_transaction_priority.dart'; import 'package:cake_wallet/entities/crypto_currency.dart'; import 'package:cake_wallet/entities/sync_status.dart'; import 'package:cake_wallet/entities/node.dart'; @@ -66,13 +65,4 @@ abstract class WalletBase< Future rescan({int height}); void close(); - - Future updateAddressesInfo() async { - try { - walletInfo.address = address; - await walletInfo.save(); - } catch (e) { - print(e.toString()); - } - } } diff --git a/lib/entities/wallet_addresses.dart b/lib/entities/wallet_addresses.dart new file mode 100644 index 00000000..81b4fdea --- /dev/null +++ b/lib/entities/wallet_addresses.dart @@ -0,0 +1,30 @@ +import 'package:cake_wallet/entities/wallet_addresses_credentials.dart'; +import 'package:cake_wallet/entities/wallet_info.dart'; + +abstract class WalletAddresses { + WalletAddresses(this.walletInfo) { + addresses = walletInfo?.addresses ?? {}; + } + + final WalletInfo walletInfo; + + Map addresses; + + Future update(WalletAddressesCredentials credentials); + + Future save() async { + try { + if (walletInfo == null) { + return; + } + + walletInfo.addresses = addresses; + + if (walletInfo.isInBox) { + await walletInfo.save(); + } + } catch (e) { + print(e.toString()); + } + } +} \ No newline at end of file diff --git a/lib/entities/wallet_addresses_credentials.dart b/lib/entities/wallet_addresses_credentials.dart new file mode 100644 index 00000000..fe3d2c92 --- /dev/null +++ b/lib/entities/wallet_addresses_credentials.dart @@ -0,0 +1 @@ +abstract class WalletAddressesCredentials {} \ No newline at end of file diff --git a/lib/monero/monero_wallet.dart b/lib/monero/monero_wallet.dart index c9ea9e03..77cd2f53 100644 --- a/lib/monero/monero_wallet.dart +++ b/lib/monero/monero_wallet.dart @@ -3,6 +3,8 @@ import 'package:cake_wallet/entities/transaction_priority.dart'; import 'package:cake_wallet/monero/monero_amount_format.dart'; import 'package:cake_wallet/monero/monero_transaction_creation_exception.dart'; import 'package:cake_wallet/monero/monero_transaction_info.dart'; +import 'package:cake_wallet/monero/monero_wallet_addresses.dart'; +import 'package:cake_wallet/monero/monero_wallet_addresses_credentials.dart'; import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_monero/transaction_history.dart' @@ -47,6 +49,8 @@ abstract class MoneroWalletBase extends WalletBase account, (Account account) { balance = MoneroBalance( fullBalance: monero_wallet.getFullBalance(accountIndex: account.id), @@ -99,6 +103,8 @@ abstract class MoneroWalletBase extends WalletBase init() async { accountList.update(); @@ -110,6 +116,7 @@ abstract class MoneroWalletBase extends WalletBase save() async { + await _updateWalletAllAddressesInBox(); + final now = DateTime.now().millisecondsSinceEpoch; if (now - _lastSaveTimestamp < Duration(seconds: 10).inMilliseconds) { @@ -446,25 +455,13 @@ abstract class MoneroWalletBase extends WalletBase updateAddressesInfo() async { - final Map _addresses = {}; - final _subaddressList = MoneroSubaddressList(); - - accountList.accounts.forEach((account) { - _subaddressList.update(accountIndex: account.id); - _subaddressList.subaddresses.forEach((subaddress) { - _addresses[subaddress.address] = subaddress.label; - }); - }); - - try { - walletInfo.addresses = _addresses; - walletInfo.address = address; - - await walletInfo.save(); - } catch (e) { - print(e.toString()); - } + Future _updateWalletAllAddressesInBox() async { + _walletAddressesCredentials + ..accountList = accountList + ..subaddressList = subaddressList; + await _walletAllAddresses.update(_walletAddressesCredentials); + subaddressList.update(accountIndex: account.id ?? 0); + subaddress = subaddressList.subaddresses.first; + address = subaddress.address; } } diff --git a/lib/monero/monero_wallet_addresses.dart b/lib/monero/monero_wallet_addresses.dart new file mode 100644 index 00000000..55680e1c --- /dev/null +++ b/lib/monero/monero_wallet_addresses.dart @@ -0,0 +1,38 @@ +import 'package:cake_wallet/entities/wallet_addresses.dart'; +import 'package:cake_wallet/entities/wallet_addresses_credentials.dart'; +import 'package:cake_wallet/entities/wallet_info.dart'; +import 'monero_wallet_addresses_credentials.dart'; + +class MoneroWalletAddresses extends WalletAddresses { + MoneroWalletAddresses(WalletInfo walletInfo) : super(walletInfo); + + @override + Future update(WalletAddressesCredentials credentials) async { + try { + if (credentials == null) { + return; + } + + final _credentials = credentials as MoneroWalletAddressesCredentials; + final _accountList = _credentials.accountList; + final _subaddressList = _credentials.subaddressList; + + if (_accountList == null || _subaddressList == null) { + return; + } + + addresses.clear(); + + _accountList.accounts.forEach((account) { + _subaddressList.update(accountIndex: account.id); + _subaddressList.subaddresses.forEach((subaddress) { + addresses[subaddress.address] = subaddress.label; + }); + }); + + await save(); + } catch (e) { + print(e.toString()); + } + } +} \ No newline at end of file diff --git a/lib/monero/monero_wallet_addresses_credentials.dart b/lib/monero/monero_wallet_addresses_credentials.dart new file mode 100644 index 00000000..0808cb12 --- /dev/null +++ b/lib/monero/monero_wallet_addresses_credentials.dart @@ -0,0 +1,9 @@ +import 'package:cake_wallet/entities/wallet_addresses_credentials.dart'; +import 'package:cake_wallet/monero/monero_account_list.dart'; +import 'package:cake_wallet/monero/monero_subaddress_list.dart'; + +class MoneroWalletAddressesCredentials extends WalletAddressesCredentials { + + MoneroAccountList accountList; + MoneroSubaddressList subaddressList; +} \ No newline at end of file diff --git a/lib/monero/monero_wallet_service.dart b/lib/monero/monero_wallet_service.dart index 17b02dcb..7795b870 100644 --- a/lib/monero/monero_wallet_service.dart +++ b/lib/monero/monero_wallet_service.dart @@ -126,7 +126,6 @@ class MoneroWalletService extends WalletService< } await wallet.init(); - await wallet.updateAddressesInfo(); return wallet; } catch (e) { 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 b5143cff..1a8bbc02 100644 --- a/lib/view_model/contact_list/contact_list_view_model.dart +++ b/lib/view_model/contact_list/contact_list_view_model.dart @@ -18,18 +18,17 @@ abstract class ContactListViewModelBase with Store { : contacts = ObservableList(), walletContacts = [] { walletInfoSource.values.forEach((info) { - if (info.address?.isNotEmpty ?? false) { - if (info.addresses != null) { - info.addresses?.forEach((address, label) { - walletContacts.add(WalletContact( - address, - info.name + ' ($label)', - walletTypeToCryptoCurrency(info.type))); - }); - } else { - walletContacts.add(WalletContact(info.address, info.name, + 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))); - } + }); } }); diff --git a/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart b/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart index cf999e41..a86fa277 100644 --- a/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart +++ b/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart @@ -42,8 +42,7 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store { await _moneroAccountList.addAccount(label: label); } - await _wallet.updateAddressesInfo(); - + await _wallet.save(); state = ExecutedSuccessfullyState(); } catch (e) { state = FailureState(e.toString()); diff --git a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart index 6b6873cd..b018c542 100644 --- a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart @@ -54,8 +54,6 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { await _createNew(); } - await _wallet.updateAddressesInfo(); - state = AddressSavedSuccessfully(); } catch (e) { state = AddressEditOrCreateStateFailure(error: e.toString()); diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 54cad29c..58ee2408 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -54,7 +54,6 @@ abstract class WalletCreationVMBase with Store { await _walletInfoSource.add(walletInfo); _appStore.changeCurrentWallet(wallet); _appStore.authenticationStore.allowed(); - await wallet.updateAddressesInfo(); state = ExecutedSuccessfullyState(); } catch (e) { state = FailureState(e.toString()); From 0d367c4b455c2ea9972649aad731f725754471dc Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Tue, 13 Jul 2021 08:46:34 +0300 Subject: [PATCH 15/18] CAKE-343 | added bitcoin_wallet_addresses.dart and litecoin_wallet_addresses.dart tj the app; moved addresses from wallets to wallet addresses classes; deleted wallet addresses credentials --- lib/bitcoin/bitcoin_wallet.dart | 16 +-- lib/bitcoin/bitcoin_wallet_addresses.dart | 33 +++++ lib/bitcoin/electrum_wallet.dart | 100 ++-------------- lib/bitcoin/electrum_wallet_addresses.dart | 113 +++++++++++++++--- ...electrum_wallet_addresses_credentials.dart | 7 -- lib/bitcoin/litecoin_wallet.dart | 36 ++---- lib/bitcoin/litecoin_wallet_addresses.dart | 54 +++++++++ lib/buy/buy_provider.dart | 2 +- lib/core/wallet_base.dart | 7 +- lib/di.dart | 2 +- lib/entities/wallet_addresses.dart | 18 ++- .../wallet_addresses_credentials.dart | 1 - lib/monero/monero_wallet.dart | 90 +++----------- lib/monero/monero_wallet_addresses.dart | 85 ++++++++++--- .../monero_wallet_addresses_credentials.dart | 9 -- lib/monero/monero_wallet_service.dart | 2 +- lib/reactions/on_current_wallet_change.dart | 2 +- lib/src/screens/exchange/exchange_page.dart | 14 ++- .../exchange/exchange_template_page.dart | 14 ++- .../dashboard/dashboard_view_model.dart | 24 ++-- .../exchange/exchange_view_model.dart | 9 +- .../monero_account_list_view_model.dart | 9 +- ...let_address_edit_or_create_view_model.dart | 20 ++-- .../wallet_address_list_view_model.dart | 19 +-- lib/view_model/wallet_creation_vm.dart | 2 +- 25 files changed, 380 insertions(+), 308 deletions(-) create mode 100644 lib/bitcoin/bitcoin_wallet_addresses.dart delete mode 100644 lib/bitcoin/electrum_wallet_addresses_credentials.dart create mode 100644 lib/bitcoin/litecoin_wallet_addresses.dart delete mode 100644 lib/entities/wallet_addresses_credentials.dart delete mode 100644 lib/monero/monero_wallet_addresses_credentials.dart diff --git a/lib/bitcoin/bitcoin_wallet.dart b/lib/bitcoin/bitcoin_wallet.dart index fd840288..02af295f 100644 --- a/lib/bitcoin/bitcoin_wallet.dart +++ b/lib/bitcoin/bitcoin_wallet.dart @@ -1,12 +1,12 @@ import 'package:mobx/mobx.dart'; import 'package:flutter/foundation.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cake_wallet/bitcoin/utils.dart'; import 'package:cake_wallet/bitcoin/electrum_wallet_snapshot.dart'; import 'package:cake_wallet/bitcoin/electrum_wallet.dart'; import 'package:cake_wallet/entities/wallet_info.dart'; import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart'; import 'package:cake_wallet/bitcoin/electrum_balance.dart'; +import 'package:cake_wallet/bitcoin/bitcoin_wallet_addresses.dart'; part 'bitcoin_wallet.g.dart'; @@ -26,8 +26,14 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { walletInfo: walletInfo, networkType: bitcoin.bitcoin, initialAddresses: initialAddresses, - initialBalance: initialBalance, - accountIndex: accountIndex); + initialBalance: initialBalance) { + walletAddresses = BitcoinWalletAddresses( + walletInfo, + initialAddresses: initialAddresses, + accountIndex: accountIndex, + hd: hd, + networkType: networkType); + } static Future open({ @required String name, @@ -44,8 +50,4 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialBalance: snp.balance, accountIndex: snp.accountIndex); } - - @override - String getAddress({@required int index, @required bitcoin.HDWallet hd}) => - generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); } diff --git a/lib/bitcoin/bitcoin_wallet_addresses.dart b/lib/bitcoin/bitcoin_wallet_addresses.dart new file mode 100644 index 00000000..ecded3cb --- /dev/null +++ b/lib/bitcoin/bitcoin_wallet_addresses.dart @@ -0,0 +1,33 @@ +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:cake_wallet/bitcoin/utils.dart'; +import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart'; +import 'package:cake_wallet/bitcoin/electrum_wallet_addresses.dart'; +import 'package:cake_wallet/entities/wallet_info.dart'; +import 'package:flutter/foundation.dart'; +import 'package:mobx/mobx.dart'; + +part 'bitcoin_wallet_addresses.g.dart'; + +class BitcoinWalletAddresses = BitcoinWalletAddressesBase + with _$BitcoinWalletAddresses; + +abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses + with Store { + BitcoinWalletAddressesBase( + WalletInfo walletInfo, + {@required List initialAddresses, + int accountIndex = 0, + @required bitcoin.HDWallet hd, + @required this.networkType}) + : super( + walletInfo, + initialAddresses: initialAddresses, + accountIndex: accountIndex, + hd: hd); + + bitcoin.NetworkType networkType; + + @override + String getAddress({@required int index, @required bitcoin.HDWallet hd}) => + generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); +} \ No newline at end of file diff --git a/lib/bitcoin/electrum_wallet.dart b/lib/bitcoin/electrum_wallet.dart index d0b1c9a6..38fc192d 100644 --- a/lib/bitcoin/electrum_wallet.dart +++ b/lib/bitcoin/electrum_wallet.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:convert'; import 'package:cake_wallet/bitcoin/electrum_wallet_addresses.dart'; -import 'package:cake_wallet/bitcoin/electrum_wallet_addresses_credentials.dart'; import 'package:mobx/mobx.dart'; import 'package:rxdart/subjects.dart'; import 'package:flutter/foundation.dart'; @@ -44,18 +43,14 @@ abstract class ElectrumWalletBase extends WalletBase.of( - (initialAddresses ?? []).toSet()), syncStatus = NotConnectedSyncStatus(), _password = password, - _accountIndex = accountIndex, _feeRates = [], _isTransactionUpdating = false, super(walletInfo) { @@ -65,8 +60,6 @@ abstract class ElectrumWalletBase extends WalletBase @@ -78,8 +71,7 @@ abstract class ElectrumWalletBase extends WalletBase addresses; - - List get scriptHashes => addresses + List get scriptHashes => walletAddresses.addresses .map((addr) => scriptHash(addr.address, networkType: networkType)) .toList(); String get xpub => hd.base58; - ElectrumWalletAddresses _walletAddressInBox; - ElectrumWalletAddressesCredentials _walletAddressInBoxCredentials; - @override String get seed => mnemonic; @@ -112,73 +99,13 @@ abstract class ElectrumWalletBase extends WalletBase _unspent; List _feeRates; - int _accountIndex; Map> _scripthashesUpdateSubject; bool _isTransactionUpdating; Future init() async { - await generateAddresses(); - address = addresses[_accountIndex].address; + await walletAddresses.init(); await transactionHistory.init(); - await _updateWalletAddressInBox(); - } - - @action - Future nextAddress() async { - _accountIndex += 1; - - if (_accountIndex >= addresses.length) { - _accountIndex = 0; - } - - address = addresses[_accountIndex].address; - - await save(); - } - - Future generateAddresses() async { - if (addresses.length < 33) { - final addressesCount = 33 - addresses.length; - await generateNewAddresses(addressesCount, - startIndex: addresses.length, hd: hd); - } - } - - Future generateNewAddress( - {bool isHidden = false, bitcoin.HDWallet hd}) async { - _accountIndex += 1; - final _hd = hd ?? this.hd; - final address = BitcoinAddressRecord( - getAddress(index: _accountIndex, hd: _hd), - index: _accountIndex, - isHidden: isHidden); - addresses.add(address); - await save(); - return address; - } - - Future> generateNewAddresses(int count, - {int startIndex = 0, bitcoin.HDWallet hd, bool isHidden = false}) async { - final list = []; - - for (var i = startIndex; i < count + startIndex; i++) { - final address = BitcoinAddressRecord(getAddress(index: i, hd: hd), - index: i, isHidden: isHidden); - list.add(address); - } - - addresses.addAll(list); await save(); - return list; - } - - Future updateAddress(String address) async { - for (final addr in addresses) { - if (addr.address == address) { - await save(); - break; - } - } } @action @@ -186,7 +113,7 @@ abstract class ElectrumWalletBase extends WalletBase startSync() async { try { syncStatus = StartingSyncStatus(); - updateTransactions(); + await updateTransactions(); _subscribeForUpdates(); await _updateBalance(); await _updateUnspent(); @@ -238,7 +165,7 @@ abstract class ElectrumWalletBase extends WalletBase json.encode({ 'mnemonic': mnemonic, - 'account_index': _accountIndex.toString(), - 'addresses': addresses.map((addr) => addr.toJSON()).toList(), + 'account_index': walletAddresses.accountIndex.toString(), + 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), 'balance': balance?.toJSON() }); @@ -370,7 +297,6 @@ abstract class ElectrumWalletBase extends WalletBase @@ -386,13 +312,12 @@ abstract class ElectrumWalletBase extends WalletBase ''; - Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); Future _updateUnspent() async { - final unspent = await Future.wait(addresses.map((address) => electrumClient + final unspent = await Future.wait(walletAddresses + .addresses.map((address) => electrumClient .getListUnspentWithAddress(address.address, networkType) .then((unspent) => unspent .map((unspent) => BitcoinUnspent.fromJSON(address, unspent))))); @@ -403,7 +328,7 @@ abstract class ElectrumWalletBase extends WalletBase _updateWalletAddressInBox() async { - _walletAddressInBoxCredentials.address = address; - await _walletAddressInBox.update(_walletAddressInBoxCredentials); - } } diff --git a/lib/bitcoin/electrum_wallet_addresses.dart b/lib/bitcoin/electrum_wallet_addresses.dart index ac4895ae..843ac406 100644 --- a/lib/bitcoin/electrum_wallet_addresses.dart +++ b/lib/bitcoin/electrum_wallet_addresses.dart @@ -1,30 +1,109 @@ -import 'package:cake_wallet/bitcoin/electrum_wallet_addresses_credentials.dart'; +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart'; import 'package:cake_wallet/entities/wallet_addresses.dart'; -import 'package:cake_wallet/entities/wallet_addresses_credentials.dart'; import 'package:cake_wallet/entities/wallet_info.dart'; +import 'package:flutter/foundation.dart'; +import 'package:mobx/mobx.dart'; -class ElectrumWalletAddresses extends WalletAddresses { - ElectrumWalletAddresses(WalletInfo walletInfo) : super(walletInfo); +part 'electrum_wallet_addresses.g.dart'; + +class ElectrumWalletAddresses = ElectrumWalletAddressesBase + with _$ElectrumWalletAddresses; + +abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { + ElectrumWalletAddressesBase(WalletInfo walletInfo, + {@required List initialAddresses, + int accountIndex = 0, + @required bitcoin.HDWallet hd}) + : super(walletInfo) { + this.hd = hd; + this.accountIndex = accountIndex; + addresses = ObservableList.of( + (initialAddresses ?? []).toSet()); + } @override - Future update(WalletAddressesCredentials credentials) async { - try { - if (credentials == null) { - return; - } + @observable + String address; + + bitcoin.HDWallet hd; + + ObservableList addresses; + + int accountIndex; + + @override + Future init() async { + await generateAddresses(); + address = addresses[accountIndex].address; + await updateAddressesInBox(); + } + + @action + Future nextAddress() async { + accountIndex += 1; + + if (accountIndex >= addresses.length) { + accountIndex = 0; + } + + address = addresses[accountIndex].address; - final _credentials = credentials as ElectrumWalletAddressesCredentials; - final _address = _credentials.address; - final _label = ''; + await updateAddressesInBox(); + } + + Future generateAddresses() async { + if (addresses.length < 33) { + final addressesCount = 33 - addresses.length; + await generateNewAddresses(addressesCount, + startIndex: addresses.length, hd: hd); + } + } - if (_address == null || _address.isEmpty) { - return; + Future generateNewAddress( + {bool isHidden = false, bitcoin.HDWallet hd}) async { + accountIndex += 1; + final _hd = hd ?? this.hd; + final address = BitcoinAddressRecord( + getAddress(index: accountIndex, hd: _hd), + index: accountIndex, + isHidden: isHidden); + addresses.add(address); + return address; + } + + Future> generateNewAddresses(int count, + {int startIndex = 0, bitcoin.HDWallet hd, bool isHidden = false}) async { + final list = []; + + for (var i = startIndex; i < count + startIndex; i++) { + final address = BitcoinAddressRecord(getAddress(index: i, hd: hd), + index: i, isHidden: isHidden); + list.add(address); + } + + addresses.addAll(list); + return list; + } + + /*Future updateAddress(String address) async { + for (final addr in addresses) { + if (addr.address == address) { + await save(); + break; } + } + }*/ - addresses.clear(); - addresses[_address] = _label; + String getAddress({@required int index, @required bitcoin.HDWallet hd}) => ''; + + @override + Future updateAddressesInBox() async { + try { + addressesMap.clear(); + addressesMap[address] = ''; - await save(); + await saveAddressesInBox(); } catch (e) { print(e.toString()); } diff --git a/lib/bitcoin/electrum_wallet_addresses_credentials.dart b/lib/bitcoin/electrum_wallet_addresses_credentials.dart deleted file mode 100644 index 30a41f8f..00000000 --- a/lib/bitcoin/electrum_wallet_addresses_credentials.dart +++ /dev/null @@ -1,7 +0,0 @@ -import 'package:cake_wallet/entities/wallet_addresses_credentials.dart'; - -class ElectrumWalletAddressesCredentials extends WalletAddressesCredentials { - ElectrumWalletAddressesCredentials(); - - String address; -} \ No newline at end of file diff --git a/lib/bitcoin/litecoin_wallet.dart b/lib/bitcoin/litecoin_wallet.dart index 209d1904..bfb7da6d 100644 --- a/lib/bitcoin/litecoin_wallet.dart +++ b/lib/bitcoin/litecoin_wallet.dart @@ -1,6 +1,5 @@ -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cake_wallet/bitcoin/bitcoin_mnemonic.dart'; import 'package:cake_wallet/bitcoin/bitcoin_transaction_priority.dart'; +import 'package:cake_wallet/bitcoin/litecoin_wallet_addresses.dart'; import 'package:cake_wallet/entities/transaction_priority.dart'; import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; @@ -10,7 +9,6 @@ import 'package:cake_wallet/bitcoin/electrum_wallet.dart'; import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart'; import 'package:cake_wallet/bitcoin/electrum_balance.dart'; import 'package:cake_wallet/bitcoin/litecoin_network.dart'; -import 'package:cake_wallet/bitcoin/utils.dart'; part 'litecoin_wallet.g.dart'; @@ -30,8 +28,15 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { walletInfo: walletInfo, networkType: litecoinNetwork, initialAddresses: initialAddresses, - initialBalance: initialBalance, - accountIndex: accountIndex); + initialBalance: initialBalance) { + walletAddresses = LitecoinWalletAddresses( + walletInfo, + initialAddresses: initialAddresses, + accountIndex: accountIndex, + hd: hd, + networkType: networkType, + mnemonic: mnemonic); + } static Future open({ @required String name, @@ -49,27 +54,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { accountIndex: snp.accountIndex); } - @override - String getAddress({@required int index, @required bitcoin.HDWallet hd}) => - generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); - - @override - Future generateAddresses() async { - if (addresses.length < 33) { - final addressesCount = 22 - addresses.length; - await generateNewAddresses(addressesCount, - hd: hd, startIndex: addresses.length); - - final changeRoot = bitcoin.HDWallet.fromSeed( - mnemonicToSeedBytes(mnemonic), - network: networkType) - .derivePath("m/0'/1"); - - await generateNewAddresses(11, - startIndex: 0, hd: changeRoot, isHidden: true); - } - } - @override int feeRate(TransactionPriority priority) { if (priority is LitecoinTransactionPriority) { diff --git a/lib/bitcoin/litecoin_wallet_addresses.dart b/lib/bitcoin/litecoin_wallet_addresses.dart new file mode 100644 index 00000000..19ade756 --- /dev/null +++ b/lib/bitcoin/litecoin_wallet_addresses.dart @@ -0,0 +1,54 @@ +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:cake_wallet/bitcoin/bitcoin_mnemonic.dart'; +import 'package:cake_wallet/bitcoin/utils.dart'; +import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart'; +import 'package:cake_wallet/bitcoin/electrum_wallet_addresses.dart'; +import 'package:cake_wallet/entities/wallet_info.dart'; +import 'package:flutter/foundation.dart'; +import 'package:mobx/mobx.dart'; + +part 'litecoin_wallet_addresses.g.dart'; + +class LitecoinWalletAddresses = LitecoinWalletAddressesBase + with _$LitecoinWalletAddresses; + +abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses + with Store { + LitecoinWalletAddressesBase( + WalletInfo walletInfo, + {@required List initialAddresses, + int accountIndex = 0, + @required bitcoin.HDWallet hd, + @required this.networkType, + @required this.mnemonic}) + : super( + walletInfo, + initialAddresses: initialAddresses, + accountIndex: accountIndex, + hd: hd); + + bitcoin.NetworkType networkType; + + final String mnemonic; + + @override + String getAddress({@required int index, @required bitcoin.HDWallet hd}) => + generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); + + @override + Future generateAddresses() async { + if (addresses.length < 33) { + final addressesCount = 22 - addresses.length; + await generateNewAddresses(addressesCount, + hd: hd, startIndex: addresses.length); + + final changeRoot = bitcoin.HDWallet.fromSeed( + mnemonicToSeedBytes(mnemonic), + network: networkType) + .derivePath("m/0'/1"); + + await generateNewAddresses(11, + startIndex: 0, hd: changeRoot, isHidden: true); + } + } +} \ No newline at end of file diff --git a/lib/buy/buy_provider.dart b/lib/buy/buy_provider.dart index b908d7bc..dc450ad7 100644 --- a/lib/buy/buy_provider.dart +++ b/lib/buy/buy_provider.dart @@ -15,7 +15,7 @@ abstract class BuyProvider { String get trackUrl; WalletType get walletType => wallet.type; - String get walletAddress => wallet.address; + String get walletAddress => wallet.walletAddresses.address; String get walletId => wallet.id; @override diff --git a/lib/core/wallet_base.dart b/lib/core/wallet_base.dart index f6ed6414..edcb0546 100644 --- a/lib/core/wallet_base.dart +++ b/lib/core/wallet_base.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/entities/balance.dart'; import 'package:cake_wallet/entities/transaction_info.dart'; import 'package:cake_wallet/entities/transaction_priority.dart'; +import 'package:cake_wallet/entities/wallet_addresses.dart'; import 'package:flutter/foundation.dart'; import 'package:cake_wallet/entities/wallet_info.dart'; import 'package:cake_wallet/core/pending_transaction.dart'; @@ -30,9 +31,9 @@ abstract class WalletBase< String get name => walletInfo.name; - String get address; + //String get address; - set address(String address); + //set address(String address); BalanceType get balance; @@ -44,6 +45,8 @@ abstract class WalletBase< Object get keys; + WalletAddresses get walletAddresses; + HistoryType transactionHistory; Future connectToNode({@required Node node}); diff --git a/lib/di.dart b/lib/di.dart index 1f535037..3b709d70 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -361,7 +361,7 @@ Future setup( getIt.registerFactoryParam( (AccountListItem account, _) => MoneroAccountEditOrCreateViewModel( - (getIt.get().wallet as MoneroWallet).accountList, + (getIt.get().wallet as MoneroWallet).walletAddresses.accountList, wallet: getIt.get().wallet, accountListItem: account)); diff --git a/lib/entities/wallet_addresses.dart b/lib/entities/wallet_addresses.dart index 81b4fdea..cd533191 100644 --- a/lib/entities/wallet_addresses.dart +++ b/lib/entities/wallet_addresses.dart @@ -1,24 +1,30 @@ -import 'package:cake_wallet/entities/wallet_addresses_credentials.dart'; import 'package:cake_wallet/entities/wallet_info.dart'; abstract class WalletAddresses { WalletAddresses(this.walletInfo) { - addresses = walletInfo?.addresses ?? {}; + addressesMap = {}; } final WalletInfo walletInfo; - Map addresses; + String get address; - Future update(WalletAddressesCredentials credentials); + set address(String address); - Future save() async { + Map addressesMap; + + Future init(); + + Future updateAddressesInBox(); + + Future saveAddressesInBox() async { try { if (walletInfo == null) { return; } - walletInfo.addresses = addresses; + walletInfo.address = address; + walletInfo.addresses = addressesMap; if (walletInfo.isInBox) { await walletInfo.save(); diff --git a/lib/entities/wallet_addresses_credentials.dart b/lib/entities/wallet_addresses_credentials.dart deleted file mode 100644 index fe3d2c92..00000000 --- a/lib/entities/wallet_addresses_credentials.dart +++ /dev/null @@ -1 +0,0 @@ -abstract class WalletAddressesCredentials {} \ No newline at end of file diff --git a/lib/monero/monero_wallet.dart b/lib/monero/monero_wallet.dart index 77cd2f53..411982a8 100644 --- a/lib/monero/monero_wallet.dart +++ b/lib/monero/monero_wallet.dart @@ -4,7 +4,6 @@ import 'package:cake_wallet/monero/monero_amount_format.dart'; import 'package:cake_wallet/monero/monero_transaction_creation_exception.dart'; import 'package:cake_wallet/monero/monero_transaction_info.dart'; import 'package:cake_wallet/monero/monero_wallet_addresses.dart'; -import 'package:cake_wallet/monero/monero_wallet_addresses_credentials.dart'; import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_monero/transaction_history.dart' @@ -17,10 +16,7 @@ import 'package:cake_wallet/monero/pending_monero_transaction.dart'; import 'package:cake_wallet/monero/monero_wallet_keys.dart'; import 'package:cake_wallet/monero/monero_balance.dart'; import 'package:cake_wallet/monero/monero_transaction_history.dart'; -import 'package:cake_wallet/monero/monero_subaddress_list.dart'; -import 'package:cake_wallet/monero/monero_account_list.dart'; import 'package:cake_wallet/monero/account.dart'; -import 'package:cake_wallet/monero/subaddress.dart'; import 'package:cake_wallet/core/pending_transaction.dart'; import 'package:cake_wallet/core/wallet_base.dart'; import 'package:cake_wallet/entities/sync_status.dart'; @@ -37,9 +33,7 @@ class MoneroWallet = MoneroWalletBase with _$MoneroWallet; abstract class MoneroWalletBase extends WalletBase with Store { MoneroWalletBase({WalletInfo walletInfo}) - : accountList = MoneroAccountList(), - subaddressList = MoneroSubaddressList(), - super(walletInfo) { + : super(walletInfo) { transactionHistory = MoneroTransactionHistory(); balance = MoneroBalance( fullBalance: monero_wallet.getFullBalance(accountIndex: 0), @@ -49,34 +43,25 @@ abstract class MoneroWalletBase extends WalletBase account, (Account account) { + walletAddresses = MoneroWalletAddresses(walletInfo); + _onAccountChangeReaction = reaction((_) => walletAddresses.account, + (Account account) { balance = MoneroBalance( fullBalance: monero_wallet.getFullBalance(accountIndex: account.id), unlockedBalance: monero_wallet.getUnlockedBalance(accountIndex: account.id)); - subaddressList.update(accountIndex: account.id); - subaddress = subaddressList.subaddresses.first; - address = subaddress.address; + walletAddresses.updateSubaddressList(accountIndex: account.id); }); } static const int _autoAfterSyncSaveInterval = 60000; - @observable - Account account; - - @observable - Subaddress subaddress; - @override - @observable - SyncStatus syncStatus; + MoneroWalletAddresses walletAddresses; @override @observable - String address; + SyncStatus syncStatus; @override @observable @@ -92,10 +77,6 @@ abstract class MoneroWalletBase extends WalletBase init() async { - accountList.update(); - account = accountList.accounts.first; - subaddressList.update(accountIndex: account.id ?? 0); - subaddress = subaddressList.getAll().first; + await walletAddresses.init(); balance = MoneroBalance( - fullBalance: monero_wallet.getFullBalance(accountIndex: account.id), + fullBalance: monero_wallet.getFullBalance(accountIndex: walletAddresses.account.id), unlockedBalance: - monero_wallet.getUnlockedBalance(accountIndex: account.id)); - address = subaddress.address; - await _updateWalletAllAddressesInBox(); + monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account.id)); _setListeners(); await updateTransactions(); @@ -136,24 +110,6 @@ abstract class MoneroWalletBase extends WalletBase connectToNode({@required Node node}) async { try { @@ -196,7 +152,7 @@ abstract class MoneroWalletBase extends WalletBase save() async { - await _updateWalletAllAddressesInBox(); + await walletAddresses.updateAddressesInBox(); final now = DateTime.now().millisecondsSinceEpoch; @@ -274,7 +230,7 @@ abstract class MoneroWalletBase extends WalletBase - monero_wallet.getFullBalance(accountIndex: account.id); + monero_wallet.getFullBalance(accountIndex: walletAddresses.account.id); int _getUnlockedBalance() => - monero_wallet.getUnlockedBalance(accountIndex: account.id); + monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account.id); Future _afterSyncSave() async { try { @@ -423,13 +379,13 @@ abstract class MoneroWalletBase extends WalletBase _updateWalletAllAddressesInBox() async { - _walletAddressesCredentials - ..accountList = accountList - ..subaddressList = subaddressList; - await _walletAllAddresses.update(_walletAddressesCredentials); - subaddressList.update(accountIndex: account.id ?? 0); - subaddress = subaddressList.subaddresses.first; - address = subaddress.address; - } } diff --git a/lib/monero/monero_wallet_addresses.dart b/lib/monero/monero_wallet_addresses.dart index 55680e1c..d14caa27 100644 --- a/lib/monero/monero_wallet_addresses.dart +++ b/lib/monero/monero_wallet_addresses.dart @@ -1,38 +1,85 @@ import 'package:cake_wallet/entities/wallet_addresses.dart'; -import 'package:cake_wallet/entities/wallet_addresses_credentials.dart'; import 'package:cake_wallet/entities/wallet_info.dart'; -import 'monero_wallet_addresses_credentials.dart'; +import 'package:cake_wallet/monero/account.dart'; +import 'package:cake_wallet/monero/monero_account_list.dart'; +import 'package:cake_wallet/monero/monero_subaddress_list.dart'; +import 'package:cake_wallet/monero/subaddress.dart'; +import 'package:mobx/mobx.dart'; -class MoneroWalletAddresses extends WalletAddresses { - MoneroWalletAddresses(WalletInfo walletInfo) : super(walletInfo); +part 'monero_wallet_addresses.g.dart'; + +class MoneroWalletAddresses = MoneroWalletAddressesBase + with _$MoneroWalletAddresses; + +abstract class MoneroWalletAddressesBase extends WalletAddresses with Store { + MoneroWalletAddressesBase(WalletInfo walletInfo) : super(walletInfo) { + accountList = MoneroAccountList(); + subaddressList = MoneroSubaddressList(); + } @override - Future update(WalletAddressesCredentials credentials) async { - try { - if (credentials == null) { - return; - } + @observable + String address; + + @observable + Account account; + + @observable + Subaddress subaddress; - final _credentials = credentials as MoneroWalletAddressesCredentials; - final _accountList = _credentials.accountList; - final _subaddressList = _credentials.subaddressList; + MoneroSubaddressList subaddressList; - if (_accountList == null || _subaddressList == null) { - return; - } + MoneroAccountList accountList; + + @override + Future init() async { + accountList.update(); + account = accountList.accounts.first; + updateSubaddressList(accountIndex: account.id ?? 0); + await updateAddressesInBox(); + } + + @override + Future updateAddressesInBox() async { + try { + final _subaddressList = MoneroSubaddressList(); - addresses.clear(); + addressesMap.clear(); - _accountList.accounts.forEach((account) { + accountList.accounts.forEach((account) { _subaddressList.update(accountIndex: account.id); _subaddressList.subaddresses.forEach((subaddress) { - addresses[subaddress.address] = subaddress.label; + addressesMap[subaddress.address] = subaddress.label; }); }); - await save(); + await saveAddressesInBox(); } catch (e) { print(e.toString()); } } + + bool validate() { + accountList.update(); + final accountListLength = accountList.accounts?.length ?? 0; + + if (accountListLength <= 0) { + return false; + } + + subaddressList.update(accountIndex: accountList.accounts.first.id); + final subaddressListLength = subaddressList.subaddresses?.length ?? 0; + + if (subaddressListLength <= 0) { + return false; + } + + return true; + } + + void updateSubaddressList({int accountIndex}) { + subaddressList.update(accountIndex: accountIndex); + subaddress = subaddressList.subaddresses.first; + address = subaddress.address; + } } \ No newline at end of file diff --git a/lib/monero/monero_wallet_addresses_credentials.dart b/lib/monero/monero_wallet_addresses_credentials.dart deleted file mode 100644 index 0808cb12..00000000 --- a/lib/monero/monero_wallet_addresses_credentials.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:cake_wallet/entities/wallet_addresses_credentials.dart'; -import 'package:cake_wallet/monero/monero_account_list.dart'; -import 'package:cake_wallet/monero/monero_subaddress_list.dart'; - -class MoneroWalletAddressesCredentials extends WalletAddressesCredentials { - - MoneroAccountList accountList; - MoneroSubaddressList subaddressList; -} \ No newline at end of file diff --git a/lib/monero/monero_wallet_service.dart b/lib/monero/monero_wallet_service.dart index 7795b870..67db056d 100644 --- a/lib/monero/monero_wallet_service.dart +++ b/lib/monero/monero_wallet_service.dart @@ -117,7 +117,7 @@ class MoneroWalletService extends WalletService< (info) => info.id == WalletBase.idFor(name, getType()), orElse: () => null); final wallet = MoneroWallet(walletInfo: walletInfo); - final isValid = wallet.validate(); + final isValid = wallet.walletAddresses.validate(); if (!isValid) { await _removeCache(name); diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart index 428f2703..5c702b0a 100644 --- a/lib/reactions/on_current_wallet_change.dart +++ b/lib/reactions/on_current_wallet_change.dart @@ -37,7 +37,7 @@ void startCurrentWalletChangeReaction(AppStore appStore, await wallet.connectToNode(node: node); if (wallet.walletInfo.address?.isEmpty ?? true) { - wallet.walletInfo.address = wallet.address; + wallet.walletInfo.address = wallet.walletAddresses.address; if (wallet.walletInfo.isInBox) { await wallet.walletInfo.save(); diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 3eb23da3..6b4e9e3c 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -179,7 +179,7 @@ class ExchangePage extends BasePage { initialAddress: exchangeViewModel.depositCurrency == exchangeViewModel.wallet.currency - ? exchangeViewModel.wallet.address + ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.depositAddress, initialIsAmountEditable: true, initialIsAddressEditable: @@ -240,7 +240,7 @@ class ExchangePage extends BasePage { initialAddress: exchangeViewModel .receiveCurrency == exchangeViewModel.wallet.currency - ? exchangeViewModel.wallet.address + ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.receiveAddress, initialIsAmountEditable: exchangeViewModel .isReceiveAmountEditable, @@ -646,7 +646,8 @@ class ExchangePage extends BasePage { } }); - reaction((_) => exchangeViewModel.wallet.address, (String address) { + reaction((_) => exchangeViewModel.wallet.walletAddresses.address, + (String address) { if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) { depositKey.currentState.changeAddress(address: address); } @@ -707,7 +708,8 @@ class ExchangePage extends BasePage { isCurrentTypeWallet ? exchangeViewModel.wallet.name : null); key.currentState.changeAddress( - address: isCurrentTypeWallet ? exchangeViewModel.wallet.address : ''); + address: isCurrentTypeWallet + ? exchangeViewModel.wallet.walletAddresses.address : ''); key.currentState.changeAmount(amount: ''); } @@ -719,9 +721,9 @@ class ExchangePage extends BasePage { if (isCurrentTypeWallet) { key.currentState.changeWalletName(exchangeViewModel.wallet.name); key.currentState.addressController.text = - exchangeViewModel.wallet.address; + exchangeViewModel.wallet.walletAddresses.address; } else if (key.currentState.addressController.text == - exchangeViewModel.wallet.address) { + exchangeViewModel.wallet.walletAddresses.address) { key.currentState.changeWalletName(null); key.currentState.addressController.text = null; } diff --git a/lib/src/screens/exchange/exchange_template_page.dart b/lib/src/screens/exchange/exchange_template_page.dart index 7df55f32..c978a535 100644 --- a/lib/src/screens/exchange/exchange_template_page.dart +++ b/lib/src/screens/exchange/exchange_template_page.dart @@ -129,7 +129,7 @@ class ExchangeTemplatePage extends BasePage { initialAddress: exchangeViewModel .depositCurrency == exchangeViewModel.wallet.currency - ? exchangeViewModel.wallet.address + ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.depositAddress, initialIsAmountEditable: true, initialIsAddressEditable: exchangeViewModel @@ -168,7 +168,7 @@ class ExchangeTemplatePage extends BasePage { initialAddress: exchangeViewModel.receiveCurrency == exchangeViewModel.wallet.currency - ? exchangeViewModel.wallet.address + ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.receiveAddress, initialIsAmountEditable: exchangeViewModel.provider is @@ -383,7 +383,8 @@ class ExchangeTemplatePage extends BasePage { } }); - reaction((_) => exchangeViewModel.wallet.address, (String address) { + reaction((_) => exchangeViewModel.wallet.walletAddresses.address, + (String address) { if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) { depositKey.currentState.changeAddress(address: address); } @@ -405,7 +406,8 @@ class ExchangeTemplatePage extends BasePage { isCurrentTypeWallet ? exchangeViewModel.wallet.name : null); key.currentState.changeAddress( - address: isCurrentTypeWallet ? exchangeViewModel.wallet.address : ''); + address: isCurrentTypeWallet + ? exchangeViewModel.wallet.walletAddresses.address : ''); key.currentState.changeAmount(amount: ''); } @@ -417,9 +419,9 @@ class ExchangeTemplatePage extends BasePage { if (isCurrentTypeWallet) { key.currentState.changeWalletName(exchangeViewModel.wallet.name); key.currentState.addressController.text = - exchangeViewModel.wallet.address; + exchangeViewModel.wallet.walletAddresses.address; } else if (key.currentState.addressController.text == - exchangeViewModel.wallet.address) { + exchangeViewModel.wallet.walletAddresses.address) { key.currentState.changeWalletName(null); key.currentState.addressController.text = null; } diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index e35316d1..0777d3ec 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -92,17 +92,17 @@ abstract class DashboardViewModelBase with Store { final _wallet = wallet; if (_wallet is MoneroWallet) { - subname = _wallet.account?.label; + subname = _wallet.walletAddresses.account?.label; - _onMoneroAccountChangeReaction = reaction((_) => _wallet.account, - (Account account) => _onMoneroAccountChange(_wallet)); + _onMoneroAccountChangeReaction = reaction((_) => _wallet.walletAddresses + .account, (Account account) => _onMoneroAccountChange(_wallet)); _onMoneroBalanceChangeReaction = reaction((_) => _wallet.balance, (MoneroBalance balance) => _onMoneroTransactionsUpdate(_wallet)); final _accountTransactions = _wallet .transactionHistory.transactions.values - .where((tx) => tx.accountIndex == _wallet.account.id) + .where((tx) => tx.accountIndex == _wallet.walletAddresses.account.id) .toList(); transactions = ObservableList.of(_accountTransactions.map((transaction) => @@ -131,7 +131,7 @@ abstract class DashboardViewModelBase with Store { filter: (TransactionInfo tx) { final wallet = _wallet; if (tx is MoneroTransactionInfo && wallet is MoneroWallet) { - return tx.accountIndex == wallet.account.id; + return tx.accountIndex == wallet.walletAddresses.account.id; } return true; @@ -153,7 +153,7 @@ abstract class DashboardViewModelBase with Store { String subname; @computed - String get address => wallet.address; + String get address => wallet.walletAddresses.address; @computed SyncStatus get status => wallet.syncStatus; @@ -251,13 +251,13 @@ abstract class DashboardViewModelBase with Store { wallet.type == WalletType.bitcoin && wallet.seed.split(' ').length < 24; if (wallet is MoneroWallet) { - subname = wallet.account?.label; + subname = wallet.walletAddresses.account?.label; _onMoneroAccountChangeReaction?.reaction?.dispose(); _onMoneroBalanceChangeReaction?.reaction?.dispose(); - _onMoneroAccountChangeReaction = reaction((_) => wallet.account, - (Account account) => _onMoneroAccountChange(wallet)); + _onMoneroAccountChangeReaction = reaction((_) => wallet.walletAddresses + .account, (Account account) => _onMoneroAccountChange(wallet)); _onMoneroBalanceChangeReaction = reaction((_) => wallet.balance, (MoneroBalance balance) => _onMoneroTransactionsUpdate(wallet)); @@ -284,7 +284,7 @@ abstract class DashboardViewModelBase with Store { settingsStore: appStore.settingsStore), filter: (TransactionInfo tx) { if (tx is MoneroTransactionInfo && wallet is MoneroWallet) { - return tx.accountIndex == wallet.account.id; + return tx.accountIndex == wallet.walletAddresses.account.id; } return true; @@ -293,7 +293,7 @@ abstract class DashboardViewModelBase with Store { @action void _onMoneroAccountChange(MoneroWallet wallet) { - subname = wallet.account?.label; + subname = wallet.walletAddresses.account?.label; _onMoneroTransactionsUpdate(wallet); } @@ -302,7 +302,7 @@ abstract class DashboardViewModelBase with Store { transactions.clear(); final _accountTransactions = wallet.transactionHistory.transactions.values - .where((tx) => tx.accountIndex == wallet.account.id) + .where((tx) => tx.accountIndex == wallet.walletAddresses.account.id) .toList(); transactions.addAll(_accountTransactions.map((transaction) => diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index f3f00cd7..01246542 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -41,7 +41,8 @@ abstract class ExchangeViewModelBase with Store { depositAmount = ''; receiveAmount = ''; receiveAddress = ''; - depositAddress = depositCurrency == wallet.currency ? wallet.address : ''; + depositAddress = depositCurrency == wallet.currency + ? wallet.walletAddresses.address : ''; limitsState = LimitsInitialState(); tradeState = ExchangeTradeStateInitial(); _cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12; @@ -308,8 +309,10 @@ abstract class ExchangeViewModelBase with Store { isReceiveAmountEntered = false; depositAmount = ''; receiveAmount = ''; - depositAddress = depositCurrency == wallet.currency ? wallet.address : ''; - receiveAddress = receiveCurrency == wallet.currency ? wallet.address : ''; + depositAddress = depositCurrency == wallet.currency + ? wallet.walletAddresses.address : ''; + receiveAddress = receiveCurrency == wallet.currency + ? wallet.walletAddresses.address : ''; isDepositAddressEnabled = !(depositCurrency == wallet.currency); isReceiveAddressEnabled = !(receiveCurrency == wallet.currency); isFixedRateMode = false; diff --git a/lib/view_model/monero_account_list/monero_account_list_view_model.dart b/lib/view_model/monero_account_list/monero_account_list_view_model.dart index c6d6aa68..ca0eb67e 100644 --- a/lib/view_model/monero_account_list/monero_account_list_view_model.dart +++ b/lib/view_model/monero_account_list/monero_account_list_view_model.dart @@ -20,15 +20,16 @@ abstract class MoneroAccountListViewModelBase with Store { } @computed - List get accounts => _moneroWallet.accountList.accounts - .map((acc) => AccountListItem( + List get accounts => _moneroWallet.walletAddresses + .accountList.accounts.map((acc) => AccountListItem( label: acc.label, id: acc.id, - isSelected: acc.id == _moneroWallet.account.id)) + isSelected: acc.id == _moneroWallet.walletAddresses.account.id)) .toList(); final MoneroWallet _moneroWallet; void select(AccountListItem item) => - _moneroWallet.account = Account(id: item.id, label: item.label); + _moneroWallet.walletAddresses.account = + Account(id: item.id, label: item.label); } diff --git a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart index b018c542..3676b3bf 100644 --- a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart @@ -64,12 +64,15 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { final wallet = _wallet; if (wallet is ElectrumWallet) { - await wallet.generateNewAddress(); + await wallet.walletAddresses.generateNewAddress(); + await wallet.save(); } if (wallet is MoneroWallet) { - await wallet.subaddressList - .addSubaddress(accountIndex: wallet.account.id, label: label); + await wallet.walletAddresses.subaddressList + .addSubaddress( + accountIndex: wallet.walletAddresses.account.id, + label: label); await wallet.save(); } } @@ -77,13 +80,14 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { Future _update() async { final wallet = _wallet; - if (wallet is BitcoinWallet) { - await wallet.updateAddress(_item.address as String); - } + /*if (wallet is BitcoinWallet) { + await wallet.walletAddresses.updateAddress(_item.address as String); + await wallet.save(); + }*/ if (wallet is MoneroWallet) { - await wallet.subaddressList.setLabelSubaddress( - accountIndex: wallet.account.id, + await wallet.walletAddresses.subaddressList.setLabelSubaddress( + accountIndex: wallet.walletAddresses.account.id, addressIndex: _item.id as int, label: label); await wallet.save(); diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index b1544322..a4d6eff6 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -80,7 +80,7 @@ abstract class WalletAddressListViewModelBase with Store { @computed WalletAddressListItem get address => - WalletAddressListItem(address: _wallet.address); + WalletAddressListItem(address: _wallet.walletAddresses.address); @computed PaymentURI get uri { @@ -105,8 +105,10 @@ abstract class WalletAddressListViewModelBase with Store { final addressList = ObservableList(); if (wallet is MoneroWallet) { - final primaryAddress = wallet.subaddressList.subaddresses.first; - addressList.addAll(wallet.subaddressList.subaddresses.map((subaddress) { + final primaryAddress = + wallet.walletAddresses.subaddressList.subaddresses.first; + addressList.addAll(wallet.walletAddresses.subaddressList.subaddresses + .map((subaddress) { final isPrimary = subaddress == primaryAddress; return WalletAddressListItem( @@ -118,8 +120,8 @@ abstract class WalletAddressListViewModelBase with Store { } if (wallet is BitcoinWallet) { - final primaryAddress = wallet.addresses.first; - final bitcoinAddresses = wallet.addresses.map((addr) { + final primaryAddress = wallet.walletAddresses.addresses.first; + final bitcoinAddresses = wallet.walletAddresses.addresses.map((addr) { final isPrimary = addr == primaryAddress; return WalletAddressListItem( @@ -139,7 +141,7 @@ abstract class WalletAddressListViewModelBase with Store { final wallet = _wallet; if (wallet is MoneroWallet) { - return wallet.account.label; + return wallet.walletAddresses.account.label; } return null; @@ -160,7 +162,7 @@ abstract class WalletAddressListViewModelBase with Store { @action void setAddress(WalletAddressListItem address) => - _wallet.address = address.address; + _wallet.walletAddresses.address = address.address; void _init() { _baseItems = []; @@ -177,7 +179,8 @@ abstract class WalletAddressListViewModelBase with Store { final wallet = _wallet; if (wallet is ElectrumWallet) { - wallet.nextAddress(); + wallet.walletAddresses.nextAddress(); + wallet.save(); } } } diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 58ee2408..402d3be8 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -50,7 +50,7 @@ abstract class WalletCreationVMBase with Store { dirPath: dirPath); credentials.walletInfo = walletInfo; final wallet = await process(credentials); - walletInfo.address = wallet.address; + walletInfo.address = wallet.walletAddresses.address; await _walletInfoSource.add(walletInfo); _appStore.changeCurrentWallet(wallet); _appStore.authenticationStore.allowed(); From 008936435b287adbf06bba5114e988eead1707fb Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Fri, 16 Jul 2021 13:28:46 +0300 Subject: [PATCH 16/18] CAKE-192 | added name property to parsed_address.dart; fixed parse_address_from_domain.dart --- lib/entities/parse_address_from_domain.dart | 29 +++++++++++++-------- lib/entities/parsed_address.dart | 6 ++++- lib/src/screens/exchange/exchange_page.dart | 4 +-- lib/src/screens/send/send_page.dart | 4 +-- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index 0c2b864d..3dc12e6c 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -7,34 +7,41 @@ const topLevelDomain = 'crypto'; Future parseAddressFromDomain( String domain, String ticker) async { try { - final domainParts = domain.split('.'); + final formattedName = OpenaliasRecord.formatDomainName(domain); + final domainParts = formattedName.split('.'); final name = domainParts.last; if (domainParts.length <= 1 || domainParts.first.isEmpty || name.isEmpty) { - return ParsedAddress(domain, ParseFrom.notParsed); + return ParsedAddress(address: domain); } if (name.contains(topLevelDomain)) { - final address = await fetchUnstoppableDomainAddress(domain, ticker); + final address = + await fetchUnstoppableDomainAddress(formattedName, ticker); if (address?.isEmpty ?? true) { - return ParsedAddress(domain, ParseFrom.notParsed); + return ParsedAddress(address: domain); } - return ParsedAddress(address, ParseFrom.unstoppableDomains); + return ParsedAddress( + address: address, + name: formattedName, + parseFrom: ParseFrom.unstoppableDomains); } - final record = await OpenaliasRecord.fetchAddressAndName( - OpenaliasRecord.formatDomainName(domain)); + final record = await OpenaliasRecord.fetchAddressAndName(formattedName); - if (record == null || record.address.contains(domain)) { - return ParsedAddress(domain, ParseFrom.notParsed); + if (record == null || record.address.contains(formattedName)) { + return ParsedAddress(address: domain); } - return ParsedAddress(record.address, ParseFrom.openAlias); + return ParsedAddress( + address: record.address, + name: record.name, + parseFrom: ParseFrom.openAlias); } catch (e) { print(e.toString()); } - return ParsedAddress(domain, ParseFrom.notParsed); + return ParsedAddress(address: domain); } \ No newline at end of file diff --git a/lib/entities/parsed_address.dart b/lib/entities/parsed_address.dart index f293d99c..91fec675 100644 --- a/lib/entities/parsed_address.dart +++ b/lib/entities/parsed_address.dart @@ -1,8 +1,12 @@ enum ParseFrom {unstoppableDomains, openAlias, notParsed} class ParsedAddress { - ParsedAddress(this.address, this.parseFrom); + ParsedAddress({ + this.address = '', + this.name = '', + this.parseFrom = ParseFrom.notParsed}); final String address; + final String name; final ParseFrom parseFrom; } \ No newline at end of file diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 693eade7..286134f1 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -787,13 +787,13 @@ class ExchangePage extends BasePage { showAddressAlert( context, S.of(context).address_detected, - S.of(context).address_from_domain(domain)); + S.of(context).address_from_domain(parsedAddress.name)); break; case ParseFrom.openAlias: showAddressAlert( context, S.of(context).openalias_alert_title, - S.of(context).openalias_alert_content(domain)); + S.of(context).openalias_alert_content(parsedAddress.name)); break; case ParseFrom.notParsed: break; diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 2aa4ebb8..aae86483 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -767,13 +767,13 @@ class SendPage extends BasePage { showAddressAlert( context, S.of(context).address_detected, - S.of(context).address_from_domain(domain)); + S.of(context).address_from_domain(parsedAddress.name)); break; case ParseFrom.openAlias: showAddressAlert( context, S.of(context).openalias_alert_title, - S.of(context).openalias_alert_content(domain)); + S.of(context).openalias_alert_content(parsedAddress.name)); break; case ParseFrom.notParsed: break; From 6855a6d68bf91a030fe10fafd16bd2eb7f56dcb4 Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Fri, 16 Jul 2021 13:44:12 +0300 Subject: [PATCH 17/18] CAKE-192 | fixed parse_address_from_domain.dart --- lib/entities/parse_address_from_domain.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index 3dc12e6c..45571e35 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -17,7 +17,7 @@ Future parseAddressFromDomain( if (name.contains(topLevelDomain)) { final address = - await fetchUnstoppableDomainAddress(formattedName, ticker); + await fetchUnstoppableDomainAddress(domain, ticker); if (address?.isEmpty ?? true) { return ParsedAddress(address: domain); @@ -25,7 +25,7 @@ Future parseAddressFromDomain( return ParsedAddress( address: address, - name: formattedName, + name: domain, parseFrom: ParseFrom.unstoppableDomains); } From 8759c2ce5652d24c2f3a10190cc359d21f895d42 Mon Sep 17 00:00:00 2001 From: M Date: Wed, 21 Jul 2021 20:07:56 +0300 Subject: [PATCH 18/18] Changed backup wallet files call. --- lib/monero/monero_wallet.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/monero/monero_wallet.dart b/lib/monero/monero_wallet.dart index 4105e5de..b51c94ed 100644 --- a/lib/monero/monero_wallet.dart +++ b/lib/monero/monero_wallet.dart @@ -245,9 +245,9 @@ abstract class MoneroWalletBase extends WalletBase getNodeHeight() async => monero_wallet.getNodeHeight();