Added ability sending to FIO address (#370)

* Added ability sending to FIO address * remove apiKey property * fix conditions for FIO address checking

Serhii committed Jun 13, 2022 at 14:41 UTC fc58972bf90ace1aceaa782c433a574f82fc2189
4 files changed +81 -1
lib/entities/fio_address_provider.dart new
+57
@@ -0,0 +1,57 @@
1 +import 'dart:convert';
2 +
3 +import 'package:http/http.dart' as http;
4 +
5 +class FioAddressProvider {
6 + static const apiAuthority = 'fio.blockpane.com';
7 + static const availCheck = '/v1/chain/avail_check';
8 + static const getAddress = '/v1/chain/get_pub_address';
9 +
10 + static Future<bool> checkAvail(String fioAddress) async {
11 + bool isFioRegistered = false;
12 + final headers = {'Content-Type': 'application/json'};
13 + final body = <String, String>{"fio_name": fioAddress};
14 +
15 + final uri = Uri.https(apiAuthority, availCheck);
16 + final response =
17 + await http.post(uri, headers: headers, body: json.encode(body));
18 +
19 + if (response.statusCode != 200) {
20 + return isFioRegistered;
21 + }
22 +
23 + final responseJSON = json.decode(response.body) as Map<String, dynamic>;
24 + isFioRegistered = responseJSON['is_registered'] as int == 1;
25 +
26 + return isFioRegistered;
27 + }
28 +
29 + static Future<String> getPubAddress(String fioAddress, String token) async {
30 + final headers = {'Content-Type': 'application/json'};
31 + final body = <String, String>{
32 + "fio_address": fioAddress,
33 + "chain_code": token.toUpperCase(),
34 + "token_code": token.toUpperCase(),
35 + };
36 +
37 + final uri = Uri.https(apiAuthority, getAddress);
38 + final response =
39 + await http.post(uri, headers: headers, body: json.encode(body));
40 +
41 + if (response.statusCode == 400) {
42 + final responseJSON = json.decode(response.body) as Map<String, dynamic>;
43 + final error = responseJSON['error'] as String;
44 + final message = responseJSON['message'] as String;
45 + throw Exception('${error}\n$message');
46 + }
47 +
48 + if (response.statusCode != 200) {
49 + return null;
50 + }
51 +
52 + final responseJSON = json.decode(response.body) as Map<String, dynamic>;
53 + final String pubAddress = responseJSON['public_address'] as String;
54 +
55 + return pubAddress;
56 + }
57 +}
lib/entities/parse_address_from_domain.dart
+9
@@ -4,6 +4,7 @@ import 'package:cake_wallet/entities/parsed_address.dart';
4 import 'package:cake_wallet/entities/unstoppable_domain_address.dart';
5 import 'package:cake_wallet/entities/emoji_string_extension.dart';
6 import 'package:flutter/foundation.dart';
7 +import 'package:cake_wallet/entities/fio_address_provider.dart';
8
9 class AddressResolver {
10
@@ -26,6 +27,14 @@ class AddressResolver {
27
28 Future<ParsedAddress> resolve(String text, String ticker) async {
29 try {
30 + if (text.contains('@') && !text.contains('.')) {
31 + final bool isFioRegistered = await FioAddressProvider.checkAvail(text);
32 + if (isFioRegistered) {
33 + final address = await FioAddressProvider.getPubAddress(text, ticker);
34 + return ParsedAddress.fetchFioAddress(address: address, name: text);
35 + }
36 +
37 + }
38 if (text.hasOnlyEmojis) {
39 final addresses = await yatService.fetchYatAddress(text, ticker);
40 return ParsedAddress.fetchEmojiAddress(addresses: addresses, name: text);
lib/entities/parsed_address.dart
+10 -1
@@ -2,7 +2,7 @@ import 'package:cake_wallet/entities/openalias_record.dart';
2 import 'package:cake_wallet/entities/yat_record.dart';
3 import 'package:flutter/material.dart';
4
5 -enum ParseFrom { unstoppableDomains, openAlias, yatRecord, notParsed }
5 +enum ParseFrom { unstoppableDomains, openAlias, yatRecord, fio, notParsed }
6
7 class ParsedAddress {
8 ParsedAddress({
@@ -58,4 +58,13 @@ class ParsedAddress {
58 parseFrom: ParseFrom.openAlias,
59 );
60 }
61 +
62 + factory ParsedAddress.fetchFioAddress({@required String address, @required String name}){
63 +
64 + return ParsedAddress(
65 + addresses: [address],
66 + name: name,
67 + parseFrom: ParseFrom.fio,
68 + );
69 + }
70 }
lib/src/screens/send/widgets/extract_address_from_parsed.dart
+5
@@ -23,6 +23,11 @@ Future<String> extractAddressFromParsed(
23 content = S.of(context).openalias_alert_content(parsedAddress.name);
24 address = parsedAddress.addresses.first;
25 break;
26 + case ParseFrom.fio:
27 + title = S.of(context).address_detected;
28 + content = S.of(context).openalias_alert_content(parsedAddress.name);
29 + address = parsedAddress.addresses.first;
30 + break;
31 case ParseFrom.yatRecord:
32 if (parsedAddress.name.isEmpty) {
33 title = S.of(context).yat_error;