handleEventBroadcast method

  1. @override
NdkBroadcastResponse handleEventBroadcast({
  1. required Nip01Event nostrEvent,
  2. required EventSigner? signer,
  3. required BroadcastState broadcastState,
  4. Iterable<String>? specificRelays,
})
override

Implementation

@override
NdkBroadcastResponse handleEventBroadcast({
  required Nip01Event nostrEvent,
  required EventSigner? signer,
  required BroadcastState broadcastState,
  Iterable<String>? specificRelays,
}) {
  Future<void> asyncStuff() async {
    final Nip01Event workingEvent;

    try {
      if (signer != null) {
        workingEvent = await signer.sign(nostrEvent);
      } else {
        workingEvent = nostrEvent;
      }
    } catch (e, stackTrace) {
      broadcastState.addError(e, stackTrace);
      return;
    }
    broadcastState.startTimeout();

    // =====================================================================================
    // specific relays
    // =====================================================================================
    if (specificRelays != null) {
      if (specificRelays.isNotEmpty) {
        await Future.wait(
          specificRelays.map(
            (relayUrl) =>
                // broadcast async
                doRelayBroadcast(relayUrl, workingEvent),
          ),
        );
      }
    } else {
      // =====================================================================================
      // own outbox
      // =====================================================================================
      // TODO should not only depend on cached, but go fetch it if not present in cache
      final nip65List = (await UserRelayLists.getUserRelayListCacheLatest(
        pubkeys: [workingEvent.pubKey],
        cacheManager: _cacheManager,
      ));
      // make a copy of the keys since connectRelay may mutate the underlying map
      List<String> writeRelaysUrls = _relayManager.globalState.relays.keys
          .toList();
      if (nip65List.isNotEmpty) {
        writeRelaysUrls = nip65List.first.relays.entries
            .where((element) => element.value.isWrite)
            .map((e) => e.key)
            .toList();
      } else {
        Logger.log.w(
          () =>
              "could not find user relay list from nip65, using default bootstrap relays",
        );
      }

      await Future.wait(
        writeRelaysUrls.map(
          (relayUrl) => doRelayBroadcast(relayUrl, workingEvent),
        ),
      );

      // =====================================================================================
      // other inbox
      // =====================================================================================
      if (workingEvent.pTags.isNotEmpty) {
        final nip65Data = await UserRelayLists.getUserRelayListCacheLatest(
          pubkeys: workingEvent.pTags,
          cacheManager: _cacheManager,
        );

        List<String> myWriteRelayUrlsOthers = [];

        /// filter read relays
        for (final userNip65 in nip65Data) {
          final completeList = userNip65.relays.entries
              .where((element) => element.value.isRead)
              .map((e) => e.key)
              .toList();

          // cut list of at a certain threshold
          final maxList = completeList.sublist(
            0,
            min(
              completeList.length,
              BroadcastDefaults.MAX_INBOX_RELAYS_TO_BROADCAST,
            ),
          );
          myWriteRelayUrlsOthers.addAll(maxList);
        }

        await Future.wait(
          myWriteRelayUrlsOthers.map(
            (relayUrl) => doRelayBroadcast(relayUrl, workingEvent),
          ),
        );
      }
    }
    broadcastState.closeIfNoRelays();
  }

  asyncStuff();

  return NdkBroadcastResponse(
    publishEvent: nostrEvent,
    broadcastDoneStream: broadcastState.stateUpdates.map(
      (state) => state.broadcasts.values.toList(),
    ),
    broadcastDoneFuture: broadcastState.publishDoneFuture.then(
      (state) => state.broadcasts.values.toList(),
    ),
  );
}