From 3b3ea4c654a926f9be54d8acc5da1ab8a58529d1 Mon Sep 17 00:00:00 2001 From: hswick Date: Fri, 4 May 2018 23:28:02 -0500 Subject: [PATCH] Added typespecs and docs to methods --- lib/exw3.ex | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/lib/exw3.ex b/lib/exw3.ex index 1954321..a9b6da2 100644 --- a/lib/exw3.ex +++ b/lib/exw3.ex @@ -1,5 +1,7 @@ defmodule ExW3 do + @spec bytes_to_string(binary()) :: binary() + @doc "converts Ethereum style bytes to string" def bytes_to_string bytes do bytes |> Base.encode16(case: :lower) @@ -7,6 +9,8 @@ defmodule ExW3 do |> Base.decode16!(case: :lower) end + @spec accounts() :: list() + @doc "returns all available accounts" def accounts do case Ethereumex.HttpClient.eth_accounts() do {:ok, accounts} -> accounts @@ -14,13 +18,16 @@ defmodule ExW3 do end end - # Converts ethereum hex string to decimal number + @spec to_decimal(binary()) :: number() + @doc "Converts ethereum hex string to decimal number" def to_decimal(hex_string) do hex_string |> String.slice(2..-1) |> String.to_integer(16) end + @spec block_number() :: integer() + @doc "Returns the current block number" def block_number do case Ethereumex.HttpClient.eth_block_number() do {:ok, block_number} -> @@ -31,6 +38,8 @@ defmodule ExW3 do end end + @spec balance(binary()) :: integer() + @doc "Returns current balance of account" def balance(account) do case Ethereumex.HttpClient.eth_get_balance(account) do {:ok, balance} -> @@ -41,6 +50,7 @@ defmodule ExW3 do end end + @spec keys_to_decimal(%{}, []) :: %{} def keys_to_decimal(map, keys) do Map.new( Enum.map(keys, fn k -> @@ -49,6 +59,8 @@ defmodule ExW3 do ) end + @spec tx_receipt(binary()) :: %{} + @doc "Returns transaction receipt for specified transaction hash(id)" def tx_receipt(tx_hash) do case Ethereumex.HttpClient.eth_get_transaction_receipt(tx_hash) do {:ok, receipt} -> @@ -59,6 +71,8 @@ defmodule ExW3 do end end + @spec block(integer()) :: any() + @doc "Returns block data for specified block number" def block(block_number) do case Ethereumex.HttpClient.eth_get_block_by_number(block_number, true) do {:ok, block} -> block @@ -66,16 +80,22 @@ defmodule ExW3 do end end + @spec mine(integer()) :: any() + @doc "Mines number of blocks specified. Default is 1" def mine(num_blocks \\ 1) do for _ <- 0..(num_blocks - 1) do Ethereumex.HttpClient.request("evm_mine", [], []) end end + @spec encode_event(binary()) :: binary() + @doc "Encodes event based on signature" def encode_event(signature) do ExthCrypto.Hash.Keccak.kec(signature) |> Base.encode16(case: :lower) end + @spec decode_event(binary(), binary()) :: any() + @doc "Decodes event based on given data and provided signature" def decode_event(data, signature) do formatted_data = data @@ -87,10 +107,14 @@ defmodule ExW3 do ABI.TypeDecoder.decode(formatted_data, fs) end + @spec reformat_abi([]) :: %{} + @doc "Reformats abi from list to map with event and function names as keys" def reformat_abi(abi) do Map.new(Enum.map(abi, fn x -> {x["name"], x} end)) end + @spec load_abi(binary()) :: [] + @doc "Loads the abi at the file path and reformats it to a map" def load_abi(file_path) do file = File.read(Path.join(System.cwd(), file_path)) @@ -100,6 +124,8 @@ defmodule ExW3 do end end + @spec load_bin(binary()) :: binary() + @doc "Loads the bin ar the file path" def load_bin(file_path) do file = File.read(Path.join(System.cwd(), file_path)) @@ -109,6 +135,8 @@ defmodule ExW3 do end end + @spec decode_output(%{}, binary(), binary()) :: [] + @doc "Decodes output based on specified functions return signature" def decode_output(abi, name, output) do {:ok, trim_output} = String.slice(output, 2..String.length(output)) |> Base.decode16(case: :lower) @@ -124,12 +152,16 @@ defmodule ExW3 do outputs end + @spec types_signature(%{}, binary()) :: binary() + @doc "Returns the type signature of a given function" def types_signature(abi, name) do input_types = Enum.map(abi[name]["inputs"], fn x -> x["type"] end) types_signature = Enum.join(["(", Enum.join(input_types, ","), ")"]) types_signature end + @spec method_signature(%{}, binary()) :: binary() + @doc "Returns the 4 character method id based on the hash of the method signature" def method_signature(abi, name) do if abi[name] do input_signature = "#{name}#{types_signature(abi, name)}" |> ExthCrypto.Hash.Keccak.kec() @@ -142,6 +174,8 @@ defmodule ExW3 do end end + @spec encode_data(binary(), []) :: binary() + @doc "Encodes data into Ethereum hex string based on types signature" def encode_data(types_signature, data) do ABI.TypeEncoder.encode_raw( [List.to_tuple(data)], @@ -149,11 +183,15 @@ defmodule ExW3 do ) end + @spec encode_method_call(%{}, binary(), []) :: binary() + @doc "Encodes data and appends it to the encoded method id" def encode_method_call(abi, name, input) do encoded_method_call = method_signature(abi, name) <> encode_data(types_signature(abi, name), input) encoded_method_call |> Base.encode16(case: :lower) end + @spec encode_input(%{}, binary(), []) :: binary() + @doc "Encodes input from a method call based on function signature" def encode_input(abi, name, input) do if abi[name]["inputs"] do input_types = Enum.map(abi[name]["inputs"], fn x -> x["type"] end) @@ -181,30 +219,44 @@ defmodule ExW3 do # Client + @spec start_link(atom(), list()) :: {:ok, pid()} + @doc "Begins a Contract GenServer with specified name and state" def start_link(name, state) do GenServer.start_link(__MODULE__, state, name: name) end + @spec deploy(pid(), []) :: {:ok, []} + @doc "Deploys contracts with given arguments" def deploy(pid, args) do GenServer.call(pid, {:deploy, args}) end + @spec at(pid(), binary()) :: :ok + @doc "Sets the current Contract GenServer's address to given address" def at(pid, address) do GenServer.cast(pid, {:at, address}) end + @spec address(pid()) :: {:ok, binary()} + @doc "Returns the current Contract GenServer's address" def address(pid) do GenServer.call(pid, :address) end + @spec call(pid(), keyword(), []) :: {:ok, any()} + @doc "Use a Contract's method with an eth_call" def call(pid, method_name, args \\ []) do GenServer.call(pid, {:call, {method_name, args}}) end + @spec send(pid(), keyword(), [], %{}) :: {:ok, binary()} + @doc "Use a Contract's method with an eth_sendTransaction" def send(pid, method_name, args, options) do GenServer.call(pid, {:send, {method_name, args, options}}) end + @spec tx_receipt(pid(), binary()) :: %{} + @doc "Returns a formatted transaction receipt for the given transaction hash(id)" def tx_receipt(pid, tx_hash) do GenServer.call(pid, {:tx_receipt, tx_hash}) end