Skip to content
This repository has been archived by the owner on Oct 4, 2024. It is now read-only.

Commit

Permalink
Unmock internal calls (#188)
Browse files Browse the repository at this point in the history
* unmock internal calls

* remove unexistent rpc method

* put internal calls behind feature flag

* polish front
  • Loading branch information
igamigo authored Sep 22, 2023
1 parent f028e41 commit 1eb4dd1
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 47 deletions.
65 changes: 64 additions & 1 deletion lib/starknet_explorer/data.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule StarknetExplorer.Data do
require Logger
alias StarknetExplorer.{Rpc, Transaction, Block, TransactionReceipt, Calldata}
alias StarknetExplorer.{Rpc, Transaction, Block, TransactionReceipt, Calldata, Gateway}
alias StarknetExplorerWeb.Utils

@common_event_hash_to_name %{
Expand Down Expand Up @@ -270,4 +270,67 @@ defmodule StarknetExplorer.Data do
|> Map.get("abi")
|> _get_event_name(event_name_hashed)
end

def internal_calls(tx, network) do
{:ok, trace} = Gateway.trace_transaction(tx.hash, network)

trace["function_invocation"]
|> StarknetExplorerWeb.Utils.atomize_keys()
|> flatten_internal_calls(0)
|> Enum.with_index()
|> Enum.map(fn {call_data, index} ->
# TODO: this can be optimized because we are going out to the Rpc/DB for every call, but contracts might be repeated
# (like in the case of CALL and DELEGATE call types) so those can be coalesced
input_data =
Calldata.get_input_data(
"latest",
call_data.contract_address,
call_data.selector,
network
)

call_data =
Map.put(
call_data,
:selector_name,
input_data["name"] || default_internal_call_name(tx.type)
)

{index, call_data}
end)
|> Map.new()
end

defp default_internal_call_name(tx_type) do
case tx_type do
"L1_HANDLER" -> "handle_deposit"
"DEPLOY_ACCOUNT" -> "constructor"
_ -> "__execute__"
end
end

defp flatten_internal_calls(%{internal_calls: inner_list_of_calls} = outer_map, height)
when is_list(inner_list_of_calls) do
outer_details = [
%{
call_type: outer_map.call_type,
contract_address: outer_map.contract_address,
caller_address: outer_map.caller_address,
selector: Map.get(outer_map, :selector),
scope: height
}
]

inner_details = Enum.flat_map(inner_list_of_calls, &flatten_internal_calls(&1, height + 1))

outer_details ++ inner_details
end

defp flatten_internal_calls(%{internal_calls: []} = _outer_map, _height) do
[]
end

defp flatten_internal_calls(list, _height) when is_list(list) do
[]
end
end
133 changes: 87 additions & 46 deletions lib/starknet_explorer_web/live/transaction_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,16 @@ defmodule StarknetExplorerWeb.TransactionLive do
>
Message Logs
</div>
<div
class={"option #{if assigns.transaction_view == "internal_calls", do: "lg:!border-b-se-blue", else: "lg:border-b-transparent"}"}
phx-click="select-view"
,
phx-value-view="internal_calls"
>
Internal Calls <span class="gray-label text-sm">Mocked</span>
</div>
<%= if @internal_calls != nil do %>
<div
class={"option #{if assigns.transaction_view == "internal_calls", do: "lg:!border-b-se-blue", else: "lg:border-b-transparent"}"}
phx-click="select-view"
,
phx-value-view="internal_calls"
>
Internal Calls
</div>
<% end %>
</div>
"""
end
Expand Down Expand Up @@ -290,43 +292,68 @@ defmodule StarknetExplorerWeb.TransactionLive do

def render_info(%{transaction_view: "internal_calls"} = assigns) do
~H"""
<div class="grid-5 table-th !pt-7 border-t border-gray-700">
<div>Identifier</div>
<div>Transaction Hash</div>
<div>Type</div>
<div>Name</div>
<div>Contract Address</div>
</div>
<div class="grid-5 custom-list-item">
<div>
<div class="list-h">Identifier</div>
<div>
<%= "0x008e571d599345e12730f53df66cf74bea8ad238d68844b71ebadb567eae7a1d"
|> Utils.shorten_block_hash() %>
</div>
</div>
<div>
<div class="list-h">Transaction Hash</div>
<div>
<%= "0x008e571d599345e12730f53df66cf74bea8ad238d68844b71ebadb567eae7a1d"
|> Utils.shorten_block_hash() %>
</div>
</div>
<div>
<div class="list-h">Type</div>
<div><span class="lilac-label">Call</span></div>
</div>
<div>
<div class="list-h">Name</div>
<div><span class="green-label">__execute__</span></div>
<div class="table-block">
<div class="grid-5 table-th !pt-7 border-t border-gray-700">
<div>Identifier</div>
<div>Transaction Hash</div>
<div>Type</div>
<div>Name</div>
<div>Contract Address</div>
</div>
<div>
<div class="list-h">Contract Address</div>
<div>
<%= "0x008e571d599345e12730f53df66cf74bea8ad238d68844b71ebadb567eae7a1d"
|> Utils.shorten_block_hash() %>
<%= for {index, call} <- @internal_calls do %>
<div class="grid-5 custom-list-item">
<div>
<div class="list-h">Identifier</div>
<div>
<%= "#{@transaction.hash}_#{call.scope}_#{index}" |> Utils.shorten_block_hash() %>
</div>
</div>
<div>
<div class="list-h">Transaction Hash</div>
<div>
<%= @transaction.hash
|> Utils.shorten_block_hash() %>
</div>
</div>
<div>
<div class="list-h">Type</div>
<div>
<%= if call.call_type=="CALL" do %>
<span class="green-label"><%= call.call_type %></span>
<% else %>
<span class="lilac-label"><%= call.call_type %></span>
<% end %>
</div>
</div>
<div>
<div class="list-h">Name</div>
<div><span class="blue-label"><%= call.selector_name %></span></div>
</div>
<div
class="copy-container"
id={"tsx-internal-calls-hash-#{call.contract_address}"}
phx-hook="Copy"
>
<div class="relative break-all text-hover-blue">
<%= call.contract_address
|> Utils.shorten_block_hash() %>
<div class="absolute top-1/2 -right-6 tranform -translate-y-1/2">
<div class="relative">
<img
class="copy-btn copy-text w-4 h-4"
src={~p"/images/copy.svg"}
data-text={call.contract_address}
/>
<img
class="copy-check absolute top-0 left-0 w-4 h-4 opacity-0 pointer-events-none"
src={~p"/images/check-square.svg"}
/>
</div>
</div>
</div>
</div>
</div>
</div>
<% end %>
</div>
"""
end
Expand Down Expand Up @@ -371,9 +398,15 @@ defmodule StarknetExplorerWeb.TransactionLive do
<div class="grid-4 custom-list-item">
<div class="block-label">Status</div>
<div class="col-span-3">
<span class={"#{if @transaction_receipt.finality_status == "ACCEPTED_ON_L2", do: "green-label"} #{if @transaction_receipt.finality_status == "ACCEPTED_ON_L1", do: "blue-label"} #{if @transaction_receipt.finality_status == "PENDING", do: "pink-label"}"}>
<%= @transaction_receipt.finality_status %>
</span>
<%= if @transaction_receipt.execution_status == "REVERTED" do %>
<span class="pink-label">
REVERTED
</span>
<% else %>
<span class={"#{if @transaction_receipt.finality_status == "ACCEPTED_ON_L2", do: "green-label"} #{if @transaction_receipt.finality_status == "ACCEPTED_ON_L1", do: "blue-label"} #{if @transaction_receipt.finality_status == "PENDING", do: "pink-label"}"}>
<%= @transaction_receipt.finality_status %>
</span>
<% end %>
</div>
</div>
<div class="grid-4 custom-list-item">
Expand Down Expand Up @@ -593,10 +626,18 @@ defmodule StarknetExplorerWeb.TransactionLive do

receipt = transaction.receipt |> Map.put(:actual_fee, actual_fee)

internal_calls =
case receipt.execution_status != "REVERTED" &&
Application.get_env(:starknet_explorer, :enable_gateway_data) do
true -> Data.internal_calls(transaction, socket.assigns.network)
_ -> nil
end

assigns = [
transaction: transaction,
transaction_receipt: receipt,
transaction_hash: transaction_hash,
internal_calls: internal_calls,
transaction_view: "overview",
events: receipt.events,
messages: messages_sent,
Expand Down
3 changes: 3 additions & 0 deletions lib/starknet_gateway.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ defmodule StarknetExplorer.Gateway do
def fetch_block(block_number, network) when is_integer(block_number),
do: get_block_request(%{blockNumber: block_number}, network)

def trace_transaction(transaction_hash, network),
do: gateway_request("get_transaction_trace", %{transactionHash: transaction_hash}, network)

defp get_block_request(query, network), do: gateway_request("get_block", query, network)

defp gateway_request(method, query, network) do
Expand Down

0 comments on commit 1eb4dd1

Please sign in to comment.