4
0
Fork 0

Able to receive event from listener

event-listener
hswick 6 years ago
parent ab94dcb4a9
commit dbd6262a40
  1. 169
      lib/exw3.ex
  2. 16
      test/exw3_test.exs

@ -288,6 +288,75 @@ defmodule ExW3 do
end
end
defmodule Poller do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, [], name: EventPoller)
end
def subscribe(filter_id) do
GenServer.cast(EventPoller, {:subscribe, filter_id})
end
@impl true
def init(state) do
schedule_work() # Schedule work to be performed on start
{:ok, state}
end
@impl true
def handle_cast({:subscribe, filter_id}, state) do
{:noreply, [filter_id | state]}
end
@impl true
def handle_info(:work, state) do
# Do the desired work here
Enum.each state, fn filter_id ->
send EventListener, {:event, filter_id, ExW3.get_filter_changes(filter_id)}
end
schedule_work() # Reschedule once more
{:noreply, state}
end
defp schedule_work() do
Process.send_after(self(), :work, 1000) # In 1 sec
end
end
defmodule Listener do
def start_link do
Poller.start_link()
{:ok, pid} = Task.start_link(fn -> loop(%{}) end)
Process.register(pid, EventListener)
:ok
end
def subscribe(filter_id, pid) do
Poller.subscribe(filter_id)
send EventListener, {:subscribe, filter_id, pid}
end
def listen(callback) do
receive do
{:event, result} -> apply callback, [result]
end
listen(callback)
end
defp loop(map) do
receive do
{:subscribe, filter_id, pid} ->
loop(Map.put(map, filter_id, pid))
{:event, filter_id, data} ->
send Map.get(map, filter_id), {:event, {filter_id, data}}
loop(map)
end
end
end
defmodule Contract do
use GenServer
@ -335,11 +404,15 @@ defmodule ExW3 do
GenServer.call(pid, {:tx_receipt, tx_hash})
end
def subscribe(pid, event_name, other_pid, event_data \\ %{}) do
GenServer.call(pid, {:subscribe, {event_name, other_pid, event_data}})
end
# Server
def init(state) do
if state[:abi] do
{:ok, [{:events, init_events(state[:abi])} | state]}
{:ok, state ++ init_events(state[:abi])}
else
raise "ABI not provided upon initialization"
end
@ -351,16 +424,28 @@ defmodule ExW3 do
v["type"] == "event"
end)
signature_types_map =
names_and_signature_types_map =
Enum.map(events, fn {name, v} ->
types = Enum.map(v["inputs"], &Map.get(&1, "type"))
names = Enum.map(v["inputs"], &Map.get(&1, "name"))
signature = Enum.join([name, "(", Enum.join(types, ","), ")"])
{"0x#{ExW3.encode_event(signature)}", %{signature: signature, names: names}}
encoded_event_signature = "0x#{ExW3.encode_event(signature)}"
{{encoded_event_signature, %{signature: signature, names: names}}, {name, encoded_event_signature}}
end)
Enum.into(signature_types_map, %{})
signature_types_map =
Enum.map(names_and_signature_types_map, fn {signature_types, _} ->
signature_types
end)
names_map =
Enum.map(names_and_signature_types_map, fn {_, names} ->
names
end)
[events: Enum.into(signature_types_map, %{}), event_names: Enum.into(names_map, %{})]
end
# Helpers
@ -429,6 +514,13 @@ defmodule ExW3 do
{:noreply, [{:address, address} | state]}
end
def handle_call({:subscribe, {event_name, other_pid, event_data}}, _from, state) do
payload = Map.merge(%{address: state[:address], topics: [state[:event_names][event_name]]}, event_data)
filter_id = ExW3.new_filter(payload)
Listener.subscribe(filter_id, other_pid)
{:reply, filter_id, state ++ [event_name, filter_id]}
end
# Calls
def handle_call({:deploy, args}, _from, state) do
@ -486,74 +578,5 @@ defmodule ExW3 do
{:reply, {:ok, {receipt, formatted_logs}}, state}
end
end
defmodule Poller do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, [], name: EventPoller)
end
def subscribe(event) do
GenServer.cast(EventPoller, {:subscribe, event})
end
@impl true
def init(state) do
schedule_work() # Schedule work to be performed on start
{:ok, state}
end
@impl true
def handle_cast({:subscribe, event}, state) do
{:noreply, [event | state]}
end
@impl true
def handle_info(:work, state) do
# Do the desired work here
Enum.each state, fn event ->
send EventListener, {:event, event, "Hello, World"}
end
schedule_work() # Reschedule once more
{:noreply, state}
end
defp schedule_work() do
Process.send_after(self(), :work, 1000) # In 1 sec
end
end
defmodule Listener do
def start_link do
Poller.start_link()
{:ok, pid} = Task.start_link(fn -> loop(%{}) end)
Process.register(pid, EventListener)
:ok
end
def subscribe(event, pid) do
Poller.subscribe(event)
send EventListener, {:subscribe, event, pid}
end
def listen(callback) do
receive do
{:event, result} -> apply callback, [result]
end
listen(callback)
end
defp loop(map) do
receive do
{:subscribe, event, pid} ->
loop(Map.put(map, event, pid))
{:event, event, data} ->
send Map.get(map, event), {:event, {event, data}}
loop(map)
end
end
end
end

@ -147,6 +147,10 @@ defmodule EXW3Test do
)
ExW3.Contract.at(EventTester, address)
ExW3.Listener.start_link()
filter_id = ExW3.Contract.subscribe(EventTester, "Simple", self())
{:ok, tx_hash} =
ExW3.Contract.send(
@ -156,14 +160,14 @@ defmodule EXW3Test do
%{from: Enum.at(context[:accounts], 0)}
)
ExW3.Listener.start_link()
ExW3.Listener.subscribe("Hello", self())
receive do
{:event, {"Frank", data}} -> IO.inspect data
after 3_000 -> raise "Never received event"
{:event, {filter_id, data}} ->
IO.inspect data
after 3_000 ->
raise "Never received event"
end
ExW3.uninstall_filter(filter_id)
end
test "starts a Contract GenServer for Complex contract", context do

Loading…
Cancel
Save