diff --git a/lib/g1/api.dart b/lib/g1/api.dart index ac8d9fc0355ce63154a91b33f279170b769d29c2..5e8aaf1b543853ecf95c724477870d20c0f617f9 100644 --- a/lib/g1/api.dart +++ b/lib/g1/api.dart @@ -50,11 +50,45 @@ Future<String> getTxHistory(String publicKey) async { } } -Future<Response> getPeers() async { - final Response response = (await requestWithRetry( - NodeType.duniter, '/network/peers', - dontRecord: true)) - .item2; +Future<List<dynamic>> getPeers(NodeType type) async { + final List<Node> nodes = NodeManager().nodeList(type); + loggerDev('Fetching ${type.name} peers with peers ${nodes.length}'); + List<dynamic> currentPeers = <dynamic>[]; + for (final Node node in nodes) { + String nodeUrl = node.url; + nodeUrl = nodeUrl.replaceAll(RegExp(r'/gva$'), ''); + nodeUrl = '$nodeUrl/network/peers'; + loggerDev('Fetching $nodeUrl'); + try { + final Response response = await http.get(Uri.parse(nodeUrl)); + if (response.statusCode == 200) { + // Try decode + final Map<String, dynamic> peerList = + jsonDecode(response.body) as Map<String, dynamic>; + final List<dynamic> peers = (peerList['peers'] as List<dynamic>) + .where((dynamic peer) => + (peer as Map<String, dynamic>)['currency'] == currency) + .where((dynamic peer) => + (peer as Map<String, dynamic>)['version'] == 10) + .where((dynamic peer) => + (peer as Map<String, dynamic>)['status'] == 'UP') + .toList(); + if (currentPeers.length < peers.length) { + // sometimes getPeers returns a small list of nodes (somethmes even one) + currentPeers = peers; + } + } + } catch (e) { + loggerDev('Error retrieving $nodeUrl ($e)'); + // Ignore + } + } + return currentPeers; +} + +Future<Response> getPeersOld(NodeType type) async { + final Response response = + (await requestWithRetry(type, '/network/peers', dontRecord: true)).item2; if (response.statusCode == 200) { return response; } else { @@ -269,6 +303,20 @@ Future<void> _fetchDuniterNodes({bool force = false}) async { NodeManager().loading = false; } +Future<void> _fetchGvaNodes({bool force = false}) async { + NodeManager().loading = true; + const NodeType type = NodeType.gva; + if (force) { + NodeManager().updateNodes(type, defaultGvaNodes); + logger('Fetching gva nodes forced'); + } else { + logger('Fetching gva nodes, we have ${NodeManager().nodesWorking(type)}'); + } + final List<Node> nodes = await _fetchDuniterNodesFromPeers(type); + NodeManager().updateNodes(type, nodes); + NodeManager().loading = false; +} + // https://github.com/duniter/cesium/blob/467ec68114be650cd1b306754c3142fc4020164c/www/js/config.js#L96 // https://g1.data.le-sou.org/g1/peer/_search?pretty Future<void> _fetchCesiumPlusNodes({bool force = false}) async { @@ -286,20 +334,6 @@ Future<void> _fetchCesiumPlusNodes({bool force = false}) async { NodeManager().loading = false; } -Future<void> _fetchGvaNodes({bool force = false}) async { - NodeManager().loading = true; - const NodeType type = NodeType.gva; - if (force) { - NodeManager().updateNodes(type, defaultGvaNodes); - logger('Fetching gva nodes forced'); - } else { - logger('Fetching gva nodes, we have ${NodeManager().nodesWorking(type)}'); - } - final List<Node> nodes = await _fetchDuniterNodesFromPeers(type); - NodeManager().updateNodes(type, nodes); - NodeManager().loading = false; -} - Future<void> _fetchEndPointNodes({bool force = false}) async { NodeManager().loading = true; const NodeType type = NodeType.endpoint; @@ -339,66 +373,54 @@ Future<List<Node>> _fetchDuniterNodesFromPeers(NodeType type, String? fastestNode; late Duration fastestLatency = const Duration(minutes: 1); try { - final Response response = await getPeers(); - if (response.statusCode == 200) { - final Map<String, dynamic> peerList = - jsonDecode(response.body) as Map<String, dynamic>; - final List<dynamic> peers = (peerList['peers'] as List<dynamic>) - .where((dynamic peer) => - (peer as Map<String, dynamic>)['currency'] == currency) - .where( - (dynamic peer) => (peer as Map<String, dynamic>)['version'] == 10) - .where((dynamic peer) => - (peer as Map<String, dynamic>)['status'] == 'UP') - .toList(); - // reorder peer list - peers.shuffle(); - for (final dynamic peerR in peers) { - final Map<String, dynamic> peer = peerR as Map<String, dynamic>; - if (peer['endpoints'] != null) { - final List<String> endpoints = - List<String>.from(peer['endpoints'] as List<dynamic>); - for (int j = 0; j < endpoints.length; j++) { - if (endpoints[j].startsWith(apyType)) { - final String endpointUnParsed = endpoints[j]; - final String? endpoint = parseHost(endpointUnParsed); - if (endpoint != null && - // !endpoint.contains('test') && - !endpoint.contains('localhost')) { - try { - final NodeCheck nodeCheck = await _pingNode(endpoint, type); - final Duration latency = nodeCheck.latency; - loggerD(debug, - 'Evaluating node: $endpoint, latency ${latency.inMicroseconds} currentBlock: ${nodeCheck.currentBlock}'); - final Node node = Node( - url: endpoint, - latency: latency.inMicroseconds, - currentBlock: nodeCheck.currentBlock); - if (fastestNode == null || latency < fastestLatency) { - fastestNode = endpoint; - fastestLatency = latency; - if (!kReleaseMode) { - loggerD( - debug, 'Node bloc: Current faster node $fastestNode'); - } - NodeManager().insertNode(type, node); - lNodes.insert(0, node); - } else { - // Not the faster - NodeManager().addNode(type, node); - lNodes.add(node); + final List<dynamic> peers = await getPeers(type); + // reorder peer list + peers.shuffle(); + for (final dynamic peerR in peers) { + final Map<String, dynamic> peer = peerR as Map<String, dynamic>; + if (peer['endpoints'] != null) { + final List<String> endpoints = + List<String>.from(peer['endpoints'] as List<dynamic>); + for (int j = 0; j < endpoints.length; j++) { + if (endpoints[j].startsWith(apyType)) { + final String endpointUnParsed = endpoints[j]; + final String? endpoint = parseHost(endpointUnParsed); + if (endpoint != null && + // !endpoint.contains('test') && + !endpoint.contains('localhost')) { + try { + final NodeCheck nodeCheck = await _pingNode(endpoint, type); + final Duration latency = nodeCheck.latency; + loggerD(debug, + 'Evaluating node: $endpoint, latency ${latency.inMicroseconds} currentBlock: ${nodeCheck.currentBlock}'); + final Node node = Node( + url: endpoint, + latency: latency.inMicroseconds, + currentBlock: nodeCheck.currentBlock); + if (fastestNode == null || latency < fastestLatency) { + fastestNode = endpoint; + fastestLatency = latency; + if (!kReleaseMode) { + loggerD( + debug, 'Node bloc: Current faster node $fastestNode'); } - } catch (e) { - logger('Error fetching $endpoint, error: $e'); + NodeManager().insertNode(type, node); + lNodes.insert(0, node); + } else { + // Not the faster + NodeManager().addNode(type, node); + lNodes.add(node); } + } catch (e) { + logger('Error fetching $endpoint, error: $e'); } } } - if (kReleaseMode && lNodes.length >= NodeManager.maxNodes) { - // In production dont' get too much nodes - loggerD(debug, 'We have enough ${type.name} nodes for now'); - break; - } + } + if (kReleaseMode && lNodes.length >= NodeManager.maxNodes) { + // In production dont' get too much nodes + loggerD(debug, 'We have enough ${type.name} nodes for now'); + break; } } }