Skip to content

Commit 1d53e3d

Browse files
committed
merge master
2 parents 27b185d + c61245c commit 1d53e3d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1473
-1013
lines changed

apps/neo_node/config/config.exs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
use Mix.Config
File renamed without changes.
+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
defmodule NeoNode do
2+
@moduledoc """
3+
The boundary for the Blockchain requests.
4+
"""
5+
6+
require Logger
7+
alias NeoNode.Parser
8+
alias NeoNode.HTTPPoisonWrapper
9+
10+
@timeout 2_000
11+
12+
@opts [ssl: [{:versions, [:"tlsv1.2"]}], timeout: @timeout, recv_timeout: @timeout]
13+
@headers [{"Content-Type", "application/json"}, {"Accept-Encoding", "gzip"}]
14+
15+
@gzip_header {"Content-Encoding", "gzip"}
16+
@xgzip_header {"Content-Encoding", "x-gzip"}
17+
18+
@doc """
19+
Get the current block by height through seed 'index'
20+
"""
21+
22+
def get_block_by_height(url, height) do
23+
case post(url, "getblock", [height, 1]) do
24+
{:ok, response} ->
25+
{:ok, Parser.parse_block(response)}
26+
27+
error ->
28+
error
29+
end
30+
end
31+
32+
def get_block_by_hash(url, hash) do
33+
case post(url, "getblock", [hash, 1]) do
34+
{:ok, response} ->
35+
{:ok, Parser.parse_block(response)}
36+
37+
error ->
38+
error
39+
end
40+
end
41+
42+
def get_block_count(url), do: post(url, "getblockcount", [])
43+
44+
def get_transaction(url, txid) do
45+
case post(url, "getrawtransaction", [txid, 1]) do
46+
{:ok, response} ->
47+
{:ok, Parser.parse_transaction(response)}
48+
49+
error ->
50+
error
51+
end
52+
end
53+
54+
def get_asset(url, txid) do
55+
case post(url, "getassetstate", [txid, 1]) do
56+
{:ok, response} ->
57+
{:ok, Parser.parse_asset(response)}
58+
59+
error ->
60+
error
61+
end
62+
end
63+
64+
def get_contract(url, hash) do
65+
case post(url, "getcontractstate", [hash]) do
66+
{:ok, response} ->
67+
{:ok, Parser.parse_contract(response)}
68+
69+
error ->
70+
error
71+
end
72+
end
73+
74+
def post(url, method, params) do
75+
data =
76+
Poison.encode!(%{
77+
"jsonrpc" => "2.0",
78+
"method" => method,
79+
"params" => params,
80+
"id" => 5
81+
})
82+
83+
result = HTTPPoisonWrapper.post(url, data, @headers, @opts)
84+
handle_response(result, url)
85+
end
86+
87+
defp has_gzip_headers?(headers), do: @gzip_header in headers or @xgzip_header in headers
88+
89+
# Handles the response of an HTTP call
90+
defp handle_response(
91+
{:ok, %HTTPoison.Response{status_code: 200, body: body, headers: headers}},
92+
_
93+
) do
94+
body
95+
|> (&if(has_gzip_headers?(headers), do: :zlib.gunzip(&1), else: &1)).()
96+
|> Poison.decode()
97+
|> handle_body()
98+
end
99+
100+
defp handle_response({_, result}, url) do
101+
message = "#{inspect(result)} #{url}"
102+
Logger.debug(message)
103+
{:error, message}
104+
end
105+
106+
# handles a sucessful response
107+
defp handle_body({:ok, %{"result" => result}}), do: {:ok, result}
108+
defp handle_body({:ok, %{"error" => error}}), do: {:error, error}
109+
defp handle_body(error), do: {:error, "body error: #{inspect(error)}"}
110+
end

apps/neoscan_node/lib/neoscan_node/parser.ex apps/neo_node/lib/neo_node/parser.ex

+1-50
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
defmodule NeoscanNode.Parser do
1+
defmodule NeoNode.Parser do
22
defp parse16("0x" <> rest), do: parse16(rest)
33

44
defp parse16(string) do
@@ -25,7 +25,6 @@ defmodule NeoscanNode.Parser do
2525

2626
defp parse_float(nil), do: nil
2727
defp parse_float(string), do: elem(Float.parse(string), 0)
28-
defp parse_integer(string), do: String.to_integer(string)
2928

3029
defp parse_claims(nil), do: []
3130
defp parse_claims(claims), do: Enum.map(claims, &parse_vin/1)
@@ -56,32 +55,6 @@ defmodule NeoscanNode.Parser do
5655
|> parse_asset()
5756
end
5857

