From 5a18897947a2523059a4c1c5a3593d8032a09de9 Mon Sep 17 00:00:00 2001 From: Deon Date: Tue, 29 May 2018 20:36:26 -0500 Subject: [PATCH] Added checksum methods --- lib/exw3.ex | 28 ++++++++++++++++++++++++++++ test/exw3_test.exs | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/lib/exw3.ex b/lib/exw3.ex index bac58fa..5890067 100644 --- a/lib/exw3.ex +++ b/lib/exw3.ex @@ -23,6 +23,34 @@ defmodule ExW3 do Enum.join(["0x", bytes |> Base.encode16(case: :lower)], "") end + @spec to_checksum_address(binary()) :: binary() + @doc "returns a checksummed address" + def to_checksum_address(address) do + address = String.replace(address, ~r/^0x/, "") + + {:ok, hash} = Ethereumex.HttpClient.web3_sha3(String.downcase(address)) + non_prefix_hash = String.replace(hash, ~r/^0x/, "") + keccak_hash_list = non_prefix_hash + |> String.split("", trim: true) + |> Enum.map(fn (x) -> elem(Integer.parse(x, 16),0) end) + + list_arr = for n <- 0..String.length(address)-1 do + number = Enum.at(keccak_hash_list, n) + cond do + number >= 8 -> String.upcase(String.at(address, n)) + true -> String.downcase(String.at(address, n)) + end + end + + "0x" <> List.to_string(list_arr) + end + + @doc "checks if the address is a valid checksummed address" + @spec is_valid_checksum_address(binary()) :: boolean() + def is_valid_checksum_address(address) do + to_checksum_address(address) == address + end + @spec accounts() :: list() @doc "returns all available accounts" def accounts do diff --git a/test/exw3_test.exs b/test/exw3_test.exs index 94cb267..1fac304 100644 --- a/test/exw3_test.exs +++ b/test/exw3_test.exs @@ -183,4 +183,37 @@ defmodule EXW3Test do assert ExW3.to_address(same_address) == Enum.at(context[:accounts], 0) end -end \ No newline at end of file + + test "returns checksum for all caps address" do + assert ExW3.to_checksum_address(String.downcase("0x52908400098527886E0F7030069857D2E4169EE7")) == "0x52908400098527886E0F7030069857D2E4169EE7" + assert ExW3.to_checksum_address(String.downcase("0x8617E340B3D01FA5F11F306F4090FD50E238070D")) == "0x8617E340B3D01FA5F11F306F4090FD50E238070D" + end + + + test "returns checksumfor all lowercase address" do + assert ExW3.to_checksum_address(String.downcase("0xde709f2102306220921060314715629080e2fb77")) == "0xde709f2102306220921060314715629080e2fb77" + assert ExW3.to_checksum_address(String.downcase("0x27b1fdb04752bbc536007a920d24acb045561c26")) == "0x27b1fdb04752bbc536007a920d24acb045561c26" + end + + test "returns checksum for normal addresses" do + assert ExW3.to_checksum_address(String.downcase("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed")) == "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed" + assert ExW3.to_checksum_address(String.downcase("0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359")) == "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359" + assert ExW3.to_checksum_address(String.downcase("0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB")) == "0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB" + assert ExW3.to_checksum_address(String.downcase("0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb")) == "0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb" + end + + test "returns valid check for is_valid_checksum_address()" do + assert ExW3.is_valid_checksum_address("0x52908400098527886E0F7030069857D2E4169EE7") == true + assert ExW3.is_valid_checksum_address("0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB") == true + assert ExW3.is_valid_checksum_address("0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb") == true + assert ExW3.is_valid_checksum_address("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed") == true + assert ExW3.is_valid_checksum_address("0x27b1fdb04752bbc536007a920d24acb045561c26") == true + assert ExW3.is_valid_checksum_address("0xde709f2102306220921060314715629080e2fb77") == true + assert ExW3.is_valid_checksum_address("0x8617E340B3D01FA5F11F306F4090FD50E238070D") == true + assert ExW3.is_valid_checksum_address("0x52908400098527886E0F7030069857D2E4169EE7") == true + end + + test "returns invalid check for is_valid_checksum_address()" do + assert ExW3.is_valid_checksum_address("0x2f015c60e0be116b1f0cd534704db9c92118fb6a") == false + end +end