diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/stats_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/stats_controller.ex index c044d63c2..76749b864 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/stats_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/stats_controller.ex @@ -26,7 +26,7 @@ defmodule BlockScoutWeb.API.V2.StatsController do alias Explorer.Chain.Cache.{ChainId, GasPriceOracle, GolemBase.UsedSlots} alias Explorer.Chain.Cache.Counters.{AddressesCount, AverageBlockTime, BlocksCount, GasUsageSum, TransactionsCount} alias Explorer.Chain.GolemBase - alias Explorer.Chain.GolemBase.Entity + alias Explorer.Chain.GolemBase.{Entity, Operation} alias Explorer.Chain.Supply.RSK alias Explorer.Chain.Transaction.History.TransactionStats alias Explorer.Stats.HotSmartContracts @@ -131,7 +131,12 @@ defmodule BlockScoutWeb.API.V2.StatsController do "golembase_storage_limit" => get_golembase_storage_limit(), "golembase_used_slots" => get_golembase_used_slots(), "golembase_active_entities_size" => get_golembase_active_entities_size(), - "golembase_active_entities_count" => get_golembase_active_entities_count() + "golembase_active_entities_count" => get_golembase_active_entities_count(), + "golembase_total_operations" => get_golembase_total_operations(), + "golembase_unique_active_addresses" => get_golembase_unique_active_addresses(), + "golembase_total_entities_created" => get_golembase_total_entities_created(), + "golembase_entities_deleted" => get_golembase_entities_deleted(), + "golembase_entities_expired" => get_golembase_entities_expired() }) else stats @@ -363,6 +368,26 @@ defmodule BlockScoutWeb.API.V2.StatsController do Entity.active_entities_count() end + defp get_golembase_total_operations do + Operation.total_operations_count() + end + + defp get_golembase_unique_active_addresses do + Entity.unique_active_addresses_count() + end + + defp get_golembase_total_entities_created do + Entity.total_entities_created() + end + + defp get_golembase_entities_deleted do + Entity.entities_deleted_count() + end + + defp get_golembase_entities_expired do + Entity.entities_expired_count() + end + case @chain_type do :rsk -> defp add_chain_type_fields(response) do diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/stats_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/stats_controller_test.exs index d3c680204..1358163d5 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/stats_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/stats_controller_test.exs @@ -48,6 +48,11 @@ defmodule BlockScoutWeb.API.V2.StatsControllerTest do assert Map.has_key?(response, "golembase_used_slots") assert Map.has_key?(response, "golembase_active_entities_size") assert Map.has_key?(response, "golembase_active_entities_count") + assert Map.has_key?(response, "golembase_total_operations") + assert Map.has_key?(response, "golembase_unique_active_addresses") + assert Map.has_key?(response, "golembase_total_entities_created") + assert Map.has_key?(response, "golembase_entities_deleted") + assert Map.has_key?(response, "golembase_entities_expired") end end end diff --git a/apps/explorer/lib/explorer/chain/golem_base/entity.ex b/apps/explorer/lib/explorer/chain/golem_base/entity.ex index ecd91bc35..9894a6440 100644 --- a/apps/explorer/lib/explorer/chain/golem_base/entity.ex +++ b/apps/explorer/lib/explorer/chain/golem_base/entity.ex @@ -78,6 +78,54 @@ defmodule Explorer.Chain.GolemBase.Entity do def active_entities_count do query = from(entity in __MODULE__, where: entity.status == :active, select: count()) - Repo.one(query) + Repo.one(query) || 0 + end + + @doc """ + Returns the count of unique addresses owning at least one active entity. + + Counts distinct owner addresses for entities with `:active` status. + """ + def unique_active_addresses_count do + query = + from(entity in __MODULE__, + where: entity.status == :active, + select: count(entity.owner, :distinct) + ) + + Repo.one(query) || 0 + end + + @doc """ + Returns the total count of all entities created (cumulative, including inactive). + + Counts all entities regardless of status. + """ + def total_entities_created do + query = from(entity in __MODULE__, select: count()) + + Repo.one(query) || 0 + end + + @doc """ + Returns the count of entities with deleted status. + + Counts all entities with `:deleted` status. + """ + def entities_deleted_count do + query = from(entity in __MODULE__, where: entity.status == :deleted, select: count()) + + Repo.one(query) || 0 + end + + @doc """ + Returns the count of entities with expired status. + + Counts all entities with `:expired` status. + """ + def entities_expired_count do + query = from(entity in __MODULE__, where: entity.status == :expired, select: count()) + + Repo.one(query) || 0 end end diff --git a/apps/explorer/lib/explorer/chain/golem_base/operation.ex b/apps/explorer/lib/explorer/chain/golem_base/operation.ex index 2eb38ea29..514199c78 100644 --- a/apps/explorer/lib/explorer/chain/golem_base/operation.ex +++ b/apps/explorer/lib/explorer/chain/golem_base/operation.ex @@ -3,8 +3,10 @@ defmodule Explorer.Chain.GolemBase.Operation do The representation of a Golem Base operation. """ + import Ecto.Query, only: [from: 2] + use Explorer.Schema - alias Explorer.Chain.Hash + alias Explorer.{Chain.Hash, Repo} @primary_key false typed_schema "golem_base_operations" do @@ -29,4 +31,15 @@ defmodule Explorer.Chain.GolemBase.Operation do |> cast(attrs, [:entity_key, :sender, :recipient, :operation, :block_hash, :transaction_hash, :index, :data, :btl]) |> validate_required([:entity_key, :sender, :recipient, :operation, :block_hash, :transaction_hash, :index]) end + + @doc """ + Returns the total count of all operations. + + Counts all Create, Update, Delete, and Extend operations. + """ + def total_operations_count do + query = from(operation in __MODULE__, select: count()) + + Repo.one(query) || 0 + end end