lib/slurpee_web/live/home_live.ex

defmodule SlurpeeWeb.HomeLive do
  use SlurpeeWeb, :live_view

  @impl true
  def mount(_params, _session, socket) do
    Phoenix.PubSub.subscribe(Slurpee.PubSub, "events:event_received")
    Phoenix.PubSub.subscribe(Slurpee.PubSub, "recent_heads:new_head_received")
    Phoenix.PubSub.subscribe(Slurpee.PubSub, "blockchain_statistics:new_stats")
    stats = Slurpee.BlockchainStatistics.get()

    socket =
      socket
      |> assign(last_head_received_at: stats.last_head_received_at)
      |> assign(block_cadence_seconds: stats.block_cadence_seconds)
      |> assign(events_per_second: stats.events_per_second)
      |> assign(recent_blocks: Slurpee.RecentHeads.queue())
      |> assign(recent_events: Slurpee.RecentEvents.queue())

    {:ok, socket}
  end

  @impl true
  def handle_info(
        {"events:event_received", blockchain_id, block_number, block_hash, address, event},
        socket
      ) do
    recent_events =
      socket.assigns.recent_events
      |> Deque.appendleft({blockchain_id, block_number, block_hash, address, event})

    socket =
      socket
      |> assign(recent_events: recent_events)

    {:noreply, socket}
  end

  @impl true
  def handle_info({"recent_heads:new_head_received", recent_heads}, socket) do
    socket =
      socket
      |> assign(recent_blocks: recent_heads)

    {:noreply, socket}
  end

  @impl true
  def handle_info(
        {"blockchain_statistics:new_stats", stats},
        socket
      ) do
    socket =
      socket
      |> assign(last_head_received_at: stats.last_head_received_at)
      |> assign(block_cadence_seconds: stats.block_cadence_seconds)
      |> assign(events_per_second: stats.events_per_second)

    {:noreply, socket}
  end

  defp last_head_received_at(nil), do: nil

  defp last_head_received_at(received_at) when is_integer(received_at) do
    received_latency =
      System.convert_time_unit(System.monotonic_time() - received_at, :native, :millisecond)

    unix_now = "Etc/UTC" |> DateTime.now!() |> DateTime.to_unix(:millisecond)
    unix_now - received_latency
  end

  defp format_event_attr(value) when is_binary(value) and byte_size(value) == 20 do
    value |> Base.encode16(case: :lower) |> ExW3.Utils.to_checksum_address()
  end

  defp format_event_attr(value), do: value |> inspect
end