Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add get_nonce function #4

Merged
merged 4 commits into from
Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @somoza
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ lint.ci:
docs:
@mix docs

#🧪 test: @ Runs all test suites
test:
@mix test
#🧪 test.all: @ Runs all test suites
test.all:
@MIX_ENV=test mix test

#🧪 test.cover: @ Runs mix tests and generates coverage
test.cover:
Expand Down
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![License](https://img.shields.io/badge/License-MIT-blue)](https://github.com/animus-coop/ex_web3/blob/master/LICENSE.md)
[![Coverage Status](https://coveralls.io/repos/github/animus-coop/ex_web3/badge.svg?branch=main)](https://coveralls.io/github/animus-coop/ex_web3?branch=main)

**This library is Work in Progress.**
**This library is Work in Progress. Please don't use yet**

Elixir library to connect and interact with Ethereum blockchain contracts.

Expand All @@ -21,6 +21,22 @@ def deps do
end
```

Add configs:
```elixir
config :ex_web3,
url: System.get_env("web3", "http://localhost:8545"),
contract_address:
System.get_env("CONTRACT_ADDRESS", "0x8efBF5F7EB5b114207353f4caDc1dE7D88741724"),
contract_owner: System.get_env("CONTRACT_OWNER", "0xa1854bDAd86f65BE7B676411E166299F779617CF"),
contract_owner_key:
System.get_env(
"CONTRACT_OWNER_KEY",
"0x34ad65c123bc49bbd8c26d6fb808b6818ccab5a0e8b47c7fcbb5c035f467dbb7"
)
```

In this case, config attempt to get values from .env first.

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/ex_web3>.
Expand Down
6 changes: 6 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Config

config :ex_web3,
node_url: "http://localhost:8545"

import_config "#{config_env()}.exs"
14 changes: 14 additions & 0 deletions config/dev.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Config

config :logger, level: :debug

config :ex_web3,
url: System.get_env("ETHERIUM_URL", "http://localhost:7545"),
contract_address:
System.get_env("CONTRACT_ADDRESS", "0x8efBF5F7EB5b114207353f4caDc1dE7D88741724"),
contract_owner: System.get_env("CONTRACT_OWNER", "0xa1854bDAd86f65BE7B676411E166299F779617CF"),
contract_owner_key:
System.get_env(
"CONTRACT_OWNER_KEY",
"0x34ad65c123bc49bbd8c26d6fb808b6818ccab5a0e8b47c7fcbb5c035f467dbb7"
)
14 changes: 14 additions & 0 deletions config/runtime.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Config

config :logger, level: :debug

config :ex_web3,
url: System.get_env("ETHERIUM_URL", "http://localhost:7545"),
contract_address:
System.get_env("CONTRACT_ADDRESS", "0x8efBF5F7EB5b114207353f4caDc1dE7D88741724"),
contract_owner: System.get_env("CONTRACT_OWNER", "0xa1854bDAd86f65BE7B676411E166299F779617CF"),
contract_owner_key:
System.get_env(
"CONTRACT_OWNER_KEY",
"0x34ad65c123bc49bbd8c26d6fb808b6818ccab5a0e8b47c7fcbb5c035f467dbb7"
)
14 changes: 14 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Config

config :logger, level: :debug

config :ex_web3,
url: System.get_env("ETHERIUM_URL", "http://localhost:7545"),
contract_address:
System.get_env("CONTRACT_ADDRESS", "0x8efBF5F7EB5b114207353f4caDc1dE7D88741724"),
contract_owner: System.get_env("CONTRACT_OWNER", "0xa1854bDAd86f65BE7B676411E166299F779617CF"),
contract_owner_key:
System.get_env(
"CONTRACT_OWNER_KEY",
"0x34ad65c123bc49bbd8c26d6fb808b6818ccab5a0e8b47c7fcbb5c035f467dbb7"
)
2 changes: 1 addition & 1 deletion coveralls.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"coverage_options": {
"treat_no_relevant_lines_as_covered": false,
"minimum_coverage": 85
"minimum_coverage": 70
},
"skip_files": [
"test",
Expand Down
19 changes: 2 additions & 17 deletions lib/ex_web3.ex
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
defmodule ExWeb3 do
@moduledoc """
Documentation for `ExWeb3`.
"""

@doc """
Hello world.

## Examples

iex> ExWeb3.hello()
:world

"""
def hello do
:world
end
defmodule WEB3 do
@moduledoc false
end
17 changes: 17 additions & 0 deletions lib/ex_web3/application.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule WEB3.Application do
@moduledoc """
Configures and starts the :web3 OTP application
"""

use Application
import Supervisor.Spec, warn: false

def start(_type, _args) do
children = [
{Finch, name: WEB3.Finch, pools: %{}}
]

opts = [strategy: :one_for_one, name: WEB3.Supervisor]
Supervisor.start_link(children, opts)
end
end
43 changes: 43 additions & 0 deletions lib/ex_web3/client.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
defmodule WEB3.Client do
alias Finch

# alias WEB3.TransactionOptions
# Cambia esto por la URL correcta de tu nodo Ganache
@ganache_url Application.compile_env(:ex_web3, :url)

@moduledoc """
Documentation for `ExWeb3`.
"""

@doc """
Get nonce

## Examples

iex> WEB.Client.get_nonce("0xa1854bDAd86f65BE7B676411E166299F779617CF")
{:ok, {0, "x0"}}

"""
@spec get_nonce(String.t()) :: {:error, String.t()} | {:ok, {integer, binary}}
def get_nonce(address) do
body =
%{
id: 1,
jsonrpc: "2.0",
method: "eth_getTransactionCount",
params: [address, "pending"]
}
|> Jason.encode!()

headers = []

with request <- Finch.build(:post, @ganache_url, headers, body),
{:ok, %{:status => 200, :body => body}} <- Finch.request(request, WEB3.Finch),
nonce_hex <- Jason.decode!(body)["result"],
nonce <- Integer.parse(nonce_hex, 16) do
{:ok, nonce}
else
_error -> {:error, "Error retrieving nonce."}
end
end
end
17 changes: 17 additions & 0 deletions lib/ex_web3/transaction_options.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule WEB3.TransactionOptions do
@moduledoc "Struct to prepare the transaction options"

@type t :: %__MODULE__{
from: String.t(),
gas_price: pos_integer(),
gas: pos_integer,
value: pos_integer()
}

defstruct [
:from,
:gas_price,
:gas,
:value
]
end
2 changes: 2 additions & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ defmodule ExWeb3.MixProject do
# Run "mix help compile.app" to learn about applications.
def application do
[
mod: {WEB3.Application, []},
extra_applications: [:logger]
]
end
Expand All @@ -56,6 +57,7 @@ defmodule ExWeb3.MixProject do
{:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false},
{:jason, "~> 1.4"},
{:excoveralls, "~> 0.10", only: :test},
{:finch, "~> 0.14"},
{:ex_abi, "~> 0.6.0"}
]
end
Expand Down
7 changes: 7 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,24 @@
"ex_keccak": {:hex, :ex_keccak, "0.7.1", "0169f4b0c5073c5df61581d6282b12f1a1b764dcfcda4eeb1c819b5194c9ced0", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.6.1", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "c18c19f66b6545b4b46b0c71c0cc0079de84e30b26365a92961e91697e8724ed"},
"excoveralls": {:hex, :excoveralls, "0.16.1", "0bd42ed05c7d2f4d180331a20113ec537be509da31fed5c8f7047ce59ee5a7c5", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "dae763468e2008cf7075a64cb1249c97cb4bc71e236c5c2b5e5cdf1cfa2bf138"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"finch": {:hex, :finch, "0.16.0", "40733f02c89f94a112518071c0a91fe86069560f5dbdb39f9150042f44dcfb1a", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f660174c4d519e5fec629016054d60edd822cdfe2b7270836739ac2f97735ec5"},
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~> 2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
"mint": {:hex, :mint, "1.5.1", "8db5239e56738552d85af398798c80648db0e90f343c8469f6c6d8898944fb6f", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "4a63e1e76a7c3956abd2c72f370a0d0aecddc3976dea5c27eccbecfa5e7d5b1e"},
"nimble_options": {:hex, :nimble_options, "1.0.2", "92098a74df0072ff37d0c12ace58574d26880e522c22801437151a159392270e", [:mix], [], "hexpm", "fd12a8db2021036ce12a309f26f564ec367373265b53e25403f0ee697380f1b8"},
"nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"},
"nimble_pool": {:hex, :nimble_pool, "1.0.0", "5eb82705d138f4dd4423f69ceb19ac667b3b492ae570c9f5c900bb3d2f50a847", [:mix], [], "hexpm", "80be3b882d2d351882256087078e1b1952a28bf98d0a287be87e4a24a710b67a"},
"parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
"rustler_precompiled": {:hex, :rustler_precompiled, "0.6.1", "160b545bce8bf9a3f1b436b2c10f53574036a0db628e40f393328cbbe593602f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "0dd269fa261c4e3df290b12031c575fff07a542749f7b0e8b744d72d66c43600"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
}
31 changes: 28 additions & 3 deletions test/ex_web3_test.exs
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
defmodule ExWeb3Test do
# This tests are not mocked, so you should configure a local truffle/ganache
# and deploy some contract and fill below the vars.
use ExUnit.Case
doctest ExWeb3
alias WEB3.TransactionOptions

test "greets the world" do
assert ExWeb3.hello() == :world
doctest WEB3
@contract_address "0x8efBF5F7EB5b114207353f4caDc1dE7D88741724"
@owner_address "0x797F0Da0Ea4725ad23755Ea85D73356a2ab282Eb"
@receiver_address "0x922119D6f8D10779c11fb29C5f5Ea0d60415ef1c"

Check warning on line 10 in test/ex_web3_test.exs

View workflow job for this annotation

GitHub Actions / Build and test

module attribute @receiver_address was set but never used

Check warning on line 10 in test/ex_web3_test.exs

View workflow job for this annotation

GitHub Actions / Build and test

module attribute @receiver_address was set but never used
@private_key "0x25e7082d2962a5763029c9aceff04b4863a1bcb8e7a7d070856d282b0010c250"

Check warning on line 11 in test/ex_web3_test.exs

View workflow job for this annotation

GitHub Actions / Build and test

module attribute @private_key was set but never used

Check warning on line 11 in test/ex_web3_test.exs

View workflow job for this annotation

GitHub Actions / Build and test

module attribute @private_key was set but never used

test "prepare transaction options for a siple transaction" do
struct = %TransactionOptions{
from: @owner_address,
gas_price: 1_000_000_000,
gas: 1_000_000,
value: 1_000_000_000_000_000_000
}

assert %{
from: @owner_address,
gas_price: 1_000_000_000,
gas: 1_000_000,
value: 1_000_000_000_000_000_000
} = struct
end

test "Get nounce" do
# {:ok, {0, "x0"}} = WEB3.Client.get_nonce(@contract_address)
{:error, "Error retrieving nonce."} = WEB3.Client.get_nonce(@contract_address)
end
end