diff --git a/lib/fester/indexer.ex b/lib/fester/indexer.ex index 6aa86b8..7d3ecf3 100644 --- a/lib/fester/indexer.ex +++ b/lib/fester/indexer.ex @@ -5,11 +5,21 @@ defmodule Fester.Indexer do alias Fester.Utxo @doc """ - Returns the list of utxos for a given address. + Returns the list of utxos for a given address + optimized for consumption by blaze-query getUnspentOutputs """ def list_utxos_by_address(address) do from(u in Utxo, where: u.address == ^address and is_nil(u.consumed_at_slot)) |> Repo.all() + |> Enum.reduce(%{data: []}, &build_response/2) + end + + defp build_response(%Utxo{utxo_ref: utxo_ref, txout_cbor: cbor}, acc) do + [tx_hash, index] = String.split(utxo_ref, "#") + data = Map.get(acc, :data) + data = [%{tx_hash: tx_hash, index: index, txout_cbor: cbor} | data] + + Map.put(acc, :data, data) end @doc """ diff --git a/lib/fester/indexer/db_indexer.ex b/lib/fester/indexer/db_indexer.ex index 87658ef..9d34ff5 100644 --- a/lib/fester/indexer/db_indexer.ex +++ b/lib/fester/indexer/db_indexer.ex @@ -74,7 +74,7 @@ defmodule Fester.DBIndexer do ) do Logger.info("Processing transaction with collaterals") - %{"collaterals" => collaterals_as_inputs} = transaction + %{"collaterals" => collaterals_as_inputs, "cbor" => cbor} = transaction # Wrapping the collateral return in a list to make it consistent with the # other calling of the process_transaction_outputs function. @@ -82,7 +82,7 @@ defmodule Fester.DBIndexer do if transaction["collateral_return"], do: [transaction["collateral_return"]], else: [] with :ok <- process_transaction_inputs(slot, collaterals_as_inputs), - :ok <- process_transaction_outputs(slot, collateral_return_as_outputs, tx_id) do + :ok <- process_transaction_outputs(slot, collateral_return_as_outputs, tx_id, cbor) do :ok else {:error, reason} -> @@ -95,11 +95,12 @@ defmodule Fester.DBIndexer do %{ "id" => tx_id, "inputs" => inputs, - "outputs" => outputs + "outputs" => outputs, + "cbor" => cbor } = transaction with :ok <- process_transaction_inputs(slot, inputs), - :ok <- process_transaction_outputs(slot, outputs, tx_id) do + :ok <- process_transaction_outputs(slot, outputs, tx_id, cbor) do :ok else {:error, reason} -> @@ -139,7 +140,7 @@ defmodule Fester.DBIndexer do :ok end - defp process_transaction_outputs(slot, outputs, tx_id) do + defp process_transaction_outputs(slot, outputs, tx_id, cbor) do utxo_attrs_list = outputs |> Enum.with_index() @@ -151,6 +152,7 @@ defmodule Fester.DBIndexer do utxo_ref: output_ref, address: address, value: value, + txout_cbor: cbor, created_at_slot: slot } end) diff --git a/lib/fester/utxo.ex b/lib/fester/utxo.ex index 0940ceb..caa516f 100644 --- a/lib/fester/utxo.ex +++ b/lib/fester/utxo.ex @@ -9,6 +9,7 @@ defmodule Fester.Utxo do field :created_at_slot, :integer field :consumed_at_slot, :integer field :value, :map + field :txout_cbor, :string timestamps() end diff --git a/lib/fester_web/controllers/utxos_controller.ex b/lib/fester_web/controllers/utxos_controller.ex new file mode 100644 index 0000000..8c1dcef --- /dev/null +++ b/lib/fester_web/controllers/utxos_controller.ex @@ -0,0 +1,11 @@ +defmodule FesterWeb.UtxosController do + use FesterWeb, :controller + + alias Fester.Indexer + + def index(conn, %{"address" => address}) do + utxos = Indexer.list_utxos_by_address(address) + + json(conn, utxos) + end +end diff --git a/lib/fester_web/router.ex b/lib/fester_web/router.ex index ab6dea1..f7735f8 100644 --- a/lib/fester_web/router.ex +++ b/lib/fester_web/router.ex @@ -10,6 +10,7 @@ defmodule FesterWeb.Router do # Lists assets for an address get "/address/:address/assets", AssetsController, :index + get "/address/:address/utxos", UtxosController, :index end # Enable Swoosh mailbox preview in development diff --git a/priv/repo/migrations/20251021210246_add_txout_cbor_to_utxos.exs b/priv/repo/migrations/20251021210246_add_txout_cbor_to_utxos.exs new file mode 100644 index 0000000..541bd6f --- /dev/null +++ b/priv/repo/migrations/20251021210246_add_txout_cbor_to_utxos.exs @@ -0,0 +1,9 @@ +defmodule Fester.Repo.Migrations.AddTxoutCborToUtxos do + use Ecto.Migration + + def change do + alter table(:utxos) do + add :txout_cbor, :text, null: false + end + end +end