59-
defp parse_notify_type("transfer"), do: :transfer
60-
61-
def parse_block_notification(block_notification = %{"notify_type" => "transfer"}) do
62-
%{
63-
addr_from: parse58(block_notification["addr_from"]),
64-
addr_to: parse58(block_notification["addr_to"]),
65-
amount: parse_integer(block_notification["amount"]),
66-
block: block_notification["block"],
67-
contract: parse16(block_notification["contract"]),
68-
notify_type: parse_notify_type(block_notification["notify_type"]),
69-
transaction_hash: parse16(block_notification["tx"]),
70-
type: block_notification["type"]
71-
}
72-
end
73-
74-
def parse_block_notification(_) do
75-
%{notify_type: :others}
76-
end
77-
78-
def parse_contract(contract = %{"code" => code}) do
79-
contract
80-
|> Map.merge(code)
81-
|> Map.delete("code")
82-
|> parse_contract()
83-
end
84-
8558
def parse_contract(contract) do
8659
%{
8760
author: contract["author"],
@@ -168,26 +141,4 @@ defmodule NeoscanNode.Parser do
168141
if(is_nil(contract), do: [], else: [%{"contract" => contract}]) ++
169142
if is_nil(script), do: [], else: [%{"script" => script}]
170143
end
171-
172-
defp parse_token_token(token) do
173-
%{
174-
contract_address: parse58(token["contract_address"]),
175-
decimals: token["decimals"],
176-
name: parse_string(token["name"]),
177-
script_hash: parse16(token["script_hash"]),
178-
symbol: parse_string(token["symbol"])
179-
}
180-
end
181-
182-
def parse_token(token) do
183-
%{
184-
block: token["block"],
185-
contract: parse_contract(token["contract"]),
186-
token: parse_token_token(token["token"]),
187-
transaction_hash: parse16(token["tx"]),
188-
type: token["type"]
189-
}
190-
end
191-
192-
defp parse_string(string), do: String.replace(string, "\u0000", "")
193144
end

apps/neo_node/mix.exs

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
defmodule NeoNode.Mixfile do
2+
use Mix.Project
3+
4+
def project do
5+
[
6+
app: :neo_node,
7+
version: "2.0.0",
8+
build_path: "../../_build",
9+
config_path: "../../config/config.exs",
10+
deps_path: "../../deps",
11+
lockfile: "../../mix.lock",
12+
elixir: "~> 1.6",
13+
elixirc_options: [
14+
warnings_as_errors: true
15+
],
16+
elixirc_paths: elixirc_paths(Mix.env()),
17+
test_coverage: [
18+
tool: ExCoveralls
19+
],
20+
preferred_cli_env: [
21+
coveralls: :test,
22+
"coveralls.detail": :test,
23+
"coveralls.post": :test,
24+
"coveralls.html": :test
25+
],
26+
build_embedded: Mix.env() == :prod,
27+
start_permanent: Mix.env() == :prod,
28+
deps: deps()
29+
]
30+
end
31+
32+
# Configuration for the OTP application
33+
#
34+
# Type "mix help compile.app" for more information
35+
def application do
36+
# Specify extra applications you'll use from Erlang/Elixir
37+
[
38+
extra_applications: [:logger, :httpoison]
39+
]
40+
end
41+
42+
# Specifies which paths to compile per environment.
43+
defp elixirc_paths(:test), do: ["lib", "test/support"]
44+
defp elixirc_paths(_), do: ["lib", "wrapper"]
45+
46+
# Dependencies can be Hex packages:
47+
#
48+
# {:my_dep, "~> 0.3.0"}
49+
#
50+
# Or git/path repositories:
51+
#
52+
# {:my_dep, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
53+
#
54+
# To depend on another app inside the umbrella:
55+
#
56+
# {:my_app, in_umbrella: true}
57+
#
58+
# Type "mix help deps" for more examples and options
59+
defp deps do
60+
[
61+
{:hackney, "~> 1.11", override: true},
62+
{:poison, "~> 3.1"},
63+
{:base58, github: "adrienmo/base58"},
64+
{:httpoison, "~> 0.11 or ~> 0.12 or ~> 0.13"},
65+
{:excoveralls, "~> 0.8", only: :test}
66+
]
67+
end
68+
end

apps/neoscan_node/test/neoscan_node/blockchain_test.exs apps/neo_node/test/neo_node/neo_node_test.exs

+32-17
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
defmodule Neoscan.Blockchain.BlockchainTest do
1+
defmodule NeoNodeTest do
22
use ExUnit.Case
33

4-
alias NeoscanNode.Blockchain
4+
@fake_node_url "http://fakenode"
5+
6+
test "post/3" do
7+
assert {:ok, _} = NeoNode.post(@fake_node_url, "getblock", [0, 1])
8+
assert {:error, _} = NeoNode.post(@fake_node_url, "getblockerror", [0, 1])
9+
end
510

611
test "get_block_by_height/2" do
712
assert {
@@ -179,26 +184,32 @@ defmodule Neoscan.Blockchain.BlockchainTest do
179184
],
180185
version: 0
181186
}
182-
} == Blockchain.get_block_by_height(0)
187+
} == NeoNode.get_block_by_height(@fake_node_url, 0)
188+
189+
assert {:ok, %{index: 2_120_069}} = NeoNode.get_block_by_height(@fake_node_url, 2_120_069)
190+
191+
assert {:error, "error"} == NeoNode.get_block_by_height(@fake_node_url, 123_456)
183192

