defmodule Ethex.Abi.Function do @moduledoc """ 0xf167FcA5b9FeDf4E8baCAf8547225af93832ed6F https://matic-mumbai.chainstacklabs.com Ethex.call "https://matic-mumbai.chainstacklabs.com", "erc20", "0xf167FcA5b9FeDf4E8baCAf8547225af93832ed6F", "symbol" Ethex.call "https://matic-mumbai.chainstacklabs.com", "erc20", "0xf167FcA5b9FeDf4E8baCAf8547225af93832ed6F", "balanceOf", ["8CcF629e123D83112423c283998443829A291334" |> Base.decode16!(case: :mixed)] """ alias Ethex.Abi.Abi alias Ethex.Blockchain.StateMethod @doc """ call contract function NOTE: address SHOULD BE binary """ @spec call(String.t(), String.t(), String.t(), String.t(), list()) :: {:ok, list()} | {:error, any()} def call(rpc, abi_name, address, fun_name, args \\ []) do with {:ok, selectors} <- Abi.get_selectors_by_name(abi_name), fs <- find_selector(fun_name, selectors), {:ok, "0x" <> returns} <- StateMethod.eth_call(rpc, %{ to: address, data: "0x#{Base.encode16(ABI.encode(fs, args, :input), case: :lower)}" }) do {:ok, ABI.decode(fs, Base.decode16!(returns, case: :lower), :output)} else {:error, :not_found} -> {:error, :abi_not_register} nil -> {:error, :function_selector_not_found} error -> error end end defp find_selector(fun_name, selectors) do Enum.find(selectors, fn s -> s.type == :function and s.function == fun_name end) end end