From fa9e97cb919bf5bdda2e946b87e12b567d8e0f95 Mon Sep 17 00:00:00 2001 From: Nicky Dev Date: Mon, 26 Aug 2024 01:51:43 +0700 Subject: [PATCH 1/5] fix: resolve issue with sendCountEventToRelays not working --- lib/nostr/model/count.dart | 24 +++++++++++++++++++++--- lib/nostr/service/registry.dart | 6 +++--- pubspec.yaml | 2 +- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/lib/nostr/model/count.dart b/lib/nostr/model/count.dart index d981237..047ef63 100644 --- a/lib/nostr/model/count.dart +++ b/lib/nostr/model/count.dart @@ -56,14 +56,18 @@ class NostrCountResponse extends Equatable { assert(countMap is Map); return NostrCountResponse( - subscriptionId: decodedData[1] as String, - count: int.parse(countMap['count'] as String), + subscriptionId: parseString(decodedData[1]) ?? '', + count: parseInt(countMap['count']) ?? 0, ); } final String subscriptionId; final int count; @override - List get props => throw UnimplementedError(); + List get props => [ + 'COUNT', + subscriptionId, + {'count': count}, + ]; static bool canBeDeserialized(String data) { final decodedData = jsonDecode(data); @@ -84,3 +88,17 @@ class NostrCountResponse extends Equatable { } } } + +String? parseString(dynamic data) { + return (data ?? '') != '' ? data.toString() : null; +} + +int? parseInt(dynamic data) { + if (data is double) { + return data.toInt(); + } else if (data is int) { + return data; + } else { + return int.tryParse(data.toString()); + } +} diff --git a/lib/nostr/service/registry.dart b/lib/nostr/service/registry.dart index 36a6a04..ac992af 100644 --- a/lib/nostr/service/registry.dart +++ b/lib/nostr/service/registry.dart @@ -163,9 +163,9 @@ class NostrRegistry { onCountResponse, required String relay, }) { - final relayCountRegister = countResponseCallBacks[subscriptionId]; - - relayCountRegister?[subscriptionId] = onCountResponse; + final relayCountRegister = + getOrCreateRegister(countResponseCallBacks, relay); + relayCountRegister[subscriptionId] = onCountResponse; } /// Returns a count response callback from the registry with the given [subscriptionId]. diff --git a/pubspec.yaml b/pubspec.yaml index 69f9112..df75c84 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: dart_nostr description: Develop Scalable Dart/Flutter Nostr clients quickly and easily -version: 8.2.0 +version: 8.2.1 repository: https://github.com/anasfik/nostr/ environment: From 7c16a45778ebb6db53154adb8b0a8eac8b7ade71 Mon Sep 17 00:00:00 2001 From: Nicky Dev Date: Mon, 2 Sep 2024 21:27:07 +0700 Subject: [PATCH 2/5] fix: can't specific subscriptionId in to NostrRequest --- lib/nostr/model/request/request.dart | 19 ++++++++++--------- pubspec.yaml | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/nostr/model/request/request.dart b/lib/nostr/model/request/request.dart index cccf939..8c6df26 100644 --- a/lib/nostr/model/request/request.dart +++ b/lib/nostr/model/request/request.dart @@ -27,14 +27,15 @@ class NostrRequest extends Equatable { /// Serialize the request to send it to the remote relays websockets. String serialized({String? subscriptionId}) { - this.subscriptionId = subscriptionId ?? - this.subscriptionId ?? - Nostr.instance.utilsService.consistent64HexChars( - filters - .map((e) => e.toMap().toString()) - .reduce((value, element) => value + element), - ); - + if (this.subscriptionId == null) { + this.subscriptionId = subscriptionId ?? + this.subscriptionId ?? + Nostr.instance.utilsService.consistent64HexChars( + filters + .map((e) => e.toMap().toString()) + .reduce((value, element) => value + element), + ); + } //! The old way of doing it is commented below // final decodedFilters = // jsonEncode(filters.map((item) => item.toMap()).toList()); @@ -44,7 +45,7 @@ class NostrRequest extends Equatable { final encodedReq = jsonEncode([ NostrConstants.request, - subscriptionId, + this.subscriptionId, ...filters.map((e) => e.toMap()), ]); diff --git a/pubspec.yaml b/pubspec.yaml index df75c84..f65e1f4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: dart_nostr description: Develop Scalable Dart/Flutter Nostr clients quickly and easily -version: 8.2.1 +version: 8.2.2 repository: https://github.com/anasfik/nostr/ environment: From ee84103498bd0d865e511cb4fe7451786ccd3535 Mon Sep 17 00:00:00 2001 From: Nicky Dev Date: Wed, 4 Sep 2024 23:26:32 +0700 Subject: [PATCH 3/5] fix: ensure _startConnectingAndRegisteringRelays uses connectionTimeout --- lib/nostr/instance/relays/relays.dart | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/nostr/instance/relays/relays.dart b/lib/nostr/instance/relays/relays.dart index b8601ba..535fa21 100644 --- a/lib/nostr/instance/relays/relays.dart +++ b/lib/nostr/instance/relays/relays.dart @@ -851,7 +851,7 @@ class NostrRelays implements NostrRelaysBase { required bool shouldReconnectToRelayOnNotice, required Duration connectionTimeout, }) async { - final completer = Completer(); + final completers = >{}; for (final relay in relaysUrl) { if (nostrRegistry.isRelayRegisteredAndConnectedSuccesfully(relay)) { @@ -861,9 +861,14 @@ class NostrRelays implements NostrRelaysBase { continue; } - try { - await webSocketsService.connectRelay( + final completer = Completer(); + completer.future.timeout( + connectionTimeout, + ); + completers[relay] = completer; + // ignore: unawaited_futures + webSocketsService.connectRelay( relay: relay, onConnectionSuccess: (relayWebSocket) { nostrRegistry.registerRelayWebSocket( @@ -891,16 +896,24 @@ class NostrRelays implements NostrRelaysBase { lazyListeningToRelays: lazyListeningToRelays, ); } + completer.complete(relay); }, ); } catch (e) { onRelayConnectionError?.call(relay, e, null); } } - - completer.complete(); - - return completer.future; + await Future.wait( + completers.keys.map( + (key) => completers[key]! + .future + .timeout(connectionTimeout) + .catchError((err) { + onRelayConnectionError?.call(key, err, null); + return null; + }), + ), + ); } bool _filterNostrEventsWithId( From 3e18784cdb5d77e04a24759fbbbff122bade2616 Mon Sep 17 00:00:00 2001 From: Nicky Dev Date: Thu, 5 Sep 2024 00:49:41 +0700 Subject: [PATCH 4/5] fix: relay init and registerEvent --- lib/nostr/instance/relays/relays.dart | 32 +++++++++++++++++++-------- lib/nostr/service/registry.dart | 14 ++++++++++-- pubspec.yaml | 2 +- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/lib/nostr/instance/relays/relays.dart b/lib/nostr/instance/relays/relays.dart index 535fa21..b021d34 100644 --- a/lib/nostr/instance/relays/relays.dart +++ b/lib/nostr/instance/relays/relays.dart @@ -24,6 +24,9 @@ class NostrRelays implements NostrRelaysBase { nostrRegistry = NostrRegistry(utils: utils); } + /// The list of relay urls that failed to connect + final List failureRelaysList = []; + /// Represents a registry of all relays that you did registered with the [init] method. @override Map get relaysWebSocketsRegistry => @@ -853,23 +856,24 @@ class NostrRelays implements NostrRelaysBase { }) async { final completers = >{}; - for (final relay in relaysUrl) { + for (final relay in relaysUrl.toList()) { + if (failureRelaysList.contains(relay)) { + continue; + } if (nostrRegistry.isRelayRegisteredAndConnectedSuccesfully(relay)) { utils.log( 'relay with url: $relay is already connected successfully, skipping...', ); - continue; } + final completer = Completer(); try { - final completer = Completer(); - completer.future.timeout( - connectionTimeout, - ); completers[relay] = completer; // ignore: unawaited_futures - webSocketsService.connectRelay( + webSocketsService + .connectRelay( relay: relay, + shouldIgnoreConnectionException: false, onConnectionSuccess: (relayWebSocket) { nostrRegistry.registerRelayWebSocket( relayUrl: relay, @@ -898,9 +902,16 @@ class NostrRelays implements NostrRelaysBase { } completer.complete(relay); }, + ) + .catchError( + (err) { + onRelayConnectionError?.call(relay, err, null); + completer.completeError(Exception()); + }, ); } catch (e) { onRelayConnectionError?.call(relay, e, null); + completer.completeError(e); } } await Future.wait( @@ -908,8 +919,11 @@ class NostrRelays implements NostrRelaysBase { (key) => completers[key]! .future .timeout(connectionTimeout) - .catchError((err) { - onRelayConnectionError?.call(key, err, null); + .onError((e, stack) { + if (!failureRelaysList.contains(key)) { + failureRelaysList.add(key); + } + onRelayConnectionError?.call(key, e, null); return null; }), ), diff --git a/lib/nostr/service/registry.dart b/lib/nostr/service/registry.dart index ac992af..b836a1d 100644 --- a/lib/nostr/service/registry.dart +++ b/lib/nostr/service/registry.dart @@ -91,9 +91,19 @@ class NostrRegistry { /// Registers an event to the registry with the given [event]. NostrEvent registerEvent(NostrEvent event) { - eventsRegistry[eventUniqueId(event)] = event; + final uniqueId = eventUniqueId(event); + final compareDate = event.createdAt != null + ? eventsRegistry[uniqueId]?.createdAt?.compareTo(event.createdAt!) + : null; + if (eventsRegistry.containsKey(uniqueId)) { + if (compareDate != null && compareDate < 0) { + eventsRegistry[uniqueId] = event; + } + } else { + eventsRegistry[uniqueId] = event; + } - return eventsRegistry[eventUniqueId(event)]!; + return eventsRegistry[uniqueId]!; } /// REturns an [event] unique id, See also [NostrEvent.uniqueKey]. diff --git a/pubspec.yaml b/pubspec.yaml index f65e1f4..0dc493a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: dart_nostr description: Develop Scalable Dart/Flutter Nostr clients quickly and easily -version: 8.2.2 +version: 8.2.3 repository: https://github.com/anasfik/nostr/ environment: From d0a58fe37fee376a4098f52c6b2ed5c77af7a484 Mon Sep 17 00:00:00 2001 From: Nicky Dev Date: Tue, 10 Sep 2024 13:08:01 +0700 Subject: [PATCH 5/5] upgrade version bip340 to 0.3.0 --- lib/nostr/core/key_pairs.dart | 2 +- pubspec.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/nostr/core/key_pairs.dart b/lib/nostr/core/key_pairs.dart index a1f27ee..8086237 100644 --- a/lib/nostr/core/key_pairs.dart +++ b/lib/nostr/core/key_pairs.dart @@ -50,7 +50,7 @@ class NostrKeyPairs extends Equatable { String message, String signature, ) { - return bip340.verify(pubkey, message, signature); + return bip340.verify(pubkey!, message, signature); } static bool isValidPrivateKey(String privateKey) { diff --git a/pubspec.yaml b/pubspec.yaml index 0dc493a..86a3464 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,13 +1,13 @@ name: dart_nostr description: Develop Scalable Dart/Flutter Nostr clients quickly and easily -version: 8.2.3 +version: 8.2.4 repository: https://github.com/anasfik/nostr/ environment: sdk: ">=3.0.0 <=3.9.9" dependencies: - bip340: ^0.1.0 + bip340: '0.3.0' equatable: ^2.0.5 convert: ^3.1.1 crypto: ^3.0.2