urbit/pkg/arvo/app/eth-watcher.hoon

380 lines
9.4 KiB
Plaintext
Raw Normal View History

2019-10-29 22:51:58 +03:00
:: eth-watcher: ethereum event log collector
::
2019-11-19 06:28:59 +03:00
/- *eth-watcher, spider
/+ default-agent, verb
=, ethereum-types
2019-08-07 01:42:37 +03:00
=, able:jael
::
2019-07-05 04:15:53 +03:00
=> |%
2019-11-19 07:36:21 +03:00
+$ card card:agent:gall
2019-07-19 01:26:15 +03:00
+$ app-state
2019-12-01 06:38:43 +03:00
$: %2
dogs=(map path watchdog)
==
::
2019-10-29 22:51:58 +03:00
+$ context [=path dog=watchdog]
+$ watchdog
$: config
2019-11-19 06:28:59 +03:00
running=(unit =tid:spider)
2019-07-19 03:08:01 +03:00
=number:block
=pending-logs
=history
2019-07-19 03:08:01 +03:00
blocks=(list block)
2019-07-19 01:26:15 +03:00
==
::
:: history: newest block first, oldest event first
+$ history (list loglist)
2019-07-05 04:15:53 +03:00
--
::
2019-11-19 06:28:59 +03:00
:: Helpers
2019-07-05 04:15:53 +03:00
::
=> |%
2019-11-19 06:28:59 +03:00
++ wait
|= [=path now=@da time=@dr]
2019-11-19 06:28:59 +03:00
^- card
[%pass [%timer path] %arvo %b %wait (add now time)]
2019-07-19 01:26:15 +03:00
::
2019-11-19 06:28:59 +03:00
++ wait-shortcut
|= [=path now=@da]
2019-11-19 06:28:59 +03:00
^- card
[%pass [%timer path] %arvo %b %wait now]
2019-07-19 01:26:15 +03:00
::
2019-11-19 06:28:59 +03:00
++ poke-spider
|= [=path our=@p =cage]
^- card
[%pass [%running path] %agent [our %spider] %poke cage]
2019-07-05 04:15:53 +03:00
::
2019-11-19 06:28:59 +03:00
++ watch-spider
|= [=path our=@p =sub=path]
^- card
[%pass [%running path] %agent [our %spider] %watch sub-path]
2019-07-19 01:26:15 +03:00
::
2019-11-19 06:28:59 +03:00
++ leave-spider
|= [=path our=@p]
^- card
[%pass [%running path] %agent [our %spider] %leave ~]
2019-07-05 04:15:53 +03:00
--
::
:: Main
::
2019-11-19 07:36:21 +03:00
^- agent:gall
2019-11-19 06:28:59 +03:00
=| state=app-state
2019-11-26 22:57:26 +03:00
%+ verb |
2019-11-19 07:36:21 +03:00
|_ =bowl:gall
2019-11-19 06:28:59 +03:00
+* this .
def ~(. (default-agent this %|) bowl)
::
++ on-init
^- (quip card _this)
[~ this]
::
2019-11-19 06:28:59 +03:00
++ on-save !>(state)
++ on-load
|= old=vase
|^
=+ !<(old-state=app-states old)
=? old-state ?=(%0 -.old-state)
2019-12-01 06:38:43 +03:00
%- (slog leaf+"upgrading eth-watcher from %0" ~)
^- app-state-1
%= old-state
- %1
dogs
%- ~(run by dogs.old-state)
|= dog=watchdog-0
%= dog
-> [~m5 ->.dog]
==
==
2019-12-01 06:38:43 +03:00
::
=^ cards-1=(list card) old-state
?. ?=(%1 -.old-state)
`old-state
%- (slog leaf+"upgrading eth-watcher from %1" ~)
2019-12-01 06:38:43 +03:00
:_ old-state(- %2)
%+ turn ~(tap by dogs.old-state)
|= [=path dog=watchdog]
(wait-shortcut path now.bowl)
::
2019-12-01 06:57:56 +03:00
[cards-1 this(state ?>(?=(%2 -.old-state) old-state))]
::
+$ app-states
2019-12-01 06:38:43 +03:00
$%(app-state-0 app-state-1 app-state)
::
+$ app-state-1
$: %1
dogs=(map path watchdog)
==
::
+$ app-state-0
$: %0
dogs=(map path watchdog-0)
==
::
+$ watchdog-0
$: config-0
running=(unit =tid:spider)
=number:block
=pending-logs
=history
blocks=(list block)
==
::
+$ config-0
$: url=@ta
from=number:block
contracts=(list address:ethereum)
=topics
==
--
::
2019-11-19 06:28:59 +03:00
++ on-poke
|= [=mark =vase]
?: ?=(%noun mark)
~& state
`this
?. ?=(%eth-watcher-poke mark)
(on-poke:def mark vase)
::
=+ !<(=poke vase)
?- -.poke
%watch
:: fully restart the watchdog if it doesn't exist yet,
:: or if the new config changes more than just the url or refresh rate.
=/ restart=?
2019-11-19 06:28:59 +03:00
?| !(~(has by dogs.state) path.poke)
?! .= ->+:(~(got by dogs.state) path.poke)
+>.config.poke
==
::
=/ already (~(has by dogs.state) path.poke)
~? &(already restart)
2019-11-19 06:28:59 +03:00
[dap.bowl 'overwriting existing watchdog on' path.poke]
=/ wait-cards
?: already
~
[(wait-shortcut path.poke now.bowl) ~]
::
2019-11-19 06:28:59 +03:00
=/ restart-cards
=/ dog (~(get by dogs.state) path.poke)
?. ?& restart
?=(^ dog)
?=(^ running.u.dog)
==
~
=/ =cage [%spider-stop !>([u.running.u.dog &])]
[%pass [%starting path] %agent [our.bowl %spider] %poke cage]
=/ new-dog
=/ dog=watchdog
?: restart *watchdog
2019-11-19 06:28:59 +03:00
(~(got by dogs.state) path.poke)
%_ dog
- config.poke
number from.config.poke
==
=. dogs.state (~(put by dogs.state) path.poke new-dog)
[wait-cards this]
::
%clear
2019-11-19 06:28:59 +03:00
=. dogs.state (~(del by dogs.state) path.poke)
[~ this]
2019-07-05 04:15:53 +03:00
==
::
2019-11-19 06:28:59 +03:00
:: +on-watch: subscribe & get initial subscription data
::
:: /logs/some-path:
::
2019-11-19 06:28:59 +03:00
++ on-watch
|= =path
2019-11-19 07:36:21 +03:00
^- (quip card agent:gall)
?. ?=([%logs ^] path)
~| [%invalid-subscription-path path]
!!
2019-11-19 06:28:59 +03:00
:_ this :_ ~
:* %give %fact ~ %eth-watcher-diff !>
:- %history
^- loglist
%- zing
%- flop
=< history
(~(gut by dogs.state) t.path *watchdog)
==
::
2019-11-19 06:28:59 +03:00
++ on-leave on-leave:def
::
:: +on-peek: get diagnostics data
::
:: /block/some-path: get next block number to check for /some-path
::
2019-11-19 06:28:59 +03:00
++ on-peek
|= =path
2019-11-19 06:28:59 +03:00
^- (unit (unit cage))
2019-12-01 06:38:43 +03:00
?+ path ~
[%x %block ^]
?. (~(has by dogs.state) t.t.path) ~
:+ ~ ~
:- %atom
!>(number:(~(got by dogs.state) t.t.path))
::
[%x %dogs ~]
``noun+!>(~(key by dogs.state))
==
2019-11-19 06:28:59 +03:00
::
++ on-agent
2019-11-19 07:36:21 +03:00
|= [=wire =sign:agent:gall]
2019-11-19 06:28:59 +03:00
|^
2019-11-19 07:36:21 +03:00
^- (quip card agent:gall)
2019-11-19 06:28:59 +03:00
?. ?=([%running *] wire)
(on-agent:def wire sign)
?- -.sign
%poke-ack
?~ p.sign
[~ this]
%- (slog leaf+"eth-watcher couldn't start thread" u.p.sign)
:_ (clear-running t.wire) :_ ~
(leave-spider t.wire our.bowl)
::
%watch-ack
?~ p.sign
[~ this]
%- (slog leaf+"eth-watcher couldn't start listen to thread" u.p.sign)
[~ (clear-running t.wire)]
::
%kick [~ (clear-running t.wire)]
%fact
=* path t.wire
=/ dog (~(get by dogs.state) path)
?~ dog
[~ this]
?+ p.cage.sign (on-agent:def wire sign)
%thread-fail
=+ !<([=term =tang] q.cage.sign)
%- (slog leaf+"eth-watcher failed; will retry" leaf+<term> tang)
[~ this(dogs.state (~(put by dogs.state) path u.dog(running ~)))]
::
%thread-done
=+ !<([vows=disavows pup=watchpup] q.cage.sign)
=. u.dog
%_ u.dog
- -.pup
number number.pup
blocks blocks.pup
pending-logs pending-logs.pup
==
=^ cards-1 u.dog (disavow path u.dog vows)
=^ cards-2 u.dog (release-logs path u.dog)
=. dogs.state (~(put by dogs.state) path u.dog(running ~))
[(weld cards-1 cards-2) this]
==
==
::
++ clear-running
|= =path
=/ dog (~(get by dogs.state) path)
?~ dog
this
this(dogs.state (~(put by dogs.state) path u.dog(running ~)))
::
++ disavow
|= [=path dog=watchdog vows=disavows]
^- (quip card watchdog)
=/ history-ids=(list [id:block loglist])
%+ murn history.dog
|= logs=loglist
^- (unit [id:block loglist])
?~ logs
~
`[[block-hash block-number]:(need mined.i.logs) logs]
=/ actual-vows=disavows
%+ skim vows
|= =id:block
(lien history-ids |=([=history=id:block *] =(id history-id)))
=/ actual-history=history
%+ murn history-ids
|= [=id:block logs=loglist]
^- (unit loglist)
?: (lien actual-vows |=(=vow=id:block =(id vow-id)))
~
`logs
:_ dog(history actual-history)
%+ turn actual-vows
|= =id:block
[%give %fact `[%logs path] %eth-watcher-diff !>([%disavow id])]
::
++ release-logs
|= [=path dog=watchdog]
^- (quip card watchdog)
?: (lth number.dog 30)
`dog
=/ rel-number (sub number.dog 30)
=/ numbers=(list number:block) ~(tap in ~(key by pending-logs.dog))
=. numbers (sort numbers lth)
|- ^- (quip card watchdog)
?~ numbers
`dog
?: (gth i.numbers rel-number)
$(numbers t.numbers)
=^ cards-1 dog
=/ =loglist (~(get ja pending-logs.dog) i.numbers)
=. pending-logs.dog (~(del by pending-logs.dog) i.numbers)
?~ loglist
`dog
=. history.dog [loglist history.dog]
:_ dog
%+ turn loglist
|= =event-log:rpc:ethereum
^- card
[%give %fact `[%logs path] %eth-watcher-diff !>([%log event-log])]
=^ cards-2 dog $(numbers t.numbers)
[(weld cards-1 cards-2) dog]
--
::
++ on-arvo
|= [=wire =sign-arvo]
2019-11-19 07:36:21 +03:00
^- (quip card agent:gall)
2019-11-19 06:28:59 +03:00
?+ +<.sign-arvo ~|([%strange-sign-arvo -.sign-arvo] !!)
%wake
2019-12-01 06:38:43 +03:00
?. ?=([%timer *] wire) ~& weird-wire=wire [~ this]
=* path t.wire
?. (~(has by dogs.state) path)
[~ this]
=/ dog=watchdog
(~(got by dogs.state) path)
2019-11-19 06:28:59 +03:00
?^ error.sign-arvo
:: failed, try again. maybe should tell user if fails more than
:: 5 times.
::
2019-12-01 06:38:43 +03:00
%- (slog leaf+"eth-watcher failed; will retry" ~)
[[(wait path now.bowl refresh-rate.dog)]~ this]
:: start a new thread that checks for updates
2019-11-19 06:28:59 +03:00
::
2019-12-01 06:38:43 +03:00
=^ cards-1=(list card) dog
2019-11-19 06:28:59 +03:00
:: if still running, kill it and restart
::
2019-12-01 06:38:43 +03:00
?~ running.dog
`dog
::
2019-11-19 06:28:59 +03:00
%- (slog leaf+"eth-watcher still running; will restart" ~)
=/ =cage [%spider-stop !>([u.running.dog |])]
:_ dog(running ~)
:~ (leave-spider path our.bowl)
[%pass [%starting path] %agent [our.bowl %spider] %poke cage]
==
2019-11-19 06:28:59 +03:00
::
2019-12-01 06:38:43 +03:00
=^ cards-2=(list card) dog
=/ new-tid=@ta
(cat 3 'eth-watcher--' (scot %uv eny.bowl))
:_ dog(running `new-tid)
=/ args
:^ ~ `new-tid %eth-watcher
!>(`watchpup`[- number pending-logs blocks]:dog)
:~ (watch-spider path our.bowl /thread-result/[new-tid])
(poke-spider path our.bowl %spider-start !>(args))
==
::
:- [(wait path now.bowl refresh-rate.dog) (weld cards-1 cards-2)]
this(dogs.state (~(put by dogs.state) path dog))
2019-11-19 06:28:59 +03:00
==
::
++ on-fail on-fail:def
2019-07-05 04:15:53 +03:00
--