CAKE-192 | implemented unstoppable domain address to the app
OleksandrSobol committed
Apr 20, 2021 at 20:49 UTC
ae9efb0ae8ae35e0c33bcfe7ba3473ddc9b4d0ae
29 files changed
+327
-46
android/app/build.gradle
+3
-2
@@ -81,6 +81,7 @@ flutter {
81
82
dependencies {
83
testImplementation 'junit:junit:4.12'
84
- androidTestImplementation 'androidx.test:runner:1.1.1'
85
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
84
+ androidTestImplementation 'androidx.test:runner:1.3.0'
85
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
86
+ implementation 'com.unstoppabledomains:resolution:1.13.0'
87
}
android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java
+45
-1
@@ -5,11 +5,55 @@ import io.flutter.embedding.android.FlutterFragmentActivity;
5
import io.flutter.embedding.engine.FlutterEngine;
6
import io.flutter.plugins.GeneratedPluginRegistrant;
7
8
+import com.unstoppabledomains.resolution.DomainResolution;
9
+import com.unstoppabledomains.resolution.Resolution;
10
+
11
+import android.os.AsyncTask;
12
+import android.os.Handler;
13
+import android.os.Looper;
14
+
15
+import io.flutter.plugin.common.MethodCall;
16
+import io.flutter.plugin.common.MethodChannel;
17
18
public class MainActivity extends FlutterFragmentActivity {
10
-
19
+ final String UNSTOPPABLE_DOMAIN_CHANNEL = "com.cakewallet.cake_wallet/unstoppable-domain";
20
+
21
@Override
22
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
23
GeneratedPluginRegistrant.registerWith(flutterEngine);
24
+
25
+ MethodChannel unstoppableDomainChannel =
26
+ new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),
27
+ UNSTOPPABLE_DOMAIN_CHANNEL);
28
+
29
+ unstoppableDomainChannel.setMethodCallHandler(this::handle);
30
+ }
31
+
32
+ private void handle(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
33
+ try {
34
+ if (call.method.equals("getUnstoppableDomainAddress")) {
35
+ getUnstoppableDomainAddress(call, result);
36
+ } else {
37
+ result.notImplemented();
38
+ }
39
+ } catch (Exception e) {
40
+ result.error("UNCAUGHT_ERROR", e.getMessage(), null);
41
+ }
42
+ }
43
+
44
+ private void getUnstoppableDomainAddress(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
45
+ DomainResolution resolution = new Resolution();
46
+ Handler handler = new Handler(Looper.getMainLooper());
47
+ String domain = call.argument("domain");
48
+ String ticker = call.argument("ticker");
49
+
50
+ AsyncTask.execute(() -> {
51
+ try {
52
+ String address = resolution.getAddress(domain, ticker);
53
+ handler.post(() -> result.success(address));
54
+ } catch (Exception e) {
55
+ handler.post(() -> result.error("INVALID DOMAIN", e.getMessage(), null));
56
+ }
57
+ });
58
}
59
}
android/build.gradle
+1
-1
@@ -5,7 +5,7 @@ buildscript {
5
}
6
7
dependencies {
8
- classpath 'com.android.tools.build:gradle:3.5.4'
8
+ classpath 'com.android.tools.build:gradle:4.1.3'
9
}
10
}
11
android/gradle/wrapper/gradle-wrapper.properties
+2
-2
@@ -1,6 +1,6 @@
1
-#Fri Jun 23 08:50:38 CEST 2017
1
+#Mon Apr 19 18:19:26 EEST 2021
2
distributionBase=GRADLE_USER_HOME
3
distributionPath=wrapper/dists
4
zipStoreBase=GRADLE_USER_HOME
5
zipStorePath=wrapper/dists
6
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
6
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
ios/Podfile
+2
-1
@@ -1,5 +1,5 @@
1
# Uncomment this line to define a global platform for your project
2
-platform :ios, '9.0'
2
+platform :ios, '11.0'
3
source 'https://github.com/CocoaPods/Specs.git'
4
5
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
@@ -36,6 +36,7 @@ target 'Runner' do
36
37
# Cake Wallet (Legacy)
38
pod 'CryptoSwift'
39
+ pod 'UnstoppableDomainsResolution', '~> 0.3.6'
40
end
41
42
post_install do |installer|
ios/Podfile.lock
+16
-2
@@ -3,6 +3,7 @@ PODS:
3
- Flutter
4
- MTBBarcodeScanner
5
- SwiftProtobuf
6
+ - BigInt (5.2.0)
7
- connectivity (0.0.1):
8
- Flutter
9
- Reachability
@@ -59,6 +60,8 @@ PODS:
60
- SwiftyGif
61
- esys_flutter_share (0.0.1):
62
- Flutter
63
+ - EthereumAddress (1.3.0):
64
+ - CryptoSwift (~> 1.0)
65
- file_picker (0.0.1):
66
- DKImagePickerController/PhotoGallery
67
- Flutter
@@ -84,6 +87,10 @@ PODS:
87
- Flutter
88
- SwiftProtobuf (1.12.0)
89
- SwiftyGif (5.3.0)
90
+ - UnstoppableDomainsResolution (0.3.6):
91
+ - BigInt
92
+ - CryptoSwift (~> 1.0)
93
+ - EthereumAddress (~> 1.3)
94
- url_launcher (0.0.1):
95
- Flutter
96
- webview_flutter (0.0.1):
@@ -105,19 +112,23 @@ DEPENDENCIES:
112
- permission_handler (from `.symlinks/plugins/permission_handler/ios`)
113
- share (from `.symlinks/plugins/share/ios`)
114
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
115
+ - UnstoppableDomainsResolution (~> 0.3.6)
116
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
117
- webview_flutter (from `.symlinks/plugins/webview_flutter/ios`)
118
119
SPEC REPOS:
120
https://github.com/CocoaPods/Specs.git:
121
+ - BigInt
122
- CryptoSwift
123
- DKImagePickerController
124
- DKPhotoGallery
125
+ - EthereumAddress
126
- MTBBarcodeScanner
127
- Reachability
128
- SDWebImage
129
- SwiftProtobuf
130
- SwiftyGif
131
+ - UnstoppableDomainsResolution
132
133
EXTERNAL SOURCES:
134
barcode_scan:
@@ -155,6 +166,7 @@ EXTERNAL SOURCES:
166
167
SPEC CHECKSUMS:
168
barcode_scan: a5c27959edfafaa0c771905bad0b29d6d39e4479
169
+ BigInt: f668a80089607f521586bbe29513d708491ef2f7
170
connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467
171
CryptoSwift: 093499be1a94b0cae36e6c26b70870668cb56060
172
cw_monero: 2e1f79929880cc2293b5bc1b25e28152e4d84649
@@ -162,6 +174,7 @@ SPEC CHECKSUMS:
174
DKImagePickerController: b5eb7f7a388e4643264105d648d01f727110fc3d
175
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
176
esys_flutter_share: 403498dab005b36ce1f8d7aff377e81f0621b0b4
177
+ EthereumAddress: 39fe8e11cf04e4e9902b55ae653dbc4e0aee5f30
178
file_picker: 3e6c3790de664ccf9b882732d9db5eaf6b8d4eb1
179
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
180
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
@@ -176,9 +189,10 @@ SPEC CHECKSUMS:
189
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
190
SwiftProtobuf: 4ef85479c18ca85b5482b343df9c319c62bda699
191
SwiftyGif: e466e86c660d343357ab944a819a101c4127cb40
192
+ UnstoppableDomainsResolution: 63abb84858d3e91eb838a5bfa6f7e3c0e0593f24
193
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
194
webview_flutter: 9f491a9b5a66f2573946a389b2677987b0ff8c0b
195
182
-PODFILE CHECKSUM: 5b5f101b119a1b6eb857c967d462832a9062dec4
196
+PODFILE CHECKSUM: 2172f10eb8ff8378f8d6e3e2c1366a0e6cdea018
197
184
-COCOAPODS: 1.9.3
198
+COCOAPODS: 1.10.1
ios/Runner/AppDelegate.swift
+40
@@ -1,8 +1,13 @@
1
import UIKit
2
import Flutter
3
+import UnstoppableDomainsResolution
4
5
@UIApplicationMain
6
@objc class AppDelegate: FlutterAppDelegate {
7
+ lazy var resolution : Resolution? = {
8
+ return try? Resolution()
9
+ }()
10
+
11
override func application(
12
_ application: UIApplication,
13
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
@@ -10,6 +15,8 @@ import Flutter
15
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
16
let batteryChannel = FlutterMethodChannel(name: "com.cakewallet.cakewallet/legacy_wallet_migration",
17
binaryMessenger: controller.binaryMessenger)
18
+ let unstoppableDomainChannel = FlutterMethodChannel(name: "com.cakewallet.cake_wallet/unstoppable-domain", binaryMessenger: controller.binaryMessenger)
19
+
20
batteryChannel.setMethodCallHandler({
21
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
22
@@ -52,6 +59,39 @@ import Flutter
59
}
60
})
61
62
+ unstoppableDomainChannel.setMethodCallHandler({ [weak self]
63
+ (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
64
+ switch call.method {
65
+ case "getUnstoppableDomainAddress":
66
+ guard let args = call.arguments as? Dictionary<String, String>,
67
+ let domain = args["domain"],
68
+ let ticker = args["ticker"] else {
69
+ result(nil)
70
+ return
71
+ }
72
+
73
+ guard let resolution = self?.resolution else {
74
+ result(nil)
75
+ return
76
+ }
77
+
78
+ resolution.addr(domain: domain, ticker: ticker) { addrResult in
79
+ var address : String = ""
80
+
81
+ switch addrResult {
82
+ case .success(let returnValue):
83
+ address = returnValue
84
+ case .failure(let error):
85
+ print("Expected Address, but got \(error)")
86
+ }
87
+
88
+ result(address)
89
+ }
90
+ default:
91
+ result(FlutterMethodNotImplemented)
92
+ }
93
+ })
94
+
95
GeneratedPluginRegistrant.register(with: self)
96
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
97
}
lib/entities/unstoppable_domain_address.dart
new
+22
@@ -0,0 +1,22 @@
1
+import 'package:flutter/services.dart';
2
+
3
+const channel = MethodChannel('com.cakewallet.cake_wallet/unstoppable-domain');
4
+
5
+Future<String> fetchUnstoppableDomainAddress(String domain, String ticker) async {
6
+ String address;
7
+
8
+ try {
9
+ address = await channel.invokeMethod(
10
+ 'getUnstoppableDomainAddress',
11
+ <String, String> {
12
+ 'domain' : domain,
13
+ 'ticker' : ticker
14
+ }
15
+ );
16
+ } catch (e) {
17
+ print('Unstoppable domain error: ${e.toString()}');
18
+ address = '';
19
+ }
20
+
21
+ return address;
22
+}
\ No newline at end of file
lib/src/screens/exchange/exchange_page.dart
+73
-8
@@ -1,7 +1,7 @@
1
import 'dart:ui';
2
import 'package:cake_wallet/entities/sync_status.dart';
3
import 'package:cake_wallet/entities/wallet_type.dart';
4
-import 'package:cake_wallet/exchange/changenow/changenow_exchange_provider.dart';
4
+import 'package:cake_wallet/src/screens/send/widgets/unstoppable_domain_address_alert.dart';
5
import 'package:cake_wallet/src/widgets/standard_checkbox.dart';
6
import 'package:dotted_border/dotted_border.dart';
7
import 'package:flutter/cupertino.dart';
@@ -9,8 +9,6 @@ import 'package:flutter/material.dart';
9
import 'package:flutter_mobx/flutter_mobx.dart';
10
import 'package:keyboard_actions/keyboard_actions.dart';
11
import 'package:mobx/mobx.dart';
12
-import 'package:cake_wallet/exchange/exchange_provider.dart';
13
-import 'package:cake_wallet/core/execution_state.dart';
12
import 'package:cake_wallet/exchange/exchange_template.dart';
13
import 'package:cake_wallet/exchange/exchange_trade_state.dart';
14
import 'package:cake_wallet/exchange/limits_state.dart';
@@ -23,7 +21,6 @@ import 'package:cake_wallet/utils/show_pop_up.dart';
21
import 'package:cake_wallet/routes.dart';
22
import 'package:cake_wallet/generated/i18n.dart';
23
import 'package:cake_wallet/entities/crypto_currency.dart';
26
-import 'package:cake_wallet/exchange/xmrto/xmrto_exchange_provider.dart';
24
import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart';
25
import 'package:cake_wallet/src/widgets/primary_button.dart';
26
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
@@ -42,7 +39,9 @@ class ExchangePage extends BasePage {
39
final checkBoxKey = GlobalKey<StandardCheckboxState>();
40
final _formKey = GlobalKey<FormState>();
41
final _depositAmountFocus = FocusNode();
42
+ final _depositAddressFocus = FocusNode();
43
final _receiveAmountFocus = FocusNode();
44
+ final _receiveAddressFocus = FocusNode();
45
var _isReactionsSet = false;
46
47
@override
@@ -52,7 +51,7 @@ class ExchangePage extends BasePage {
51
Color get titleColor => Colors.white;
52
53
@override
55
- bool get resizeToAvoidBottomPadding => false;
54
+ bool get resizeToAvoidBottomInset => false;
55
56
@override
57
bool get extendBodyBehindAppBar => true;
@@ -171,6 +170,7 @@ class ExchangePage extends BasePage {
170
.calculateDepositAllAmount()
171
: null,
172
amountFocusNode: _depositAmountFocus,
173
+ addressFocusNode: _depositAddressFocus,
174
key: depositKey,
175
title: S.of(context).you_will_send,
176
initialCurrency:
@@ -223,6 +223,15 @@ class ExchangePage extends BasePage {
223
type: exchangeViewModel.wallet.type),
224
addressTextFieldValidator: AddressValidator(
225
type: exchangeViewModel.depositCurrency),
226
+ onPushPasteButton: (context) async {
227
+ final domain =
228
+ exchangeViewModel.depositAddress;
229
+ final ticker =
230
+ exchangeViewModel.depositCurrency.title;
231
+ exchangeViewModel.depositAddress =
232
+ await applyUnstoppableDomainAddress(
233
+ context, domain, ticker);
234
+ },
235
),
236
),
237
),
@@ -232,6 +241,7 @@ class ExchangePage extends BasePage {
241
child: Observer(
242
builder: (_) => ExchangeCard(
243
amountFocusNode: _receiveAmountFocus,
244
+ addressFocusNode: _receiveAddressFocus,
245
key: receiveKey,
246
title: S.of(context).you_will_get,
247
initialCurrency:
@@ -268,6 +278,15 @@ class ExchangePage extends BasePage {
278
AddressValidator(
279
type: exchangeViewModel
280
.receiveCurrency),
281
+ onPushPasteButton: (context) async {
282
+ final domain =
283
+ exchangeViewModel.receiveAddress;
284
+ final ticker =
285
+ exchangeViewModel.receiveCurrency.title;
286
+ exchangeViewModel.receiveAddress =
287
+ await applyUnstoppableDomainAddress(
288
+ context, domain, ticker);
289
+ },
290
)),
291
)
292
],
@@ -371,7 +390,7 @@ class ExchangePage extends BasePage {
390
from: template.depositCurrency,
391
to: template.receiveCurrency,
392
onTap: () {
374
- applyTemplate(
393
+ applyTemplate(context,
394
exchangeViewModel, template);
395
},
396
onRemove: () {
@@ -472,8 +491,8 @@ class ExchangePage extends BasePage {
491
));
492
}
493
475
- void applyTemplate(
476
- ExchangeViewModel exchangeViewModel, ExchangeTemplate template) {
494
+ void applyTemplate(BuildContext context,
495
+ ExchangeViewModel exchangeViewModel, ExchangeTemplate template) async {
496
exchangeViewModel.changeDepositCurrency(
497
currency: CryptoCurrency.fromString(template.depositCurrency));
498
exchangeViewModel.changeReceiveCurrency(
@@ -491,6 +510,16 @@ class ExchangePage extends BasePage {
510
exchangeViewModel.receiveAddress = template.receiveAddress;
511
exchangeViewModel.isReceiveAmountEntered = false;
512
exchangeViewModel.isFixedRateMode = false;
513
+
514
+ var domain = template.depositAddress;
515
+ var ticker = template.depositCurrency;
516
+ exchangeViewModel.depositAddress =
517
+ await applyUnstoppableDomainAddress(context, domain, ticker);
518
+
519
+ domain = template.receiveAddress;
520
+ ticker = template.receiveCurrency;
521
+ exchangeViewModel.receiveAddress =
522
+ await applyUnstoppableDomainAddress(context, domain, ticker);
523
}
524
525
void _setReactions(
@@ -656,6 +685,26 @@ class ExchangePage extends BasePage {
685
}
686
});
687
688
+ _depositAddressFocus.addListener(() async {
689
+ if (!_depositAddressFocus.hasFocus &&
690
+ depositAddressController.text.isNotEmpty) {
691
+ final domain = depositAddressController.text;
692
+ final ticker = exchangeViewModel.depositCurrency.title;
693
+ exchangeViewModel.depositAddress =
694
+ await applyUnstoppableDomainAddress(context, domain, ticker);
695
+ }
696
+ });
697
+
698
+ _receiveAddressFocus.addListener(() async {
699
+ if (!_receiveAddressFocus.hasFocus &&
700
+ receiveAddressController.text.isNotEmpty) {
701
+ final domain = receiveAddressController.text;
702
+ final ticker = exchangeViewModel.receiveCurrency.title;
703
+ exchangeViewModel.receiveAddress =
704
+ await applyUnstoppableDomainAddress(context, domain, ticker);
705
+ }
706
+ });
707
+
708
_receiveAmountFocus.addListener(() {
709
if (_receiveAmountFocus.hasFocus && !exchangeViewModel.isFixedRateMode) {
710
showPopUp<void>(
@@ -726,4 +775,20 @@ class ExchangePage extends BasePage {
775
key.currentState.addressController.text = null;
776
}
777
}
778
+
779
+ Future<String> applyUnstoppableDomainAddress(BuildContext context,
780
+ String domain, String ticker) async {
781
+ try {
782
+ final address =
783
+ await exchangeViewModel.getUnstoppableDomainAddress(domain, ticker);
784
+ if ((address != null)&&address.isNotEmpty) {
785
+ unstoppableDomainAddressAlert(context, domain);
786
+ return address;
787
+ }
788
+ } catch (e) {
789
+ print(e.toString());
790
+ }
791
+
792
+ return domain;
793
+ }
794
}
lib/src/screens/exchange/exchange_template_page.dart
+5
-6
@@ -37,7 +37,7 @@ class ExchangeTemplatePage extends BasePage {
37
Color get titleColor => Colors.white;
38
39
@override
40
- bool get resizeToAvoidBottomPadding => false;
40
+ bool get resizeToAvoidBottomInset => false;
41
42
@override
43
bool get extendBodyBehindAppBar => true;
@@ -150,9 +150,8 @@ class ExchangeTemplatePage extends BasePage {
150
.color,
151
currencyValueValidator: AmountValidator(
152
type: exchangeViewModel.wallet.type),
153
- addressTextFieldValidator: AddressValidator(
154
- type:
155
- exchangeViewModel.depositCurrency),
153
+ //addressTextFieldValidator: AddressValidator(
154
+ // type: exchangeViewModel.depositCurrency),
155
),
156
),
157
),
@@ -190,8 +189,8 @@ class ExchangeTemplatePage extends BasePage {
189
.decorationColor,
190
currencyValueValidator: AmountValidator(
191
type: exchangeViewModel.wallet.type),
193
- addressTextFieldValidator: AddressValidator(
194
- type: exchangeViewModel.receiveCurrency),
192
+ //addressTextFieldValidator: AddressValidator(
193
+ // type: exchangeViewModel.receiveCurrency),
194
)),
195
)
196
],
lib/src/screens/exchange/widgets/exchange_card.dart
+8
-2
@@ -28,8 +28,10 @@ class ExchangeCard extends StatefulWidget {
28
this.currencyValueValidator,
29
this.addressTextFieldValidator,
30
this.amountFocusNode,
31
+ this.addressFocusNode,
32
this.hasAllAmount = false,
32
- this.allAmount})
33
+ this.allAmount,
34
+ this.onPushPasteButton})
35
: super(key: key);
36
37
final List<CryptoCurrency> currencies;
@@ -49,8 +51,10 @@ class ExchangeCard extends StatefulWidget {
51
final FormFieldValidator<String> currencyValueValidator;
52
final FormFieldValidator<String> addressTextFieldValidator;
53
final FocusNode amountFocusNode;
54
+ final FocusNode addressFocusNode;
55
final bool hasAllAmount;
53
- Function allAmount;
56
+ final Function allAmount;
57
+ final Function(BuildContext context) onPushPasteButton;
58
59
@override
60
ExchangeCardState createState() => ExchangeCardState();
@@ -288,6 +292,7 @@ class ExchangeCardState extends State<ExchangeCard> {
292
? Padding(
293
padding: EdgeInsets.only(top: 20),
294
child: AddressTextField(
295
+ focusNode: widget.addressFocusNode,
296
controller: addressController,
297
placeholder: widget.hasRefundAddress
298
? S.of(context).refund_address
@@ -311,6 +316,7 @@ class ExchangeCardState extends State<ExchangeCard> {
316
.decorationColor),
317
buttonColor: widget.addressButtonsColor,
318
validator: widget.addressTextFieldValidator,
319
+ onPushPasteButton: widget.onPushPasteButton,
320
),
321
)
322
: Padding(
lib/src/screens/send/send_page.dart
+28
-6
@@ -1,6 +1,6 @@
1
import 'dart:ui';
2
-import 'package:cake_wallet/entities/monero_transaction_priority.dart';
2
import 'package:cake_wallet/entities/transaction_priority.dart';
3
+import 'package:cake_wallet/src/screens/send/widgets/unstoppable_domain_address_alert.dart';
4
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
5
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
6
import 'package:cake_wallet/src/widgets/picker.dart';
@@ -38,9 +38,10 @@ class SendPage extends BasePage {
38
_cryptoAmountFocus = FocusNode(),
39
_fiatAmountFocus = FocusNode(),
40
_addressFocusNode = FocusNode() {
41
- _addressFocusNode.addListener(() {
41
+ _addressFocusNode.addListener(() async {
42
if (!_addressFocusNode.hasFocus && _addressController.text.isNotEmpty) {
43
- getOpenaliasRecord(_addressFocusNode.context);
43
+ await getOpenaliasRecord(_addressFocusNode.context);
44
+ await applyUnstoppableDomainAddress(_addressFocusNode.context);
45
}
46
});
47
}
@@ -67,7 +68,7 @@ class SendPage extends BasePage {
68
Color get titleColor => Colors.white;
69
70
@override
70
- bool get resizeToAvoidBottomPadding => false;
71
+ bool get resizeToAvoidBottomInset => false;
72
73
@override
74
bool get extendBodyBehindAppBar => true;
@@ -173,6 +174,10 @@ class SendPage extends BasePage {
174
.headline
175
.decorationColor),
176
validator: sendViewModel.addressValidator,
177
+ onPushPasteButton: (context) async {
178
+ await getOpenaliasRecord(context);
179
+ await applyUnstoppableDomainAddress(context);
180
+ },
181
),
182
Observer(
183
builder: (_) => Padding(
@@ -513,12 +518,13 @@ class SendPage extends BasePage {
518
to: template.name,
519
amount: template.amount,
520
from: template.cryptoCurrency,
516
- onTap: () {
521
+ onTap: () async {
522
_addressController.text =
523
template.address;
524
_cryptoAmountController.text =
525
template.amount;
521
- getOpenaliasRecord(context);
526
+ await getOpenaliasRecord(context);
527
+ await applyUnstoppableDomainAddress(context);
528
},
529
onRemove: () {
530
showPopUp<void>(
@@ -770,4 +776,20 @@ class SendPage extends BasePage {
776
),
777
context: context);
778
}
779
+
780
+ Future<void> applyUnstoppableDomainAddress(BuildContext context) async {
781
+ try {
782
+ final address = await sendViewModel
783
+ .getUnstoppableDomainAddress(
784
+ _addressController.text);
785
+
786
+ if ((address != null)&&address.isNotEmpty) {
787
+ unstoppableDomainAddressAlert(
788
+ context, _addressController.text);
789
+ _addressController.text = address;
790
+ }
791
+ } catch (e) {
792
+ print(e.toString());
793
+ }
794
+ }
795
}
lib/src/screens/send/send_template_page.dart
+2
-2
@@ -34,7 +34,7 @@ class SendTemplatePage extends BasePage {
34
Color get titleColor => Colors.white;
35
36
@override
37
- bool get resizeToAvoidBottomPadding => false;
37
+ bool get resizeToAvoidBottomInset => false;
38
39
@override
40
bool get extendBodyBehindAppBar => true;
@@ -145,7 +145,7 @@ class SendTemplatePage extends BasePage {
145
.primaryTextTheme
146
.headline
147
.decorationColor),
148
- validator: sendViewModel.addressValidator,
148
+ //validator: sendViewModel.addressValidator,
149
),
150
),
151
Observer(builder: (_) {
lib/src/screens/send/widgets/unstoppable_domain_address_alert.dart
new
+17
@@ -0,0 +1,17 @@
1
+import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
2
+import 'package:cake_wallet/utils/show_pop_up.dart';
3
+import 'package:flutter/material.dart';
4
+import 'package:cake_wallet/generated/i18n.dart';
5
+
6
+void unstoppableDomainAddressAlert(BuildContext context, String domain) async {
7
+ await showPopUp<void>(
8
+ context: context,
9
+ builder: (BuildContext context) {
10
+
11
+ return AlertWithOneAction(
12
+ alertTitle: S.of(context).address_detected,
13
+ alertContent: S.of(context).address_from_domain(domain),
14
+ buttonText: S.of(context).ok,
15
+ buttonAction: () => Navigator.of(context).pop());
16
+ });
17
+}
\ No newline at end of file
lib/src/widgets/address_text_field.dart
+5
-1
@@ -24,7 +24,8 @@ class AddressTextField extends StatelessWidget {
24
this.iconColor,
25
this.textStyle,
26
this.hintStyle,
27
- this.validator});
27
+ this.validator,
28
+ this.onPushPasteButton});
29
30
static const prefixIconWidth = 34.0;
31
static const prefixIconHeight = 34.0;
@@ -43,6 +44,7 @@ class AddressTextField extends StatelessWidget {
44
final TextStyle textStyle;
45
final TextStyle hintStyle;
46
final FocusNode focusNode;
47
+ final Function(BuildContext context) onPushPasteButton;
48
49
@override
50
Widget build(BuildContext context) {
@@ -225,5 +227,7 @@ class AddressTextField extends StatelessWidget {
227
if (address?.isNotEmpty ?? false) {
228
controller.text = address;
229
}
230
+
231
+ onPushPasteButton?.call(context);
232
}
233
}
lib/view_model/exchange/exchange_view_model.dart
+5
@@ -4,6 +4,7 @@ import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
4
import 'package:cake_wallet/core/wallet_base.dart';
5
import 'package:cake_wallet/entities/crypto_currency.dart';
6
import 'package:cake_wallet/entities/sync_status.dart';
7
+import 'package:cake_wallet/entities/unstoppable_domain_address.dart';
8
import 'package:cake_wallet/entities/wallet_type.dart';
9
import 'package:cake_wallet/exchange/exchange_provider.dart';
10
import 'package:cake_wallet/exchange/limits.dart';
@@ -417,4 +418,8 @@ abstract class ExchangeViewModelBase with Store {
418
}*/
419
isReceiveAmountEditable = false;
420
}
421
+
422
+ Future<String> getUnstoppableDomainAddress(String domain, String ticker) async {
423
+ return await fetchUnstoppableDomainAddress(domain, ticker.toLowerCase());
424
+ }
425
}
lib/view_model/send/send_view_model.dart
+5
@@ -4,6 +4,7 @@ import 'package:cake_wallet/entities/balance_display_mode.dart';
4
import 'package:cake_wallet/entities/calculate_fiat_amount_raw.dart';
5
import 'package:cake_wallet/entities/transaction_description.dart';
6
import 'package:cake_wallet/entities/transaction_priority.dart';
7
+import 'package:cake_wallet/entities/unstoppable_domain_address.dart';
8
import 'package:cake_wallet/monero/monero_amount_format.dart';
9
import 'package:cake_wallet/view_model/settings/settings_view_model.dart';
10
import 'package:hive/hive.dart';
@@ -267,6 +268,10 @@ abstract class SendViewModelBase with Store {
268
return record.name != name ? record : null;
269
}
270
271
+ Future<String> getUnstoppableDomainAddress(String domain) async {
272
+ return await fetchUnstoppableDomainAddress(domain, currency.title.toLowerCase());
273
+ }
274
+
275
@action
276
void _updateFiatAmount() {
277
try {
res/values/strings_de.arb
+4
-1
@@ -469,5 +469,8 @@
469
"unconfirmed" : "Unbestätigt",
470
"displayable" : "Anzeigebar",
471
472
- "submit_request" : "Einen Antrag stellen"
472
+ "submit_request" : "Einen Antrag stellen",
473
+
474
+ "address_detected" : "Adresse erkannt",
475
+ "address_from_domain" : "Sie haben die Adresse von der unaufhaltsamen Domain ${domain} erhalten"
476
}
\ No newline at end of file
res/values/strings_en.arb
+4
-1
@@ -469,5 +469,8 @@
469
"unconfirmed" : "Unconfirmed",
470
"displayable" : "Displayable",
471
472
- "submit_request" : "submit a request"
472
+ "submit_request" : "submit a request",
473
+
474
+ "address_detected" : "Address detected",
475
+ "address_from_domain" : "You got address from unstoppable domain ${domain}"
476
}
\ No newline at end of file
res/values/strings_es.arb
+4
-1
@@ -469,5 +469,8 @@
469
"unconfirmed" : "Inconfirmado",
470
"displayable" : "Visualizable",
471
472
- "submit_request" : "presentar una solicitud"
472
+ "submit_request" : "presentar una solicitud",
473
+
474
+ "address_detected" : "Dirección detectada",
475
+ "address_from_domain" : "Tienes la dirección de unstoppable domain ${domain}"
476
}
\ No newline at end of file
res/values/strings_hi.arb
+4
-1
@@ -469,5 +469,8 @@
469
"unconfirmed" : "अपुष्ट",
470
"displayable" : "प्रदर्शन योग्य",
471
472
- "submit_request" : "एक अनुरोध सबमिट करें"
472
+ "submit_request" : "एक अनुरोध सबमिट करें",
473
+
474
+ "address_detected" : "पता लग गया",
475
+ "address_from_domain" : "आपको अजेय डोमेन ${domain} से पता मिला है"
476
}
\ No newline at end of file
res/values/strings_ja.arb
+4
-1
@@ -469,5 +469,8 @@
469
"unconfirmed" : "未確認",
470
"displayable" : "表示可能",
471
472
- "submit_request" : "リクエストを送信する"
472
+ "submit_request" : "リクエストを送信する",
473
+
474
+ "address_detected" : "アドレスが検出されました",
475
+ "address_from_domain" : "あなたはからアドレスを得ました unstoppable domain ${domain}"
476
}
\ No newline at end of file
res/values/strings_ko.arb
+4
-1
@@ -469,5 +469,8 @@
469
"unconfirmed" : "미확인",
470
"displayable" : "표시 가능",
471
472
- "submit_request" : "요청을 제출"
472
+ "submit_request" : "요청을 제출",
473
+
474
+ "address_detected" : "주소 감지",
475
+ "address_from_domain" : "주소는 unstoppable domain ${domain}"
476
}
\ No newline at end of file
res/values/strings_nl.arb
+4
-1
@@ -469,5 +469,8 @@
469
"unconfirmed" : "Niet bevestigd",
470
"displayable" : "Weer te geven",
471
472
- "submit_request" : "een verzoek indienen"
472
+ "submit_request" : "een verzoek indienen",
473
+
474
+ "address_detected" : "Adres gedetecteerd",
475
+ "address_from_domain" : "Je adres is van unstoppable domain ${domain}"
476
}
\ No newline at end of file
res/values/strings_pl.arb
+4
-1
@@ -469,5 +469,8 @@
469
"unconfirmed" : "Niepotwierdzony",
470
"displayable" : "Wyświetlane",
471
472
- "submit_request" : "złożyć wniosek"
472
+ "submit_request" : "złożyć wniosek",
473
+
474
+ "address_detected" : "Wykryto adres",
475
+ "address_from_domain" : "Dostałeś adres od unstoppable domain ${domain}"
476
}
\ No newline at end of file
res/values/strings_pt.arb
+4
-1
@@ -469,5 +469,8 @@
469
"unconfirmed" : "Não confirmado",
470
"displayable" : "Exibível",
471
472
- "submit_request" : "enviar um pedido"
472
+ "submit_request" : "enviar um pedido",
473
+
474
+ "address_detected" : "Endereço detectado",
475
+ "address_from_domain" : "Você obteve o endereço de unstoppable domain ${domain}"
476
}
\ No newline at end of file
res/values/strings_ru.arb
+4
-1
@@ -469,5 +469,8 @@
469
"unconfirmed" : "Неподтвержденный",
470
"displayable" : "Отображаемый",
471
472
- "submit_request" : "отправить запрос"
472
+ "submit_request" : "отправить запрос",
473
+
474
+ "address_detected" : "Обнаружен адрес",
475
+ "address_from_domain" : "Вы получили адрес из unstoppable domain ${domain}"
476
}
\ No newline at end of file
res/values/strings_uk.arb
+4
-1
@@ -469,5 +469,8 @@
469
"unconfirmed" : "Непідтверджений",
470
"displayable" : "Відображуваний",
471
472
- "submit_request" : "надіслати запит"
472
+ "submit_request" : "надіслати запит",
473
+
474
+ "address_detected" : "Виявлено адресу",
475
+ "address_from_domain" : "Ви отримали адресу від unstoppable domain ${domain}"
476
}
\ No newline at end of file
res/values/strings_zh.arb
+4
-1
@@ -469,5 +469,8 @@
469
"unconfirmed" : "未经证实",
470
"displayable" : "可显示",
471
472
- "submit_request" : "提交請求"
472
+ "submit_request" : "提交請求",
473
+
474
+ "address_detected" : "檢測到地址",
475
+ "address_from_domain" : "您有以下地址 unstoppable domain ${domain}"
476
}
\ No newline at end of file