@playlive/react-pipeline
    Preparing search index...

    Function usePipelineDonationSum

    • Reduce the WebSocket-driven donations[campaignID] slice into a per-currency sum inside a caller-supplied [start, end) window.

      Overlays that display "$X raised this block" for a per-streamer schedule item historically polled GET /schedules/campaigns/{id}/raised every 30 s. That endpoint sums tiltify_campaign_donations — the same table saveDonation() writes to inside handleTiltifyWebhookData, right before the handler fans the donation out over the WebSocket firehose as public:direct:donation_updated. The store's _processDonation action pushes every such donation onto donations[campaign_id], so overlays already carry a stream of every donation that would ever count toward the sum.

      This hook closes the loop: pass the REST endpoint's asOf timestamp as options.start and the block's ends_at as options.end, and the returned raised value is the pure post-baseline delta. Combine it with the baseline scalar to get a live block total that updates on every donation without a fetch.

      • Donations are matched inclusively against start and exclusively against end (i.e. start <= completed_at < end), matching the REST endpoint's SQL completed_at BETWEEN start AND end when paired with an asOf-based start.
      • Donations with an unparseable completed_at are dropped.
      • Donations are de-duplicated by id so a Tiltify re-delivery of the same donation_updated event doesn't double-count. The last-seen amount wins so post-edit corrections propagate.
      • Test donations (test: true) are excluded unless PipelineDonationSumOptions.includeTest is set — see the option's JSDoc for why.
      • When options.currency is set, only matching donations are counted and both raised and currency are scalar. Otherwise raised collapses to the sole currency present in the window, or null when multiple currencies appear.
      • An empty window returns raised: 0, currency: null, donationCount: 0, byCurrency: [] — same shape as the REST endpoint's empty-window response.

      The underlying donations[campaignID] reference is only replaced when a new donation lands (Zustand + spread semantics inside _processDonation), so the enclosing useMemo re-runs at most once per incoming donation for a given (start, end, currency, includeTest) tuple.

      Parameters

      Returns PipelineDonationSumResult

      const { data: baseline } = useQuery({ queryKey: ["block-raised", ...], queryFn });
      const delta = usePipelineDonationSum(campaignID, {
      start: baseline?.asOf,
      end: scheduleItem.ends_at,
      currency: baseline?.currency ?? undefined,
      });
      const raised = (baseline?.raised ?? 0) + (delta.raised ?? 0);