From b196ed2bf1bda966ef77c1712380fdc987fff1a0 Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 14 Jun 2022 21:55:33 +0200 Subject: [PATCH] check online indexer on startup^in bootstrap nodes; Don't use it in app if offline --- config/indexer_endpoints.json | 4 + lib/globals.dart | 2 + lib/main.dart | 15 +- lib/providers/duniter_indexer.dart | 170 ++++++++++++++++++++++ lib/providers/wallet_options.dart | 64 +------- lib/screens/home.dart | 4 + lib/screens/myWallets/wallet_options.dart | 5 +- lib/screens/myWallets/wallets_home.dart | 5 +- pubspec.yaml | 5 +- 9 files changed, 207 insertions(+), 67 deletions(-) create mode 100644 config/indexer_endpoints.json create mode 100644 lib/providers/duniter_indexer.dart diff --git a/config/indexer_endpoints.json b/config/indexer_endpoints.json new file mode 100644 index 0000000..9e8dc83 --- /dev/null +++ b/config/indexer_endpoints.json @@ -0,0 +1,4 @@ +[ + "https://duniter-indexer.coinduf.eu/v1/graphql", + "http://192.168.1.72:8080/v1/graphql" +] diff --git a/lib/globals.dart b/lib/globals.dart index 74b5b32..ba6d8d4 100644 --- a/lib/globals.dart +++ b/lib/globals.dart @@ -51,3 +51,5 @@ String currencyName = 'ĞD'; // Debug const debugPin = true; + +String indexerEndpoint = ''; diff --git a/lib/main.dart b/lib/main.dart index 3f348e4..c56bff1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -23,6 +23,7 @@ import 'package:gecko/providers/cesium_plus.dart'; import 'package:gecko/models/chest_data.dart'; import 'package:gecko/providers/chest_provider.dart'; import 'package:gecko/models/g1_wallets_list.dart'; +import 'package:gecko/providers/duniter_indexer.dart'; import 'package:gecko/providers/generate_wallets.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/wallets_profiles.dart'; @@ -56,6 +57,7 @@ Future main() async { } HomeProvider _homeProvider = HomeProvider(); + DuniterIndexer _duniterIndexer = DuniterIndexer(); await _homeProvider.initHive(); appVersion = await _homeProvider.getAppVersion(); prefs = await SharedPreferences.getInstance(); @@ -80,8 +82,10 @@ Future main() async { } // log.d(await configBox.get('endpoint')); - // const indexerEndpoint = "http://192.168.1.72:8080/v1/graphql"; - const indexerEndpoint = "https://duniter-indexer.coinduf.eu/v1/graphql"; + await _duniterIndexer.getValidIndexerEndpoint(); + // _duniterIndexer.indexerEndpoint = "http://192.168.1.72:8080/v1/graphql"; + // _duniterIndexer.indexerEndpoint = + // "https://duniter-indexer.coinduf.eu/v1/graphql"; HttpOverrides.global = MyHttpOverrides(); @@ -99,7 +103,7 @@ Future main() async { await SentryFlutter.init((options) { options.dsn = 'https://c09587b46eaa42e8b9fda28d838ed180@o496840.ingest.sentry.io/5572110'; - }, appRunner: () => runApp(const Gecko(indexerEndpoint))); + }, appRunner: () => runApp(Gecko(indexerEndpoint))); // runZoned>( // () async { @@ -116,7 +120,7 @@ Future main() async { } else { print('Debug mode enabled: No sentry alerte'); - runApp(const Gecko(indexerEndpoint)); + runApp(Gecko(indexerEndpoint)); } } @@ -149,7 +153,8 @@ class Gecko extends StatelessWidget { ChangeNotifierProvider(create: (_) => WalletOptionsProvider()), ChangeNotifierProvider(create: (_) => SearchProvider()), ChangeNotifierProvider(create: (_) => CesiumPlusProvider()), - ChangeNotifierProvider(create: (_) => SubstrateSdk()) + ChangeNotifierProvider(create: (_) => SubstrateSdk()), + ChangeNotifierProvider(create: (_) => DuniterIndexer()) ], child: GraphQLProvider( client: _client, diff --git a/lib/providers/duniter_indexer.dart b/lib/providers/duniter_indexer.dart new file mode 100644 index 0000000..952f2ce --- /dev/null +++ b/lib/providers/duniter_indexer.dart @@ -0,0 +1,170 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:gecko/globals.dart'; +import 'package:gecko/models/queries_indexer.dart'; +import 'package:gecko/models/wallet_data.dart'; +import 'package:gecko/providers/wallet_options.dart'; +import 'package:graphql_flutter/graphql_flutter.dart'; +import 'package:provider/provider.dart'; + +class DuniterIndexer with ChangeNotifier { + Map walletNameIndexer = {}; + + void reload() { + notifyListeners(); + } + + Future checkIndexerEndpoint() async { + final oldEndpoint = indexerEndpoint; + while (true) { + await Future.delayed(const Duration(seconds: 30)); + final _client = HttpClient(); + _client.connectionTimeout = const Duration(milliseconds: 1000); + try { + final request = await _client.postUrl(Uri.parse(oldEndpoint)); + final response = await request.close(); + if (response.statusCode != 200) { + log.d('INDEXER IS OFFILINE'); + indexerEndpoint = ''; + } else { + // log.d('Indexer is online'); + indexerEndpoint = oldEndpoint; + } + } catch (e) { + log.d('INDEXER IS OFFILINE'); + indexerEndpoint = ''; + } + } + } + + Future getValidIndexerEndpoint() async { + List _listEndpoints = await rootBundle + .loadString('config/indexer_endpoints.json') + .then((jsonStr) => jsonDecode(jsonStr)); + // _listEndpoints.shuffle(); + + int i = 0; + // String _endpoint = ''; + int _statusCode = 0; + + final _client = HttpClient(); + _client.connectionTimeout = const Duration(milliseconds: 1000); + + do { + int listLenght = _listEndpoints.length; + if (i >= listLenght) { + log.e('NO VALID INDEXER ENDPOINT FOUND'); + indexerEndpoint = ''; + break; + } + log.d( + (i + 1).toString() + 'n indexer endpoint try: ${_listEndpoints[i]}'); + + if (i != 0) { + await Future.delayed(const Duration(milliseconds: 300)); + } + + try { + final request = await _client.postUrl(Uri.parse(_listEndpoints[i])); + final response = await request.close(); + + indexerEndpoint = _listEndpoints[i]; + _statusCode = response.statusCode; + i++; + } on TimeoutException catch (_) { + log.e('This endpoint is timeout, next'); + _statusCode = 50; + i++; + continue; + } on SocketException catch (_) { + log.e('This endpoint is a bad endpoint, next'); + _statusCode = 70; + i++; + continue; + } on Exception { + log.e('Unknown error'); + _statusCode = 60; + i++; + continue; + } + } while (_statusCode != 200); + + log.i('INDEXER: ' + indexerEndpoint); + return indexerEndpoint; + } + + Widget getNameByAddress(BuildContext context, String address, + [WalletData? wallet, + double size = 20, + bool canEdit = false, + Color _color = Colors.black, + FontWeight fontWeight = FontWeight.w400, + FontStyle fontStyle = FontStyle.italic]) { + WalletOptionsProvider _walletOptions = + Provider.of(context, listen: false); + log.d('iiiiiiiiiiiiiiiiiiiiiii $indexerEndpoint'); + if (indexerEndpoint == '') { + if (wallet == null) { + return const SizedBox(); + } else { + if (canEdit) { + return _walletOptions.walletName(context, wallet, size, _color); + } else { + return _walletOptions.walletNameController(context, wallet, size); + } + } + } + + return Query( + options: QueryOptions( + document: gql( + getNameByAddressQ), // this is the query string you just created + variables: { + 'address': address, + }, + // pollInterval: const Duration(seconds: 10), + ), + builder: (QueryResult result, + {VoidCallback? refetch, FetchMore? fetchMore}) { + if (result.hasException) { + return Text(result.exception.toString()); + } + + if (result.isLoading) { + return const Text('Loading'); + } + + walletNameIndexer[address] = + result.data?['account_by_pk']?['identity']?['name']; + + if (walletNameIndexer[address] == null) { + if (wallet == null) { + return const SizedBox(); + } else { + if (canEdit) { + return _walletOptions.walletName(context, wallet, size, _color); + } else { + return _walletOptions.walletNameController( + context, wallet, size); + } + } + } + + return Text( + _color == Colors.grey[700]! + ? '(${walletNameIndexer[address]!})' + : walletNameIndexer[address]!, + style: TextStyle( + fontSize: size, + color: _color, + fontWeight: fontWeight, + fontStyle: fontStyle, + ), + ); + }); + } +} diff --git a/lib/providers/wallet_options.dart b/lib/providers/wallet_options.dart index 5474836..1270bbf 100644 --- a/lib/providers/wallet_options.dart +++ b/lib/providers/wallet_options.dart @@ -2,7 +2,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'dart:async'; import 'package:gecko/globals.dart'; -import 'package:gecko/models/queries_indexer.dart'; +import 'package:gecko/providers/duniter_indexer.dart'; import 'package:gecko/providers/my_wallets.dart'; import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/providers/substrate_sdk.dart'; @@ -10,7 +10,6 @@ import 'package:gecko/screens/animated_text.dart'; import 'package:gecko/screens/common_elements.dart'; import 'package:gecko/screens/myWallets/unlocking_wallet.dart'; import 'package:gecko/screens/transaction_in_progress.dart'; -import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:image_picker/image_picker.dart'; import 'package:provider/provider.dart'; import 'package:image_cropper/image_cropper.dart'; @@ -27,7 +26,6 @@ class WalletOptionsProvider with ChangeNotifier { TextEditingController nameController = TextEditingController(); late bool isDefaultWallet; bool canValidateNameBool = false; - Map walletNameIndexer = {}; Future? get badWallet => null; @@ -130,6 +128,9 @@ class WalletOptionsProvider with ChangeNotifier { Widget idtyStatus(BuildContext context, String address, {bool isOwner = false, Color color = Colors.black}) { +DuniterIndexer _duniterIndexer = + Provider.of(context, listen: false); + _showText(String text, [double size = 18, bool _bold = false, bool smooth = true]) { log.d(text); @@ -175,7 +176,7 @@ class WalletOptionsProvider with ChangeNotifier { { return isOwner ? _showText('Identité confirmé') - : getNameByAddress(context, address, null, 20, true, + : _duniterIndexer.getNameByAddress(context, address, null, 20, true, Colors.grey[700]!, FontWeight.w500, FontStyle.italic); } @@ -183,7 +184,7 @@ class WalletOptionsProvider with ChangeNotifier { { return isOwner ? _showText('Membre validé !', 18, true) - : getNameByAddress(context, address, null, 20, true, + : _duniterIndexer.getNameByAddress(context, address, null, 20, true, Colors.black, FontWeight.w600, FontStyle.normal); } @@ -430,60 +431,7 @@ class WalletOptionsProvider with ChangeNotifier { return _address; } - Widget getNameByAddress(BuildContext context, String address, - [WalletData? wallet, - double size = 20, - bool canEdit = false, - Color _color = Colors.black, - FontWeight fontWeight = FontWeight.w400, - FontStyle fontStyle = FontStyle.italic]) { - return Query( - options: QueryOptions( - document: gql( - getNameByAddressQ), // this is the query string you just created - variables: { - 'address': address, - }, - // pollInterval: const Duration(seconds: 10), - ), - builder: (QueryResult result, - {VoidCallback? refetch, FetchMore? fetchMore}) { - if (result.hasException) { - return Text(result.exception.toString()); - } - if (result.isLoading) { - return const Text('Loading'); - } - - walletNameIndexer[address] = - result.data?['account_by_pk']?['identity']?['name']; - - if (walletNameIndexer[address] == null) { - if (wallet == null) { - return const SizedBox(); - } else { - if (canEdit) { - return walletName(context, wallet, size, _color); - } else { - return walletNameController(context, wallet, size); - } - } - } - - return Text( - _color == Colors.grey[700]! - ? '(${walletNameIndexer[address]!})' - : walletNameIndexer[address]!, - style: TextStyle( - fontSize: size, - color: _color, - fontWeight: fontWeight, - fontStyle: fontStyle, - ), - ); - }); - } Widget walletNameController(BuildContext context, WalletData wallet, [double size = 20]) { diff --git a/lib/screens/home.dart b/lib/screens/home.dart index fd6fd27..899c14a 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -3,6 +3,7 @@ import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:gecko/globals.dart'; import 'package:gecko/models/stateful_wrapper.dart'; import 'package:gecko/providers/chest_provider.dart'; +import 'package:gecko/providers/duniter_indexer.dart'; import 'package:gecko/providers/home.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/wallets_profiles.dart'; @@ -145,6 +146,9 @@ class HomeScreen extends StatelessWidget { } }); } + DuniterIndexer _duniterIndexer = + Provider.of(ctx, listen: false); + _duniterIndexer.checkIndexerEndpoint(); }); }, child: isWalletsExists ? geckHome(context) : welcomeHome(context) diff --git a/lib/screens/myWallets/wallet_options.dart b/lib/screens/myWallets/wallet_options.dart index 0800784..907dbe8 100644 --- a/lib/screens/myWallets/wallet_options.dart +++ b/lib/screens/myWallets/wallet_options.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:gecko/globals.dart'; +import 'package:gecko/providers/duniter_indexer.dart'; import 'package:gecko/providers/home.dart'; import 'package:gecko/providers/my_wallets.dart'; import 'package:gecko/models/wallet_data.dart'; @@ -31,6 +32,8 @@ class WalletOptions extends StatelessWidget { Provider.of(context, listen: false); HomeProvider _homeProvider = Provider.of(context, listen: false); + DuniterIndexer _duniterIndexer = + Provider.of(context, listen: false); log.d(_walletOptions.address.text); @@ -100,7 +103,7 @@ class WalletOptions extends StatelessWidget { Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - _walletOptions.getNameByAddress( + _duniterIndexer.getNameByAddress( context, walletProvider.address.text, wallet, diff --git a/lib/screens/myWallets/wallets_home.dart b/lib/screens/myWallets/wallets_home.dart index 80b8344..e1b2a79 100644 --- a/lib/screens/myWallets/wallets_home.dart +++ b/lib/screens/myWallets/wallets_home.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/services.dart'; import 'package:gecko/globals.dart'; import 'package:gecko/models/chest_data.dart'; +import 'package:gecko/providers/duniter_indexer.dart'; import 'package:gecko/providers/home.dart'; import 'package:gecko/providers/my_wallets.dart'; import 'package:gecko/models/wallet_data.dart'; @@ -136,6 +137,8 @@ class WalletsHome extends StatelessWidget { Provider.of(context); WalletOptionsProvider _walletOptions = Provider.of(context, listen: false); + DuniterIndexer _duniterIndexer = + Provider.of(context, listen: false); final bool isWalletsExists = _myWalletProvider.checkIfWalletExist(); if (!isWalletsExists) { @@ -263,7 +266,7 @@ class WalletsHome extends StatelessWidget { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 5), - child: _walletOptions.getNameByAddress( + child: _duniterIndexer.getNameByAddress( context, _repository.address!, _repository, diff --git a/pubspec.yaml b/pubspec.yaml index a74dd68..8a4784b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ description: Pay with G1. # pub.dev using `pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 0.0.9+1 +version: 0.0.9+2 environment: sdk: '>=2.12.0 <3.0.0' @@ -29,6 +29,7 @@ dependencies: flutter_logs: ^2.1.4 flutter_svg: ^0.22.0 graphql_flutter: ^5.1.1-beta.3 + hive: ^2.0.4 hive_flutter: ^1.1.0 http: ^0.13.4 @@ -98,7 +99,7 @@ flutter: assets: - images/ - - config/gdev_endpoints.json + - config/ - assets/ - assets/home/ - assets/avatars/