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()),
  );
}