From 8278f6073903d015c538a57aedba96b76e79979c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20Mo=C5=A1i=C4=87?= Date: Thu, 11 Apr 2019 14:38:23 +0100 Subject: [PATCH 1/3] Add dialyxir to deps and ignore warnings from dependencies --- mix.exs | 6 +++++- mix.lock | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index 907cf88..3016f77 100644 --- a/mix.exs +++ b/mix.exs @@ -12,7 +12,10 @@ defmodule ExW3.MixProject do description: description(), package: package(), name: "exw3", - source_url: "https://github.com/hswick/exw3" + source_url: "https://github.com/hswick/exw3", + dialyzer: [ + remove_defaults: [:unknown] + ] ] end @@ -37,6 +40,7 @@ defmodule ExW3.MixProject do {:ex_doc, ">= 0.0.0", only: :dev}, {:ethereumex, "~> 0.4.0"}, {:abi, "~> 0.1.8"}, + {:dialyxir, "~> 1.0.0-rc.5", only: [:dev], runtime: false}, {:poison, "~> 4.0.1"} ] end diff --git a/mix.lock b/mix.lock index d187407..1bedce7 100644 --- a/mix.lock +++ b/mix.lock @@ -2,7 +2,9 @@ "abi": {:hex, :abi, "0.1.12", "87ae04cb09e2308db7b3c350584dc3934de0e308f6a056ba82be5756b081a1ca", [:mix], [{:exth_crypto, "~> 0.1.4", [hex: :exth_crypto, repo: "hexpm", optional: false]}], "hexpm"}, "binary": {:hex, :binary, "0.0.5", "20d816f7274ea34f1b673b4cff2fdb9ebec9391a7a68c349070d515c66b1b2cf", [:mix], [], "hexpm"}, "certifi": {:hex, :certifi, "2.4.2", "75424ff0f3baaccfd34b1214184b6ef616d89e420b258bb0a5ea7d7bc628f7f0", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, + "dialyxir": {:hex, :dialyxir, "1.0.0-rc.6", "78e97d9c0ff1b5521dd68041193891aebebce52fc3b93463c0a6806874557d7d", [:mix], [{:erlex, "~> 0.2.1", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm"}, "earmark": {:hex, :earmark, "1.2.6", "b6da42b3831458d3ecc57314dff3051b080b9b2be88c2e5aa41cd642a5b044ed", [:mix], [], "hexpm"}, + "erlex": {:hex, :erlex, "0.2.1", "cee02918660807cbba9a7229cae9b42d1c6143b768c781fa6cee1eaf03ad860b", [:mix], [], "hexpm"}, "ethereumex": {:hex, :ethereumex, "0.4.0", "6ed98639c717dc7940a56f657fb81f44afe3e0287f9825b7b0f9016642e605ac", [:mix], [{:httpoison, "~> 1.3.1", [hex: :httpoison, repo: "hexpm", optional: false]}, {:poison, "~> 4.0.1", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.19.1", "519bb9c19526ca51d326c060cb1778d4a9056b190086a8c6c115828eaccea6cf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.7", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, "exth_crypto": {:hex, :exth_crypto, "0.1.6", "8e636a9bcb75d8e32451be96e547a495121ed2178d078db294edb0f81f7cf2e8", [:mix], [{:binary, "~> 0.0.4", [hex: :binary, repo: "hexpm", optional: false]}, {:keccakf1600, "~> 2.0.0", [hex: :keccakf1600_orig, repo: "hexpm", optional: false]}, {:libsecp256k1, "~> 0.1.9", [hex: :libsecp256k1, repo: "hexpm", optional: false]}], "hexpm"}, From ca31f08e6b74835e08e38256eeef30542bc77263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20Mo=C5=A1i=C4=87?= Date: Thu, 11 Apr 2019 14:38:56 +0100 Subject: [PATCH 2/3] Fix all spec warnings --- lib/exw3.ex | 83 +++++++++++++++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/lib/exw3.ex b/lib/exw3.ex index 127a7bd..5dae5bc 100644 --- a/lib/exw3.ex +++ b/lib/exw3.ex @@ -32,15 +32,18 @@ defmodule ExW3 do :tether => 1_000_000_000_000_000_000_000_000_000_000 } - @client_type Application.get_env(:ethereumex, :client_type, :http) + @spec get_client_type() :: atom() + def get_client_type do + Application.get_env(:ethereumex, :client_type, :http) + end - @spec get_unit_map() :: %{} + @spec get_unit_map() :: map() @doc "Returns the map used for ether unit conversion" def get_unit_map do @unit_map end - @spec to_wei(integer(), keyword()) :: integer() + @spec to_wei(integer(), atom()) :: integer() @doc "Converts the value to whatever unit key is provided. See unit map for details." def to_wei(num, key) do if @unit_map[key] do @@ -50,7 +53,7 @@ defmodule ExW3 do end end - @spec from_wei(integer(), keyword()) :: integer() + @spec from_wei(integer(), atom()) :: integer() | float() | no_return @doc "Converts the value to whatever unit key is provided. See unit map for details." def from_wei(num, key) do if @unit_map[key] do @@ -125,7 +128,7 @@ defmodule ExW3 do end defp call_client(method_name, arguments \\ []) do - case @client_type do + case get_client_type() do :http -> apply(Ethereumex.HttpClient, method_name, arguments) :ipc -> apply(Ethereumex.IpcClient, method_name, arguments) _ -> {:error, :invalid_client_type} @@ -161,7 +164,7 @@ defmodule ExW3 do end end - @spec balance(binary()) :: integer() + @spec balance(binary()) :: integer() | {:error, any()} @doc "Returns current balance of account" def balance(account) do case call_client(:eth_get_balance, [account]) do @@ -173,12 +176,12 @@ defmodule ExW3 do end end - @spec keys_to_decimal(%{}, []) :: %{} + @spec keys_to_decimal(map(), list()) :: map() def keys_to_decimal(map, keys) do for k <- keys, into: %{}, do: {k, map |> Map.get(k) |> to_decimal()} end - @spec tx_receipt(binary()) :: %{} + @spec tx_receipt(binary()) :: {:ok, map()} | {:error, any()} @doc "Returns transaction receipt for specified transaction hash(id)" def tx_receipt(tx_hash) do case call_client(:eth_get_transaction_receipt, [tx_hash]) do @@ -195,7 +198,7 @@ defmodule ExW3 do end end - @spec block(integer()) :: any() + @spec block(integer()) :: any() | {:error, any()} @doc "Returns block data for specified block number" def block(block_number) do case call_client(:eth_get_block_by_number, [block_number, true]) do @@ -204,7 +207,7 @@ defmodule ExW3 do end end - @spec new_filter(%{}) :: binary() + @spec new_filter(map()) :: binary() | {:error, any()} @doc "Creates a new filter, returns filter id. For more sophisticated use, prefer ExW3.Contract.filter." def new_filter(map) do case call_client(:eth_new_filter, [map]) do @@ -222,7 +225,7 @@ defmodule ExW3 do end end - @spec uninstall_filter(binary()) :: boolean() + @spec uninstall_filter(binary()) :: boolean() | {:error, any()} @doc "Uninstalls filter from the ethereum node" def uninstall_filter(filter_id) do case call_client(:eth_uninstall_filter, [filter_id]) do @@ -231,7 +234,7 @@ defmodule ExW3 do end end - @spec mine(integer()) :: any() + @spec mine(integer()) :: any() | {:error, any()} @doc "Mines number of blocks specified. Default is 1" def mine(num_blocks \\ 1) do for _ <- 0..(num_blocks - 1) do @@ -239,49 +242,49 @@ defmodule ExW3 do end end - @spec personal_list_accounts([]) :: {:ok, []} + @spec personal_list_accounts(list()) :: {:ok, list()} | {:error, any()} @doc "Using the personal api, returns list of accounts." def personal_list_accounts(opts \\ []) do call_client(:request, ["personal_listAccounts", [], opts]) end - @spec personal_new_account(binary(), []) :: {:ok, binary} + @spec personal_new_account(binary(), list()) :: {:ok, binary()} | {:error, any()} @doc "Using the personal api, this method creates a new account with the passphrase, and returns new account address." def personal_new_account(password, opts \\ []) do call_client(:request, ["personal_newAccount", [password], opts]) end - @spec personal_unlock_account(binary(), []) :: {:ok, boolean()} + @spec personal_unlock_account(binary(), list()) :: {:ok, boolean()} | {:error, any()} @doc "Using the personal api, this method unlocks account using the passphrase provided, and returns a boolean." def personal_unlock_account(password, opts) do call_client(:request, ["personal_unlockAccount", [password], opts]) end - @spec personal_send_transaction(%{}, binary(), []) :: {:ok, binary()} + @spec personal_send_transaction(map(), binary(), list()) :: {:ok, binary()} | {:error, any()} @doc "Using the personal api, this method sends a transaction and signs it in one call, and returns a transaction id hash." def personal_send_transaction(param_map, passphrase, opts \\ []) do call_client(:request, ["personal_sendTransaction", [param_map, passphrase], opts]) end - @spec personal_sign_transaction(%{}, binary(), []) :: {:ok, %{}} + @spec personal_sign_transaction(map(), binary(), list()) :: {:ok, map()} | {:error, any()} @doc "Using the personal api, this method signs a transaction, and returns the signed transaction." def personal_sign_transaction(param_map, passphrase, opts \\ []) do call_client(:request, ["personal_signTransaction", [param_map, passphrase], opts]) end - @spec personal_sign(binary(), binary(), binary(), []) :: {:ok, binary()} + @spec personal_sign(binary(), binary(), binary(), list()) :: {:ok, binary()} | {:error, any()} @doc "Using the personal api, this method calculates an Ethereum specific signature, and returns that signature." def personal_sign(data, address, passphrase, opts \\ []) do call_client(:request, ["personal_sign", [data, address, passphrase], opts]) end - @spec personal_ec_recover(binary(), binary(), []) :: {:ok, binary()} + @spec personal_ec_recover(binary(), binary(), []) :: {:ok, binary()} | {:error, any()} @doc "Using the personal api, this method returns the address associated with the private key that was used to calculate the signature with personal_sign." def personal_ec_recover(data0, data1, opts \\ []) do call_client(:request, ["personal_ecRecover", [data0, data1], opts]) end - @spec eth_sign(binary(), binary(), []) :: {:ok, binary()} + @spec eth_sign(binary(), binary(), list()) :: {:ok, binary()} | {:error, any()} @doc "Calculates an Ethereum specific signature and signs the data provided, using the accounts private key" def eth_sign(data0, data1, opts \\ []) do call_client(:request, ["eth_sign", [data0, data1], opts]) @@ -293,13 +296,13 @@ defmodule ExW3 do ExthCrypto.Hash.Keccak.kec(signature) |> Base.encode16(case: :lower) end - @spec eth_call([]) :: any() + @spec eth_call(list()) :: any() @doc "Simple eth_call to client. Recommended to use ExW3.Contract.call instead." def eth_call(arguments) do call_client(:eth_call, arguments) end - @spec eth_send([]) :: any() + @spec eth_send(list()) :: any() @doc "Simple eth_send_transaction. Recommended to use ExW3.Contract.send instead." def eth_send(arguments) do call_client(:eth_send_transaction, arguments) @@ -318,7 +321,7 @@ defmodule ExW3 do ABI.TypeDecoder.decode(formatted_data, fs) end - @spec reformat_abi([]) :: %{} + @spec reformat_abi(list()) :: map() @doc "Reformats abi from list to map with event and function names as keys" def reformat_abi(abi) do abi @@ -326,7 +329,7 @@ defmodule ExW3 do |> Map.new() end - @spec load_abi(binary()) :: [] + @spec load_abi(binary()) :: list() | {:error, atom()} @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)) @@ -356,7 +359,7 @@ defmodule ExW3 do ABI.decode(types_signature, trim_data) |> List.first() end - @spec decode_output(%{}, binary(), binary()) :: [] + @spec decode_output(map(), binary(), binary()) :: list() @doc "Decodes output based on specified functions return signature" def decode_output(abi, name, output) do {:ok, trim_output} = @@ -374,7 +377,7 @@ defmodule ExW3 do outputs end - @spec types_signature(%{}, binary()) :: binary() + @spec types_signature(map(), 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) @@ -382,7 +385,7 @@ defmodule ExW3 do types_signature end - @spec method_signature(%{}, binary()) :: binary() + @spec method_signature(map(), 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 @@ -396,7 +399,7 @@ defmodule ExW3 do end end - @spec encode_data(binary(), []) :: binary() + @spec encode_data(binary(), list()) :: binary() @doc "Encodes data into Ethereum hex string based on types signature" def encode_data(types_signature, data) do ABI.TypeEncoder.encode_raw( @@ -405,7 +408,7 @@ defmodule ExW3 do ) end - @spec encode_options(%{}, []) :: %{} + @spec encode_options(map(), list()) :: map() @doc "Encodes list of options and returns them as a map" def encode_options(options, keys) do keys @@ -432,7 +435,7 @@ defmodule ExW3 do |> String.trim_leading("0")) end - @spec encode_method_call(%{}, binary(), []) :: binary() + @spec encode_method_call(map(), binary(), list()) :: binary() @doc "Encodes data and appends it to the encoded method id" def encode_method_call(abi, name, input) do encoded_method_call = @@ -441,7 +444,7 @@ defmodule ExW3 do encoded_method_call |> Base.encode16(case: :lower) end - @spec encode_input(%{}, binary(), []) :: binary() + @spec encode_input(map(), binary(), list()) :: binary() @doc "Encodes input from a method call based on function signature" def encode_input(abi, name, input) do if abi[name]["inputs"] do @@ -486,13 +489,13 @@ defmodule ExW3 do GenServer.start_link(__MODULE__, %{filters: %{}}, name: ContractManager) end - @spec deploy(keyword(), []) :: {:ok, binary(), []} + @spec deploy(atom(), list()) :: {:ok, binary(), binary()} @doc "Deploys contracts with given arguments" def deploy(name, args) do GenServer.call(ContractManager, {:deploy, {name, args}}) end - @spec register(keyword(), []) :: :ok + @spec register(atom(), list()) :: :ok @doc "Registers the contract with the ContractManager process. Only :abi is required field." def register(name, contract_info) do GenServer.cast(ContractManager, {:register, {name, contract_info}}) @@ -504,37 +507,37 @@ defmodule ExW3 do GenServer.cast(ContractManager, {:uninstall_filter, filter_id}) end - @spec at(keyword(), binary()) :: :ok + @spec at(atom(), binary()) :: :ok @doc "Sets the address for the contract specified by the name argument" def at(name, address) do GenServer.cast(ContractManager, {:at, {name, address}}) end - @spec address(keyword()) :: {:ok, binary()} + @spec address(atom()) :: {:ok, binary()} @doc "Returns the current Contract GenServer's address" def address(name) do GenServer.call(ContractManager, {:address, name}) end - @spec call(keyword(), keyword(), []) :: {:ok, any()} + @spec call(atom(), atom(), list()) :: {:ok, any()} @doc "Use a Contract's method with an eth_call" def call(contract_name, method_name, args \\ []) do GenServer.call(ContractManager, {:call, {contract_name, method_name, args}}) end - @spec send(keyword(), keyword(), [], %{}) :: {:ok, binary()} + @spec send(atom(), atom(), list(), map()) :: {:ok, binary()} @doc "Use a Contract's method with an eth_sendTransaction" def send(contract_name, method_name, args, options) do GenServer.call(ContractManager, {:send, {contract_name, method_name, args, options}}) end - @spec tx_receipt(keyword(), binary()) :: %{} + @spec tx_receipt(atom(), binary()) :: map() @doc "Returns a formatted transaction receipt for the given transaction hash(id)" def tx_receipt(contract_name, tx_hash) do GenServer.call(ContractManager, {:tx_receipt, {contract_name, tx_hash}}) end - @spec filter(keyword(), binary(), %{}) :: {:ok, binary()} + @spec filter(atom(), binary(), map()) :: {:ok, binary()} @doc "Installs a filter on the Ethereum node. This also formats the parameters, and saves relevant information to format event logs." def filter(contract_name, event_name, event_data \\ %{}) do GenServer.call( @@ -543,7 +546,7 @@ defmodule ExW3 do ) end - @spec get_filter_changes(binary()) :: {:ok, []} + @spec get_filter_changes(binary()) :: {:ok, list()} @doc "Using saved information related to the filter id, event logs are formatted properly" def get_filter_changes(filter_id) do GenServer.call( From 56aa89cfd7f6260cf257760bb363640e41c92e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20Mo=C5=A1i=C4=87?= Date: Thu, 11 Apr 2019 14:52:30 +0100 Subject: [PATCH 3/3] Update travis_install.sh to use new parity url --- travis_install.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/travis_install.sh b/travis_install.sh index f6ed381..ab0beba 100644 --- a/travis_install.sh +++ b/travis_install.sh @@ -2,8 +2,7 @@ echo > passfile - -wget https://releases.parity.io/v1.8.5/x86_64-unknown-linux-gnu/parity +wget https://releases.parity.io/ethereum/v1.8.5/x86_64-unknown-linux-gnu/parity chmod 755 ./parity echo > passfile