184-
assert {:ok, %{index: 2_120_069}} = Blockchain.get_block_by_height(2_120_069)
193+
assert {:error, ":timeout #{@fake_node_url}"} ==
194+
NeoNode.get_block_by_height(@fake_node_url, 123_457)
185195
end
186196

187197
test "get_block_by_hash/2" do
188198
block_0_hash = "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
189199
block_1_hash = "d782db8a38b0eea0d7394e0f007c61c71798867578c77c387c08113903946cc9"
190-
assert {:ok, %{index: 0}} = Blockchain.get_block_by_hash(block_0_hash)
191-
assert {:ok, %{index: 1}} = Blockchain.get_block_by_hash(block_1_hash)
200+
assert {:ok, %{index: 0}} = NeoNode.get_block_by_hash(@fake_node_url, block_0_hash)
201+
assert {:ok, %{index: 1}} = NeoNode.get_block_by_hash(@fake_node_url, block_1_hash)
192202

193203
assert {:error, %{"code" => -100, "message" => _message}} =
194-
Blockchain.get_block_by_hash(
204+
NeoNode.get_block_by_hash(
205+
@fake_node_url,
195206
"0000000000000000000000000000000000000000000000000000000000000000"
196207
)
197208
end
198209

199210
test "get_block_count/1" do
200-
{:ok, count} = Blockchain.get_block_count()
201-
assert 200 == count
211+
{:ok, count} = NeoNode.get_block_count(@fake_node_url)
212+
assert 2_400_000 == count
202213
end
203214

204215
test "get_transaction/2" do
@@ -227,20 +238,23 @@ defmodule Neoscan.Blockchain.BlockchainTest do
227238
vouts: [],
228239
claims: []
229240
}
230-
} == Blockchain.get_transaction(txid)
241+
} == NeoNode.get_transaction(@fake_node_url, txid)
231242

232243
assert {:ok, %{scripts: [%{}, %{"contract" => _}]}} =
233-
Blockchain.get_transaction(
244+
NeoNode.get_transaction(
245+
@fake_node_url,
234246
"fd161ccd87deab812daa433cbc0f8f6468de24f1d708187beef5ab9ada7050f3"
235247
)
236248

237249
assert {:ok, %{scripts: [%{}, %{}, %{"script" => _}]}} =
238-
Blockchain.get_transaction(
250+
NeoNode.get_transaction(
251+
@fake_node_url,
239252
"45ced268026de0fcaf7035e4960e860b98fe1ae5122e716d9daac1163f13e534"
240253
)
241254

242255
assert {:error, %{"code" => -100, "message" => _message}} =
243-
Blockchain.get_transaction(
256+
NeoNode.get_transaction(
257+
@fake_node_url,
244258
"0000000000000000000000000000000000000000000000000000000000000000"
245259
)
246260
end
@@ -273,10 +287,11 @@ defmodule Neoscan.Blockchain.BlockchainTest do
273287
type: :governing_token,
274288
version: 0
275289
}
276-
} == Blockchain.get_asset(txid)
290+
} == NeoNode.get_asset(@fake_node_url, txid)
277291

278292
assert {:error, %{"code" => -100, "message" => _message}} =
279-
Blockchain.get_asset(
293+
NeoNode.get_asset(
294+
@fake_node_url,
280295
"0x0000000000000000000000000000000000000000000000000000000000000000"
281296
)
282297
end
@@ -303,9 +318,9 @@ defmodule Neoscan.Blockchain.BlockchainTest do
303318
script: <<1, 31>>,
304319
version: 0
305320
}
306-
} = Blockchain.get_contract(contract_hash)
321+
} = NeoNode.get_contract(@fake_node_url, contract_hash)
307322

308323
assert {:error, %{"code" => -100, "message" => _message}} =
309-
Blockchain.get_contract("0x0000000000000000000000000000000000000000")
324+
NeoNode.get_contract(@fake_node_url, "0x0000000000000000000000000000000000000000")
310325
end
311326
end

0 commit comments

Comments
 (0)