mirror of
https://github.com/urbit/shrub.git
synced 2025-01-05 02:57:18 +03:00
Merge remote-tracking branch 'origin/master' into philip/aquarium
This commit is contained in:
commit
1e1bcfa02e
@ -1069,6 +1069,7 @@
|
||||
?- -.sink.com
|
||||
$stdout [%show %0]
|
||||
$output-file $(sink.com [%command (cat 3 '@' pax.sink.com)])
|
||||
$output-pill $(sink.com [%command (cat 3 '.' pax.sink.com)])
|
||||
$output-clay [%file (need (de-beam:format pax.sink.com))]
|
||||
$url [%http %post `~. url.sink.com]
|
||||
$to-api !!
|
||||
|
568
app/eth-watcher.hoon
Normal file
568
app/eth-watcher.hoon
Normal file
@ -0,0 +1,568 @@
|
||||
:: watcher: ethereum event log collector
|
||||
::
|
||||
/+ *eth-watcher
|
||||
::
|
||||
=, ethereum
|
||||
=, rpc
|
||||
::
|
||||
|%
|
||||
++ state
|
||||
$: eyes=(map name eye)
|
||||
==
|
||||
::
|
||||
++ eye
|
||||
$: config
|
||||
latest-block=@ud
|
||||
filter-id=@ud
|
||||
poll-timer=(unit @da)
|
||||
snapshot
|
||||
sap=history
|
||||
==
|
||||
::
|
||||
++ history
|
||||
$: interval=_100
|
||||
max-count=_10
|
||||
count=@ud
|
||||
latest-block=@ud
|
||||
snaps=(qeu snapshot)
|
||||
==
|
||||
::
|
||||
++ move (pair bone card)
|
||||
++ card
|
||||
$% [%hiss wire (unit user:eyre) mark %hiss hiss:eyre]
|
||||
[%wait wire @da]
|
||||
[%rest @da]
|
||||
[%info wire desk nori:clay]
|
||||
[%diff %eth-watcher-update update]
|
||||
[%quit ~]
|
||||
==
|
||||
--
|
||||
::
|
||||
|_ [bowl:gall state]
|
||||
::
|
||||
++ prep
|
||||
|= old=(unit state)
|
||||
?~ old
|
||||
[~ ..prep]
|
||||
[~ ..prep(+<+ u.old)]
|
||||
::
|
||||
++ poke-noun
|
||||
|= [what=?(%save %load) =name]
|
||||
^- (quip move _+>)
|
||||
=+ eye=(fall (~(get by eyes) name) *eye)
|
||||
?- what
|
||||
%save
|
||||
=/ pax=path
|
||||
/(scot %p our)/home/(scot %da now)/watcher/[name]/jam
|
||||
:_ +>.$
|
||||
:_ ~
|
||||
^- move
|
||||
:* ost
|
||||
%info
|
||||
/jamfile
|
||||
(foal:space:userlib pax [%jam !>((jam eye))])
|
||||
==
|
||||
::
|
||||
%load
|
||||
=. eyes
|
||||
%+ ~(put by eyes) name
|
||||
=- (^eye (cue .^(@ %cx -)))
|
||||
/(scot %p our)/home/(scot %da now)/watcher/[name]/jam
|
||||
done:new-filter:(open:watcher name)
|
||||
==
|
||||
::
|
||||
++ poke-eth-watcher-action
|
||||
|= act=action
|
||||
^- (quip move _+>)
|
||||
?- -.act
|
||||
%watch
|
||||
done:(init:watcher +.act)
|
||||
::
|
||||
%clear
|
||||
wipe:(open:watcher +.act)
|
||||
==
|
||||
::
|
||||
++ peek-x
|
||||
|= pax=path
|
||||
^- (unit (unit [%noun *]))
|
||||
?. ?=([@ *] pax) ~
|
||||
=+ eye=(~(get by eyes) i.pax)
|
||||
?~ eye [~ ~]
|
||||
:: /name: all logs
|
||||
::
|
||||
?~ t.pax ``[%noun logs.u.eye]
|
||||
:: /name/num: most recent num logs
|
||||
::
|
||||
=+ num=(slaw %ud i.t.pax)
|
||||
?^ num ``[%noun (scag u.num logs.u.eye)]
|
||||
:: /name/debug: debug information
|
||||
::
|
||||
?. ?=(%debug i.t.pax) ~
|
||||
=- ``[%noun -]
|
||||
=, u.eye
|
||||
:* node=(en-purl:html node)
|
||||
last=last-heard-block
|
||||
lent=(lent logs)
|
||||
time=poll-timer
|
||||
==
|
||||
::
|
||||
++ peer
|
||||
|= pax=path
|
||||
^- (quip move _+>)
|
||||
?> ?=([@ ~] pax)
|
||||
done:(put-snapshot-diff:(open:watcher i.pax) ost)
|
||||
::
|
||||
++ wake
|
||||
|= [wir=wire ~]
|
||||
^- (quip move _+>)
|
||||
?> ?=([@ %poll ~] wir)
|
||||
done:poll-filter:(open:watcher i.wir)
|
||||
::
|
||||
++ sigh-tang
|
||||
|= [wir=wire res=tang]
|
||||
^- (quip move _+>)
|
||||
~& ['something went wrong!' wir]
|
||||
~_ res
|
||||
[~ +>.$]
|
||||
::
|
||||
++ sigh-json-rpc-response
|
||||
|= [wir=wire res=response:rpc:jstd]
|
||||
^- (quip move _+>)
|
||||
?> ?=([@ *] wir)
|
||||
=< done
|
||||
%- sigh-json-rpc-response:(open:watcher i.wir)
|
||||
[t.wir res]
|
||||
::
|
||||
++ watcher
|
||||
|_ $: =name
|
||||
=eye
|
||||
rewind-block=(unit @ud)
|
||||
new-logs=loglist
|
||||
moves=(list move)
|
||||
==
|
||||
::
|
||||
:: +open: initialize core
|
||||
::
|
||||
++ open
|
||||
|= nom=^name
|
||||
^+ +>
|
||||
+>.$(name nom, eye (~(got by eyes) nom))
|
||||
::
|
||||
:: +init: set up eye and initialize core
|
||||
::
|
||||
++ init
|
||||
|= [nom=^name =config]
|
||||
^+ +>
|
||||
=. name nom
|
||||
=. eye
|
||||
%*(. *^eye - config, last-heard-block from-block.config)
|
||||
get-latest-block
|
||||
::
|
||||
:: +| outward
|
||||
::
|
||||
:: +wipe: delete eye
|
||||
::
|
||||
++ wipe
|
||||
=> cancel-wait-poll
|
||||
=> cancel-subscribers
|
||||
:- (flop moves)
|
||||
..watcher(eyes (~(del by eyes) name))
|
||||
::
|
||||
:: +done: store changes, update subscribers
|
||||
::
|
||||
++ done
|
||||
^- [(list move) _..watcher]
|
||||
=? . ?=(^ rewind-block)
|
||||
:: if we're rewinding to a block, then we throw away any moves
|
||||
:: and changes we were going to make.
|
||||
::
|
||||
=: moves *(list move)
|
||||
new-logs *loglist
|
||||
==
|
||||
(restore-block u.rewind-block)
|
||||
:: if we have any updates, send them
|
||||
::
|
||||
=? . !=(~ new-logs)
|
||||
(fan-diff %logs new-logs)
|
||||
:: produce moves, store updated state
|
||||
::
|
||||
:- (flop moves)
|
||||
..watcher(eyes (~(put by eyes) name eye))
|
||||
::
|
||||
:: +put-move: store side-effect
|
||||
::
|
||||
++ put-move
|
||||
|= =card
|
||||
%_(+> moves [[ost card] moves])
|
||||
::
|
||||
++ put-moves
|
||||
|= moz=(list move)
|
||||
%_(+> moves (weld (flop moz) moves))
|
||||
::
|
||||
:: +put-rpc-request: store rpc request to ethereum node
|
||||
::
|
||||
++ put-rpc-request
|
||||
|= [wir=wire id=(unit @t) req=request]
|
||||
^+ +>
|
||||
%- put-move
|
||||
^- card
|
||||
:* %hiss
|
||||
[name wir]
|
||||
~
|
||||
%json-rpc-response
|
||||
%hiss
|
||||
%+ json-request node.eye
|
||||
(request-to-json id req)
|
||||
==
|
||||
::
|
||||
:: +put-log: store change made by event
|
||||
::
|
||||
++ put-log
|
||||
|= log=event-log
|
||||
%_ +>
|
||||
new-logs (store-new-logs ~[log] new-logs)
|
||||
logs.eye (store-new-logs ~[log] logs.eye)
|
||||
heard.eye (~(put in heard.eye) (log-to-id log))
|
||||
==
|
||||
::
|
||||
:: +| subscriptions
|
||||
::
|
||||
++ put-diff
|
||||
|= [for=bone dif=update]
|
||||
%_(+> moves [[for %diff %eth-watcher-update dif] moves])
|
||||
::
|
||||
++ put-snapshot-diff
|
||||
|= for=bone
|
||||
(put-diff for %snap last-heard-block.eye heard.eye logs.eye)
|
||||
::
|
||||
++ get-subscribers
|
||||
^- (list bone)
|
||||
%+ murn ~(tap by sup)
|
||||
|= [b=bone s=ship p=path]
|
||||
^- (unit bone)
|
||||
?> ?=([@ *] p)
|
||||
?:(=(name i.p) `b ~)
|
||||
::
|
||||
++ fan-diff
|
||||
|= dif=update
|
||||
%- put-moves
|
||||
%+ turn get-subscribers
|
||||
|= b=bone
|
||||
^- move
|
||||
[b %diff %eth-watcher-update dif]
|
||||
::
|
||||
++ cancel-subscribers
|
||||
%- put-moves
|
||||
%+ turn get-subscribers
|
||||
|=(b=bone [b %quit ~])
|
||||
::
|
||||
:: +| catch-up-operations
|
||||
::
|
||||
:: +get-latest-block
|
||||
::
|
||||
:: Get latest block from eth node and compare to our own latest block.
|
||||
:: Get intervening blocks in chunks until we're caught up, then set
|
||||
:: up a filter going forward.
|
||||
::
|
||||
++ get-latest-block
|
||||
=> cancel-wait-poll
|
||||
(put-rpc-request /catch-up/block-number `'block number' %eth-block-number ~)
|
||||
::
|
||||
:: +catch-up: get next chunk
|
||||
::
|
||||
++ catch-up
|
||||
|= from-block=@ud
|
||||
^+ +>
|
||||
?: (gte from-block latest-block.eye)
|
||||
new-filter
|
||||
=/ next-block (min latest-block.eye (add from-block 5.760)) :: ~d1
|
||||
~? debug=|
|
||||
[%catching-up from=from-block to=latest-block.eye]
|
||||
%- put-rpc-request
|
||||
:+ /catch-up/step/(scot %ud from-block)/(scot %ud next-block)
|
||||
`'catch up'
|
||||
:* %eth-get-logs
|
||||
`number+from-block
|
||||
`number+next-block
|
||||
contracts.eye
|
||||
topics.eye
|
||||
==
|
||||
::
|
||||
:: +| filter-operations
|
||||
::
|
||||
:: +new-filter: request a new polling filter
|
||||
::
|
||||
:: Listens from the last-heard block onward.
|
||||
::
|
||||
++ new-filter
|
||||
%- put-rpc-request
|
||||
:+ /filter/new `'new filter'
|
||||
^- request:rpc
|
||||
:* %eth-new-filter
|
||||
`number+last-heard-block.eye
|
||||
?~(to-block.eye ~ `number+u.to-block.eye)
|
||||
contracts.eye
|
||||
topics.eye
|
||||
==
|
||||
::
|
||||
:: +read-filter: get all events the filter captures
|
||||
::
|
||||
++ read-filter
|
||||
%- put-rpc-request
|
||||
:+ /filter/logs `'filter logs'
|
||||
[%eth-get-filter-logs filter-id.eye]
|
||||
::
|
||||
:: +poll-filter: get all new events since last poll (or filter creation)
|
||||
::
|
||||
++ poll-filter
|
||||
?: =(0 filter-id.eye)
|
||||
~& %no-filter-bad-poll
|
||||
.
|
||||
%- put-rpc-request
|
||||
:+ /filter/changes `'poll filter'
|
||||
[%eth-get-filter-changes filter-id.eye]
|
||||
::
|
||||
:: +wait-poll: remind us to poll in four minutes
|
||||
::
|
||||
:: Four minutes because Ethereum RPC filters time out after five.
|
||||
:: We don't check for an existing timer or clear an old one here,
|
||||
:: sane flows shouldn't see this being called superfluously.
|
||||
::
|
||||
++ wait-poll
|
||||
=+ wen=(add now ~m4)
|
||||
%- put-move(poll-timer.eye `wen)
|
||||
[%wait name^/poll wen]
|
||||
::
|
||||
:: +cancel-wait-poll: remove poll reminder
|
||||
::
|
||||
++ cancel-wait-poll
|
||||
?~ poll-timer.eye ..cancel-wait-poll
|
||||
%- put-move(poll-timer.eye ~)
|
||||
[%rest u.poll-timer.eye]
|
||||
::
|
||||
:: +| filter-results
|
||||
::
|
||||
:: +sigh-json-rpc-response: process rpc response
|
||||
::
|
||||
++ sigh-json-rpc-response
|
||||
|= [wir=wire res=response:rpc:jstd]
|
||||
^+ +>
|
||||
~! -.res
|
||||
?: ?=(%fail -.res)
|
||||
?: =(405 p.hit.res)
|
||||
~& 'HTTP 405 error (expected if using infura)'
|
||||
+>.$
|
||||
?. =(5 (div p.hit.res 100))
|
||||
~& [%http-error hit.res]
|
||||
+>.$
|
||||
?+ wir
|
||||
~& [%retrying-node ~] ::((soft tang) q.res)]
|
||||
wait-poll
|
||||
[%catch-up %step @ta @ta ~]
|
||||
~& %retrying-catch-up
|
||||
(catch-up (slav %ud `@ta`i.t.t.wir))
|
||||
==
|
||||
?+ wir ~|([%weird-sigh-wire wir] !!)
|
||||
[%filter %new *]
|
||||
(take-new-filter res)
|
||||
::
|
||||
[%filter *]
|
||||
(take-filter-results res)
|
||||
::
|
||||
[%catch-up %block-number ~]
|
||||
(take-block-number res)
|
||||
::
|
||||
[%catch-up %step @ta @ta ~]
|
||||
=/ from-block (slav %ud `@ta`i.t.t.wir)
|
||||
=/ next-block (slav %ud `@ta`i.t.t.t.wir)
|
||||
(take-catch-up-step res from-block next-block)
|
||||
==
|
||||
::
|
||||
:: +take-new-filter: store filter-id and read it
|
||||
::
|
||||
++ take-new-filter
|
||||
|= rep=response:rpc:jstd
|
||||
^+ +>
|
||||
~| rep
|
||||
?< ?=(%batch -.rep)
|
||||
?< ?=(%fail -.rep)
|
||||
?: ?=(%error -.rep)
|
||||
~& [%filter-error--retrying message.rep]
|
||||
new-filter
|
||||
=- read-filter(filter-id.eye -)
|
||||
(parse-eth-new-filter-res res.rep)
|
||||
::
|
||||
:: +take-filter-results: parse results into event-logs and process them
|
||||
::
|
||||
++ take-filter-results
|
||||
|= rep=response:rpc:jstd
|
||||
^+ +>
|
||||
?< ?=(%batch -.rep)
|
||||
?< ?=(%fail -.rep)
|
||||
?: ?=(%error -.rep)
|
||||
?. ?| =('filter not found' message.rep) :: geth
|
||||
=('Filter not found' message.rep) :: parity
|
||||
==
|
||||
~& [%unhandled-filter-error +.rep]
|
||||
+>
|
||||
~& [%filter-timed-out--recreating block=last-heard-block.eye +.rep]
|
||||
:: arguably should rewind 40 blocks on the off chance the chain reorganized
|
||||
:: when we blinked. this will also restart the filter.
|
||||
::
|
||||
:: (restore-block ?:((lth last-heard-block 40) 0 (sub.add last-heard-block 40)))
|
||||
::
|
||||
:: counter-argument: it's a royal pain to restore from a snapshot
|
||||
:: every time you can't ping the node for 5 minutes. this is likely
|
||||
:: to destabilize the network. better to manually restore if we
|
||||
:: notice an anomaly.
|
||||
::
|
||||
:: third way: don't trust anything that doesn't have 40 confirmations
|
||||
::
|
||||
new-filter
|
||||
:: kick polling timer, only if it hasn't already been.
|
||||
=? +> |(?=(~ poll-timer.eye) (gth now u.poll-timer.eye))
|
||||
wait-poll
|
||||
(take-events rep)
|
||||
::
|
||||
:: +take-block-number: take block number and start catching up
|
||||
::
|
||||
++ take-block-number
|
||||
|= rep=response:rpc:jstd
|
||||
^+ +>
|
||||
?< ?=(%batch -.rep)
|
||||
?< ?=(%fail -.rep)
|
||||
?: ?=(%error -.rep)
|
||||
~& [%take-block-number-error--retrying message.rep]
|
||||
get-latest-block
|
||||
=. latest-block.eye (parse-eth-block-number res.rep)
|
||||
(catch-up last-heard-block.eye)
|
||||
::
|
||||
:: +take-catch-up-step: process chunk
|
||||
::
|
||||
++ take-catch-up-step
|
||||
|= [rep=response:rpc:jstd from-block=@ud next-block=@ud]
|
||||
^+ +>
|
||||
?< ?=(%batch -.rep)
|
||||
?< ?=(%fail -.rep)
|
||||
?: ?=(%error -.rep)
|
||||
~& [%catch-up-step-error--retrying message.rep]
|
||||
(catch-up from-block)
|
||||
=. +>.$ (take-events rep)
|
||||
(catch-up next-block)
|
||||
::
|
||||
:: +take-events: process events
|
||||
::
|
||||
++ take-events
|
||||
|= rep=response:rpc:jstd
|
||||
^+ +>
|
||||
?< ?=(%batch -.rep)
|
||||
?< ?=(%fail -.rep)
|
||||
?< ?=(%error -.rep)
|
||||
?. ?=(%a -.res.rep)
|
||||
~& [%events-not-array rep]
|
||||
!!
|
||||
=* changes p.res.rep
|
||||
~? &(debug=| (gth (lent changes) 0))
|
||||
:* %processing-changes
|
||||
changes=(lent changes)
|
||||
block=last-heard-block.eye
|
||||
id=filter-id.eye
|
||||
==
|
||||
|- ^+ +>.^$
|
||||
?~ changes +>.^$
|
||||
=. +>.^$
|
||||
(take-event-log (parse-event-log i.changes))
|
||||
$(changes t.changes)
|
||||
::
|
||||
:: +take-event-log: obtain changes from event-log
|
||||
::
|
||||
++ take-event-log
|
||||
|= log=event-log
|
||||
^+ +>
|
||||
?~ mined.log
|
||||
~& %ignoring-unmined-event
|
||||
+>
|
||||
=* place u.mined.log
|
||||
?: (~(has in heard.eye) block-number.place log-index.place)
|
||||
?. removed.u.mined.log
|
||||
~? debug=|
|
||||
[%ignoring-duplicate-event tx=transaction-hash.u.mined.log]
|
||||
+>
|
||||
:: block was reorganized away, so rewind to this block and
|
||||
:: start syncing again.
|
||||
::
|
||||
~& :* 'removed event! Perhaps chain has reorganized?'
|
||||
tx-hash=transaction-hash.u.mined.log
|
||||
block-number=block-number.u.mined.log
|
||||
block-hash=block-hash.u.mined.log
|
||||
==
|
||||
%= +>
|
||||
rewind-block
|
||||
:- ~
|
||||
?~ rewind-block
|
||||
block-number.place
|
||||
(min block-number.place u.rewind-block)
|
||||
==
|
||||
=. last-heard-block.eye
|
||||
(max block-number.place last-heard-block.eye)
|
||||
?: ?& (gte block-number.place from-block.eye)
|
||||
?| ?=(~ to-block.eye)
|
||||
(lte block-number.place u.to-block.eye)
|
||||
==
|
||||
==
|
||||
(put-log log)
|
||||
~& :* %event-block-out-of-range
|
||||
got=block-number.place
|
||||
from=from-block.eye
|
||||
to=to-block.eye
|
||||
==
|
||||
+>.$
|
||||
::
|
||||
:: +restore-block: rewind to block or earlier
|
||||
::
|
||||
++ restore-block
|
||||
|= block=@ud
|
||||
^+ +>
|
||||
=/ old-qeu snaps.sap.eye
|
||||
:: clear history
|
||||
::
|
||||
=: snaps.sap.eye ~
|
||||
count.sap.eye 0
|
||||
latest-block.sap.eye 0
|
||||
==
|
||||
:: find a snapshot we can use, remove ones that are too new
|
||||
::
|
||||
=^ snap=snapshot +>.$
|
||||
?: |(=(~ old-qeu) (lth block last-heard-block:(need ~(top to old-qeu))))
|
||||
[%*(. *snapshot last-heard-block from-block.eye) +>.$]
|
||||
|- ^- [snapshot _+>.^$]
|
||||
=^ snap=snapshot old-qeu
|
||||
~(get to old-qeu)
|
||||
=: count.sap.eye +(count.sap.eye)
|
||||
latest-block.sap.eye last-heard-block.snap
|
||||
snaps.sap.eye (~(put to snaps.sap.eye) snap)
|
||||
==
|
||||
?: |(=(~ old-qeu) (lth block last-heard-block:(need ~(top to old-qeu))))
|
||||
[snap +>.^$]
|
||||
$
|
||||
~& [%restoring-block block last-heard-block.snap]
|
||||
(restore-snap snap)
|
||||
::
|
||||
:: +restore-snap: revert state to snapshot
|
||||
::
|
||||
++ restore-snap
|
||||
|= snap=snapshot
|
||||
^+ +>
|
||||
:: notify subscribers
|
||||
::TODO be more nuanced about what changed, maybe
|
||||
::
|
||||
=. +>.$ (fan-diff snap+snap)
|
||||
:: restore state and kick new fetch cycle
|
||||
::
|
||||
%= get-latest-block
|
||||
last-heard-block.eye last-heard-block.snap
|
||||
heard.eye heard.snap
|
||||
logs.eye logs.snap
|
||||
==
|
||||
--
|
||||
--
|
269
app/tiebout.hoon
Normal file
269
app/tiebout.hoon
Normal file
@ -0,0 +1,269 @@
|
||||
/- hall, tiebout
|
||||
=, tiebout
|
||||
=, eyre
|
||||
|%
|
||||
+$ move [bone card]
|
||||
::
|
||||
+$ card
|
||||
$% [%poke wire dock poke]
|
||||
[%peer wire dock path]
|
||||
[%pull wire dock ~]
|
||||
[%diff diff]
|
||||
[%hiss wire [~ ~] %httr %hiss hiss]
|
||||
==
|
||||
::
|
||||
+$ diff
|
||||
$% [%hall-rumor rumor:hall]
|
||||
[%tiebout-action action]
|
||||
==
|
||||
::
|
||||
+$ poke
|
||||
$% [%tiebout-action action]
|
||||
==
|
||||
::
|
||||
+$ state
|
||||
$% [%0 tiebout-zero]
|
||||
==
|
||||
::
|
||||
+$ tiebout-zero
|
||||
$:
|
||||
:: iOS device token
|
||||
::
|
||||
token=@t
|
||||
:: ship that routes notifications to Apple
|
||||
::
|
||||
king=@p
|
||||
:: url of Apple server to send notifications to
|
||||
::
|
||||
baseurl=@t
|
||||
:: name and last read
|
||||
::
|
||||
circles=(map name:hall @)
|
||||
==
|
||||
::
|
||||
--
|
||||
::
|
||||
:: state:
|
||||
::
|
||||
|_ [bol=bowl:gall sta=state]
|
||||
::
|
||||
:: +this: app core subject
|
||||
::
|
||||
++ this .
|
||||
::
|
||||
:: +prep: set up app state, upgrade app state
|
||||
::
|
||||
++ prep
|
||||
|= old=(unit state)
|
||||
^- (quip move _this)
|
||||
?~ old
|
||||
:- ~
|
||||
%= this
|
||||
king.sta ~dabben-larbet
|
||||
baseurl.sta 'https://api.push.apple.com/3/device/'
|
||||
==
|
||||
?- -.u.old
|
||||
%0
|
||||
[~ this(sta u.old)]
|
||||
==
|
||||
::
|
||||
:: +coup: receive acknowledgement for poke, print error if it failed
|
||||
::
|
||||
++ coup
|
||||
|= [wir=wire err=(unit tang)]
|
||||
^- (quip move _this)
|
||||
?~ err
|
||||
[~ this]
|
||||
(mean u.err)
|
||||
::
|
||||
:: +poke-noun: receive debugging actions
|
||||
::
|
||||
++ poke-noun
|
||||
|= act=action
|
||||
^- (quip move _this)
|
||||
(poke-tiebout-action act)
|
||||
::
|
||||
:: +poke-tiebout-action: main action handler
|
||||
::
|
||||
++ poke-tiebout-action
|
||||
|= act=action
|
||||
^- (quip move _this)
|
||||
?- -.act
|
||||
$king (set-king +.act)
|
||||
$token (set-token +.act)
|
||||
$baseurl (set-baseurl +.act)
|
||||
$add-circle (add-circle +.act)
|
||||
$del-circle (del-circle +.act)
|
||||
$notify (send-notify +.act)
|
||||
==
|
||||
::
|
||||
:: +add-circle: add circle and subscribe for updates
|
||||
::
|
||||
++ add-circle
|
||||
|= nom=name:hall
|
||||
^- (quip move _this)
|
||||
:_ this(circles.sta (~(put by circles.sta) nom 0))
|
||||
[ost.bol %peer /our/[nom] [our.bol %hall] /circle/[nom]/config/grams]~
|
||||
::
|
||||
:: +del-circle: delete circle and unsubscribe from updates
|
||||
::
|
||||
++ del-circle
|
||||
|= nom=name:hall
|
||||
^- (quip move _this)
|
||||
:_ this(circles.sta (~(del by circles.sta) nom))
|
||||
[ost.bol %pull /our/[nom] [our.bol %hall] ~]~
|
||||
::
|
||||
:: +set-king: set king @p
|
||||
::
|
||||
++ set-king
|
||||
|= kng=@p
|
||||
^- (quip move _this)
|
||||
[~ this(king.sta kng)]
|
||||
::
|
||||
:: +set-token: set iOS device token @t
|
||||
::
|
||||
++ set-token
|
||||
|= tok=@t
|
||||
^- (quip move _this)
|
||||
[~ this(token.sta tok)]
|
||||
::
|
||||
:: +set-baseurl: set base url @t
|
||||
::
|
||||
++ set-baseurl
|
||||
|= burl=@t
|
||||
^- (quip move _this)
|
||||
[~ this(baseurl.sta burl)]
|
||||
::
|
||||
:: +send-notify: if king, send hiss. if not, do nothing.
|
||||
::
|
||||
++ send-notify
|
||||
|= not=notification
|
||||
^- (quip move _this)
|
||||
?: =(king.sta our.bol)
|
||||
:_ this
|
||||
[ost.bol %hiss /request [~ ~] %httr %hiss (create-apns-request not)]~
|
||||
[~ this]
|
||||
::
|
||||
:: +diff-hall-prize: receive new circle data
|
||||
::
|
||||
++ diff-hall-prize
|
||||
|= [wir=wire piz=prize:hall]
|
||||
^- (quip move _this)
|
||||
?+ wir
|
||||
(mean [leaf+"invalid wire for diff: {(spud wir)}"]~)
|
||||
::
|
||||
:: %our: set config of circle and iterate through messages, sending
|
||||
:: notifications for all messages where number is higher than our last-read
|
||||
::
|
||||
{%our @ @}
|
||||
?> ?=(%circle -.piz)
|
||||
=/ nom/name:hall i.t.wir
|
||||
=/ red/@ud red.loc.cos.piz
|
||||
[~ this(circles.sta (~(put by circles.sta) nom red))]
|
||||
==
|
||||
::
|
||||
:: +reap: recieve acknowledgement for peer
|
||||
::
|
||||
++ reap
|
||||
|= [wir=wire err=(unit tang)]
|
||||
^- (quip move _this)
|
||||
?~ err
|
||||
[~ this]
|
||||
?+ wir
|
||||
(mean [leaf+"invalid wire for diff: {(spud wir)}"]~)
|
||||
::
|
||||
{%our @ @}
|
||||
?< ?=(~ t.wir)
|
||||
[~ this]
|
||||
==
|
||||
::
|
||||
:: +quit: receive subscription failed, resubscribe
|
||||
::
|
||||
++ quit
|
||||
|= wir=wire
|
||||
^- (quip move _this)
|
||||
?+ wir
|
||||
(mean [leaf+"invalid wire for diff: {(spud wir)}"]~)
|
||||
::
|
||||
{%our @ @}
|
||||
?< ?=(~ t.wir)
|
||||
:_ this
|
||||
=/ doc/dock [our.bol %hall]
|
||||
[ost.bol %peer /our/[i.t.wir] doc /circle/[i.t.wir]/config/grams]~
|
||||
==
|
||||
|
||||
::
|
||||
:: +diff-hall-rumor: receive message or a read event from a hall circle
|
||||
::
|
||||
++ diff-hall-rumor
|
||||
|= [wir=wire rum=rumor:hall]
|
||||
^- (quip move _this)
|
||||
?+ wir
|
||||
(mean [leaf+"invalid wire for diff: {(spud wir)}"]~)
|
||||
::
|
||||
:: %our
|
||||
::
|
||||
{%our @ @}
|
||||
?> ?=(%circle -.rum)
|
||||
=/ nom/name:hall i.t.wir
|
||||
?+ -.rum.rum
|
||||
[~ this]
|
||||
::
|
||||
:: %gram: send notification if envelope is lower than read number
|
||||
::
|
||||
%gram
|
||||
=/ red (~(get by circles.sta) nom)
|
||||
?~ red
|
||||
(mean [leaf+"invalid circle for diff: {(spud wir)}"]~)
|
||||
?: (gth num.nev.rum.rum u.red)
|
||||
:_ this(circles.sta (~(put by circles.sta) nom u.red))
|
||||
(conditional-msg-to-not u.red nev.rum.rum)
|
||||
:_ this
|
||||
(conditional-msg-to-not u.red nev.rum.rum)
|
||||
::
|
||||
:: %config: set our read number
|
||||
::
|
||||
%config
|
||||
?+ -.dif.rum.rum
|
||||
[~ this]
|
||||
::
|
||||
%read
|
||||
[~ this(circles.sta (~(put by circles.sta) nom red.dif.rum.rum))]
|
||||
==
|
||||
==
|
||||
==
|
||||
::
|
||||
:: generate notification move from hall message if conditions are met
|
||||
::
|
||||
++ conditional-msg-to-not
|
||||
|= [red=@ud env=envelope:hall]
|
||||
^- (list move)
|
||||
?: =(aut.gam.env our.bol)
|
||||
~
|
||||
=/ pay %- my :~
|
||||
alert+s+'New message from {(cite:title aut.gam.env)}'
|
||||
==
|
||||
=/ not/notification [token.sta 'com.tlon.urbit-client' pay]
|
||||
?: (lte num.env red)
|
||||
~
|
||||
=/ doc/dock [king.sta dap.bol]
|
||||
[ost.bol %poke /ask-king doc %tiebout-action [%notify not]]~
|
||||
|
||||
::
|
||||
:: +create-apns-request: create hiss with payload for APNs
|
||||
::
|
||||
++ create-apns-request
|
||||
|= not=notification
|
||||
^- hiss
|
||||
=/ furl=@t (crip (weld (trip baseurl.sta) (trip token.not)))
|
||||
=/ url=purl (need (de-purl:html furl))
|
||||
=/ jon=json :- %o
|
||||
%- my :~
|
||||
aps+o+payload.not
|
||||
==
|
||||
:^ url %post
|
||||
%- my :~
|
||||
apns-topic+[topic.not ~] :: generate map from raw noun
|
||||
==
|
||||
(some (as-octt:mimes:html (en-json:html jon)))
|
||||
--
|
@ -5,35 +5,89 @@
|
||||
::
|
||||
=+ [pad=& url=|]
|
||||
|%
|
||||
::
|
||||
+$ byte @D
|
||||
+$ word24 @
|
||||
::
|
||||
++ div-ceil
|
||||
:: divide, rounding up.
|
||||
|= [x=@ y=@] ^- @
|
||||
?: =(0 (mod x y))
|
||||
(div x y)
|
||||
+((div x y))
|
||||
::
|
||||
++ explode-bytes
|
||||
:: Explode a bytestring into list of bytes. Result is in LSB order.
|
||||
|= =octs ^- (list byte)
|
||||
=/ atom-byte-width (met 3 q.octs)
|
||||
=/ leading-zeros (sub p.octs atom-byte-width)
|
||||
(weld (reap leading-zeros 0) (rip 3 q.octs))
|
||||
::
|
||||
++ explode-words
|
||||
:: Explode a bytestring to words of bit-width `wid`. Result is in LSW order.
|
||||
|= [wid=@ =octs]
|
||||
^- (list @)
|
||||
=/ atom-bit-width (met 0 q.octs)
|
||||
=/ octs-bit-width (mul 8 p.octs)
|
||||
=/ atom-word-width (div-ceil atom-bit-width wid)
|
||||
=/ rslt-word-width (div-ceil octs-bit-width wid)
|
||||
=/ pad (sub rslt-word-width atom-word-width)
|
||||
=/ x (ripn wid q.octs)
|
||||
%+ weld x
|
||||
(reap pad 0)
|
||||
::
|
||||
:: +en:base64: encode +octs to base64 cord
|
||||
::
|
||||
:: Encode an `octs` into a base64 string.
|
||||
::
|
||||
:: First, we break up the input into a list of 24-bit words. The input
|
||||
:: might not be a multiple of 24-bits, so we add 0-2 padding bytes at
|
||||
:: the end (to the least-significant side, with a left-shift).
|
||||
::
|
||||
:: Then, we encode each block into four base64 characters.
|
||||
::
|
||||
:: Finally we remove the padding that we added at the beginning: for
|
||||
:: each byte that was added, we replace one character with an = (unless
|
||||
:: `pad` is false, in which case we just remove the extra characters).
|
||||
::
|
||||
++ en
|
||||
|= inp=octs
|
||||
^- cord
|
||||
:: dif: offset from 3-byte block
|
||||
^- $-(octs cord)
|
||||
::
|
||||
=/ dif=@ud (~(dif fo 3) 0 p.inp)
|
||||
:: dap: reversed, 3-byte block-aligned input
|
||||
::
|
||||
=/ dap=@ux (lsh 3 dif (rev 3 inp))
|
||||
=/ cha
|
||||
?: url
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||
%- crip
|
||||
%- flop
|
||||
%+ weld
|
||||
?.(pad ~ (reap dif '='))
|
||||
%+ slag dif
|
||||
|- ^- tape
|
||||
?: =(0x0 dap) ~
|
||||
=/ d (end 3 3 dap)
|
||||
:* (cut 3 [(cut 0 [0 6] d) 1] cha)
|
||||
(cut 3 [(cut 0 [6 6] d) 1] cha)
|
||||
(cut 3 [(cut 0 [12 6] d) 1] cha)
|
||||
(cut 3 [(cut 0 [18 6] d) 1] cha)
|
||||
$(dap (rsh 3 3 dap))
|
||||
==
|
||||
::
|
||||
|^ |= bs=octs ^- cord
|
||||
=+ ^- [padding=@ blocks=(list word24)]
|
||||
(octs-to-blocks bs)
|
||||
(crip (flop (unpad padding (encode-blocks blocks))))
|
||||
::
|
||||
++ octs-to-blocks
|
||||
|= bs=octs ^- [padding=@ud (list word24)]
|
||||
=/ padding=@ud (~(dif fo 3) 0 p.bs)
|
||||
=/ padded=octs [(add padding p.bs) (lsh 3 padding (rev 3 bs))]
|
||||
[padding (explode-words 24 padded)]
|
||||
::
|
||||
++ unpad
|
||||
|= [extra=@ t=tape] ^- tape
|
||||
=/ without (slag extra t)
|
||||
?. pad without
|
||||
(weld (reap extra '=') without)
|
||||
::
|
||||
++ encode-blocks
|
||||
|= ws=(list word24) ^- tape
|
||||
(zing (turn ws encode-block))
|
||||
::
|
||||
++ encode-block
|
||||
|= w=word24 ^- tape
|
||||
=/ a (cut 3 [(cut 0 [0 6] w) 1] cha)
|
||||
=/ b (cut 3 [(cut 0 [6 6] w) 1] cha)
|
||||
=/ c (cut 3 [(cut 0 [12 6] w) 1] cha)
|
||||
=/ d (cut 3 [(cut 0 [18 6] w) 1] cha)
|
||||
~[a b c d]
|
||||
--
|
||||
::
|
||||
:: +de:base64: decode base64 cord to (unit @)
|
||||
::
|
||||
++ de
|
||||
|
38
lib/eth-watcher.hoon
Normal file
38
lib/eth-watcher.hoon
Normal file
@ -0,0 +1,38 @@
|
||||
:: eth-watcher utilities
|
||||
::
|
||||
/- *eth-watcher
|
||||
::
|
||||
|%
|
||||
:: +log-to-id: extract the event-id from an event-log
|
||||
::
|
||||
++ log-to-id
|
||||
|= log=event-log:rpc:ethereum
|
||||
^- event-id:ethereum
|
||||
?> ?=(^ mined.log)
|
||||
:- block-number.u.mined.log
|
||||
log-index.u.mined.log
|
||||
::
|
||||
:: +store-new-logs: add logs to an old loglist, ensuring newest-first ordering
|
||||
::
|
||||
:: assumes :new is already ordered newest-first
|
||||
::
|
||||
++ store-new-logs
|
||||
|= [new=loglist old=loglist]
|
||||
^- loglist
|
||||
?~ new old
|
||||
=+ new-place=(log-to-id i.new)
|
||||
|-
|
||||
?~ old [i.new old]
|
||||
=+ old-place=(log-to-id i.old)
|
||||
:: if the :old-place is older than :new-place,
|
||||
:: put :new-place down, and grab the next one from :new
|
||||
:: otherwise, keep looking through :old
|
||||
::
|
||||
?: ?| (gth block.new-place block.old-place)
|
||||
?& =(block.new-place block.old-place)
|
||||
(gth log.new-place log.old-place)
|
||||
==
|
||||
==
|
||||
[i.new ^$(new t.new)]
|
||||
[i.old $(old t.old)]
|
||||
--
|
@ -15,7 +15,7 @@
|
||||
;div#root
|
||||
;+ inner
|
||||
==
|
||||
;script@"/~~/landscape/js/index-min.js";
|
||||
;script@"/~~/landscape/js/index.js";
|
||||
==
|
||||
::
|
||||
==
|
||||
|
7
mar/eth-watcher/action.hoon
Normal file
7
mar/eth-watcher/action.hoon
Normal file
@ -0,0 +1,7 @@
|
||||
/- *eth-watcher
|
||||
|_ act=action
|
||||
++ grab
|
||||
|%
|
||||
++ noun action
|
||||
--
|
||||
--
|
7
mar/eth-watcher/update.hoon
Normal file
7
mar/eth-watcher/update.hoon
Normal file
@ -0,0 +1,7 @@
|
||||
/- *eth-watcher
|
||||
|_ upd=update
|
||||
++ grab
|
||||
|%
|
||||
++ noun update
|
||||
--
|
||||
--
|
@ -44,6 +44,7 @@
|
||||
%- of :~
|
||||
stdout+none
|
||||
output-file+so
|
||||
output-pill+so
|
||||
output-clay+(su (easy /sentinel/path))
|
||||
url+(su auri:de-purl:html)
|
||||
to-api+(su ;~(plug sym ;~(pfix col prn)))
|
||||
|
@ -3,6 +3,8 @@
|
||||
::
|
||||
/? 310
|
||||
/- sole
|
||||
/+ base64
|
||||
!:
|
||||
::
|
||||
::::
|
||||
::
|
||||
@ -53,6 +55,11 @@
|
||||
?+ -.sef ~
|
||||
$tan (wall (turn (flop p.sef) |=(a/tank ~(ram re a))))
|
||||
$txt s+(crip p.sef)
|
||||
$sag
|
||||
=/ =atom (jam q.sef)
|
||||
=/ =octs [(met 3 atom) atom]
|
||||
=/ enc (en:base64 octs)
|
||||
(pairs file+s+(crip <`path`p.sef>) data+s+enc ~)
|
||||
$sav
|
||||
(pairs file+s+(crip <`path`p.sef>) data+s+(crip (en-base64:mimes:html q.sef)) ~)
|
||||
::
|
||||
|
33
mar/tiebout-action.hoon
Normal file
33
mar/tiebout-action.hoon
Normal file
@ -0,0 +1,33 @@
|
||||
/- hall, tiebout
|
||||
=, format
|
||||
::
|
||||
|_ act=action:tiebout
|
||||
::
|
||||
++ grow
|
||||
|%
|
||||
++ tank >act<
|
||||
--
|
||||
::
|
||||
++ grab
|
||||
|%
|
||||
++ noun action:tiebout
|
||||
++ json
|
||||
|= jon=^json
|
||||
^- action:tiebout
|
||||
=< (action jon)
|
||||
|%
|
||||
++ action
|
||||
%- of:dejs
|
||||
:~ token+so:dejs
|
||||
add-circle+sa
|
||||
del-circle+sa
|
||||
==
|
||||
++ sa :: string as ta
|
||||
|= jon=^json
|
||||
?> ?=([%s *] jon)
|
||||
(scot %tas p.jon)
|
||||
--
|
||||
--
|
||||
::
|
||||
--
|
||||
|
39
sur/eth-watcher.hoon
Normal file
39
sur/eth-watcher.hoon
Normal file
@ -0,0 +1,39 @@
|
||||
:: watcher: ethereum event log collector
|
||||
::
|
||||
|%
|
||||
++ name @tas
|
||||
::
|
||||
++ config
|
||||
$: node=purl:eyre
|
||||
from-block=@ud
|
||||
to-block=(unit @ud)
|
||||
contracts=(list address:ethereum)
|
||||
topics=(list $@(@ux (list @ux)))
|
||||
==
|
||||
::
|
||||
++ action
|
||||
$% [%watch =name =config]
|
||||
::TODO support modifying existing config for future polling
|
||||
[%clear =name]
|
||||
==
|
||||
::
|
||||
++ update
|
||||
$% :: %snap: all known-good logs, sent on-subscribe and on-reorg
|
||||
::TODO there's probably a way to be more nuanced about what we forgot
|
||||
:: to cope with a reorg
|
||||
::
|
||||
[%snap =snapshot]
|
||||
:: %vent: newly added logs
|
||||
::
|
||||
[%logs =loglist]
|
||||
==
|
||||
::
|
||||
++ snapshot
|
||||
$: last-heard-block=@ud
|
||||
heard=(set event-id:ethereum)
|
||||
logs=loglist
|
||||
==
|
||||
::
|
||||
++ loglist
|
||||
(list event-log:rpc:ethereum) :: newest first
|
||||
--
|
@ -19,6 +19,7 @@
|
||||
++ sink
|
||||
$% {$stdout ~}
|
||||
{$output-file pax/@t}
|
||||
{$output-pill pax/@t}
|
||||
{$output-clay pax/path}
|
||||
{$url url/purl:eyre}
|
||||
{$to-api api/term command/@t}
|
||||
|
21
sur/tiebout.hoon
Normal file
21
sur/tiebout.hoon
Normal file
@ -0,0 +1,21 @@
|
||||
/- hall
|
||||
=, eyre
|
||||
::
|
||||
::
|
||||
|%
|
||||
+$ notification
|
||||
$: token=@t
|
||||
topic=@t
|
||||
payload=(map @t json)
|
||||
==
|
||||
::
|
||||
+$ action
|
||||
$% [%token tok=@t] :: set device token
|
||||
[%king kng=@p] :: set ship to route notifications through
|
||||
[%baseurl bur=@t] :: set url to send notifications to
|
||||
[%notify not=notification] :: send notification
|
||||
[%add-circle nom=name:hall] :: send notifications for this circle
|
||||
[%del-circle nom=name:hall] :: stop sending for this circle
|
||||
==
|
||||
::
|
||||
--
|
@ -956,12 +956,21 @@
|
||||
(sub len (met boz dat))
|
||||
(swp boz dat)
|
||||
::
|
||||
:: Like `rip` but produces n-bit blocks instead of 2^n bit blocks.
|
||||
::
|
||||
++ ripn
|
||||
~/ %ripn
|
||||
|= {bits=@ud x=@}
|
||||
^- (list @)
|
||||
?: =(0 x) ~
|
||||
[(end 0 bits x) $(x (rsh 0 bits x))]
|
||||
::
|
||||
++ rip :: disassemble
|
||||
~/ %rip
|
||||
|= {a/bloq b/@}
|
||||
|= {=bloq x=@}
|
||||
^- (list @)
|
||||
?: =(0 b) ~
|
||||
[(end a 1 b) $(b (rsh a 1 b))]
|
||||
?: =(0 x) ~
|
||||
[(end bloq 1 x) $(x (rsh bloq 1 x))]
|
||||
::
|
||||
++ rsh :: right-shift
|
||||
~/ %rsh
|
||||
@ -15369,6 +15378,7 @@
|
||||
{$code p/tape} :: code literal
|
||||
{$text p/tape} :: text symbol
|
||||
{$link p/(list graf) q/tape} :: URL
|
||||
{$mage p/tape q/tape} :: image
|
||||
{$expr p/tuna:hoot} :: interpolated hoon
|
||||
==
|
||||
--
|
||||
@ -15497,7 +15507,7 @@
|
||||
[[lin `~] +<.^$]
|
||||
[[lin ~] eat-newline]
|
||||
::
|
||||
++ look :: inspedt line
|
||||
++ look :: inspect line
|
||||
^- (unit trig)
|
||||
%+ bind (wonk (look:parse loc txt))
|
||||
|= a/trig ^+ a
|
||||
@ -15856,6 +15866,16 @@
|
||||
(ifix [lit rit] (cash rit))
|
||||
==
|
||||
::
|
||||
:: ![alt text](url)
|
||||
::
|
||||
%+ stag %mage
|
||||
;~ pfix zap
|
||||
;~ (glue (punt whit))
|
||||
(ifix [lac rac] (cash rac))
|
||||
(ifix [lit rit] (cash rit))
|
||||
==
|
||||
==
|
||||
::
|
||||
:: #hoon
|
||||
::
|
||||
%+ stag %list
|
||||
@ -15942,6 +15962,7 @@
|
||||
`(list graf)`[%text (tufa ~-~201d. ~)]~
|
||||
==
|
||||
$link [[%a [%href q.nex] ~] ^$(gaf p.nex)]~
|
||||
$mage [[%img [%src q.nex] ?~(p.nex ~ [%alt p.nex]~)] ~]~
|
||||
==
|
||||
--
|
||||
::
|
||||
|
@ -6,7 +6,7 @@
|
||||
=, ames
|
||||
:: this number needs to be below 8
|
||||
::
|
||||
=+ protocol-version=1
|
||||
=+ protocol-version=2
|
||||
|%
|
||||
+= move [p=duct q=(wind note:able gift:able)] :: local move
|
||||
:: |pact: internal packet structures
|
||||
|
@ -1798,8 +1798,7 @@
|
||||
:* hen %pass
|
||||
[%foreign-x (scot %p our) (scot %p her) syd car (scot cas) pax]
|
||||
%f %build live=%.n %pin
|
||||
:: XX perhaps should be now as in ++validate-plops
|
||||
(case-to-date cas)
|
||||
now
|
||||
(vale-page [her syd] peg)
|
||||
==
|
||||
::
|
||||
|
@ -990,7 +990,7 @@
|
||||
?. ?=($json p.p.cuf)
|
||||
:: ~> %slog.`%*(. >[%backing p.p.cuf %q-p-cuf]< &3.+> (sell q.p.cuf))
|
||||
(back-turbo tee %json p.cuf)
|
||||
(get-rush:(ire-ix p.tee) q.tee ((hard json) q.q.p.cuf))
|
||||
(get-rush:(ire-ix p.tee) q.tee (,json q.q.p.cuf))
|
||||
::
|
||||
$quit (get-quit:(ire-ix p.tee) q.tee)
|
||||
==
|
||||
@ -1066,7 +1066,7 @@
|
||||
=/ cay=cage (result-to-cage:ford build-result.result.sih)
|
||||
%+ get-rush:(ire-ix p.tee) q.tee
|
||||
?> ?=($json p.cay) :: XX others
|
||||
((hard json) q.q.cay)
|
||||
(,json q.q.cay)
|
||||
==
|
||||
==
|
||||
::
|
||||
|
@ -6736,6 +6736,13 @@
|
||||
:: ::::
|
||||
++ chrono ^?
|
||||
|%
|
||||
:: +from-unix: unix timestamp to @da
|
||||
::
|
||||
++ from-unix
|
||||
|= timestamp=@ud
|
||||
^- @da
|
||||
%+ add ~1970.1.1
|
||||
(mul timestamp ~s1)
|
||||
:: :: ++dawn:chrono:
|
||||
++ dawn :: Jan 1 weekday
|
||||
|= yer/@ud
|
||||
@ -7334,68 +7341,68 @@
|
||||
::
|
||||
?: =(i.topics.log owner-changed)
|
||||
=+ ^- [who=@ wer=address]
|
||||
(decode-topics topics.log ~[%uint %address])
|
||||
(decode-topics t.topics.log ~[%uint %address])
|
||||
`[who %owner wer]
|
||||
::
|
||||
?: =(i.topics.log activated)
|
||||
=/ who=@
|
||||
(decode-topics topics.log ~[%uint])
|
||||
(decode-topics t.topics.log ~[%uint])
|
||||
`[who %activated who]
|
||||
::
|
||||
?: =(i.topics.log spawned)
|
||||
=+ ^- [pre=@ who=@]
|
||||
(decode-topics topics.log ~[%uint %uint])
|
||||
(decode-topics t.topics.log ~[%uint %uint])
|
||||
`[pre %spawned who]
|
||||
::
|
||||
?: =(i.topics.log escape-requested)
|
||||
=+ ^- [who=@ wer=@]
|
||||
(decode-topics topics.log ~[%uint %uint])
|
||||
(decode-topics t.topics.log ~[%uint %uint])
|
||||
`[who %escape `wer]
|
||||
::
|
||||
?: =(i.topics.log escape-canceled)
|
||||
=/ who=@ (decode-topics topics.log ~[%uint])
|
||||
=/ who=@ (decode-topics t.topics.log ~[%uint])
|
||||
`[who %escape ~]
|
||||
::
|
||||
?: =(i.topics.log escape-accepted)
|
||||
=+ ^- [who=@ wer=@]
|
||||
(decode-topics topics.log ~[%uint %uint])
|
||||
(decode-topics t.topics.log ~[%uint %uint])
|
||||
`[who %sponsor & wer]
|
||||
::
|
||||
?: =(i.topics.log lost-sponsor)
|
||||
=+ ^- [who=@ pos=@]
|
||||
(decode-topics topics.log ~[%uint %uint])
|
||||
(decode-topics t.topics.log ~[%uint %uint])
|
||||
`[who %sponsor | pos]
|
||||
::
|
||||
?: =(i.topics.log changed-keys)
|
||||
=/ who=@ (decode-topics topics.log ~[%uint])
|
||||
=/ who=@ (decode-topics t.topics.log ~[%uint])
|
||||
=+ ^- [enc=octs aut=octs sut=@ud rev=@ud]
|
||||
%+ decode-results data.log
|
||||
~[[%bytes-n 32] [%bytes-n 32] %uint %uint]
|
||||
`[who %keys rev (pass-from-eth enc aut sut)]
|
||||
::
|
||||
?: =(i.topics.log broke-continuity)
|
||||
=/ who=@ (decode-topics topics.log ~[%uint])
|
||||
=/ who=@ (decode-topics t.topics.log ~[%uint])
|
||||
=/ num=@ (decode-results data.log ~[%uint])
|
||||
`[who %continuity num]
|
||||
::
|
||||
?: =(i.topics.log changed-management-proxy)
|
||||
=+ ^- [who=@ sox=address]
|
||||
(decode-topics topics.log ~[%uint %address])
|
||||
(decode-topics t.topics.log ~[%uint %address])
|
||||
`[who %management-proxy sox]
|
||||
::
|
||||
?: =(i.topics.log changed-voting-proxy)
|
||||
=+ ^- [who=@ tox=address]
|
||||
(decode-topics topics.log ~[%uint %address])
|
||||
(decode-topics t.topics.log ~[%uint %address])
|
||||
`[who %voting-proxy tox]
|
||||
::
|
||||
?: =(i.topics.log changed-spawn-proxy)
|
||||
=+ ^- [who=@ sox=address]
|
||||
(decode-topics topics.log ~[%uint %address])
|
||||
(decode-topics t.topics.log ~[%uint %address])
|
||||
`[who %spawn-proxy sox]
|
||||
::
|
||||
?: =(i.topics.log changed-transfer-proxy)
|
||||
=+ ^- [who=@ tox=address]
|
||||
(decode-topics topics.log ~[%uint %address])
|
||||
(decode-topics t.topics.log ~[%uint %address])
|
||||
`[who %transfer-proxy tox]
|
||||
::
|
||||
:: warn about unimplemented events, but ignore
|
||||
@ -7890,6 +7897,7 @@
|
||||
adr=(list address)
|
||||
top=(list ?(@ux (list @ux)))
|
||||
==
|
||||
[%eth-get-block-by-number bon=@ud txs=?]
|
||||
[%eth-get-filter-logs fid=@ud]
|
||||
$: %eth-get-logs
|
||||
fro=(unit block)
|
||||
@ -8046,6 +8054,12 @@
|
||||
:+ ~ 'topics'
|
||||
(topics-to-json top.req)
|
||||
==
|
||||
::
|
||||
%eth-get-block-by-number
|
||||
:- 'eth_getBlockByNumber'
|
||||
:~ (tape (num-to-hex bon.req))
|
||||
b+txs.req
|
||||
==
|
||||
::
|
||||
%eth-get-filter-logs
|
||||
['eth_getFilterLogs' (tape (num-to-hex fid.req)) ~]
|
||||
|
@ -14,6 +14,37 @@
|
||||
--
|
||||
::
|
||||
|%
|
||||
++ test-explode-bytes
|
||||
;: weld
|
||||
%+ expect-eq
|
||||
!> ~
|
||||
!> (flop (explode-bytes:base64 [0 `@`0]))
|
||||
::
|
||||
%+ expect-eq
|
||||
!> ~[0x0 0x0 0x0]
|
||||
!> (flop (explode-bytes:base64 [3 `@`0]))
|
||||
::
|
||||
%+ expect-eq
|
||||
!> ~[0x1 0x1 0x1]
|
||||
!> (flop (explode-bytes:base64 [3 `@`0x1.0101]))
|
||||
==
|
||||
::
|
||||
++ test-explode-words
|
||||
;: weld
|
||||
%+ expect-eq
|
||||
!> ~
|
||||
!> (flop (explode-words:base64 1 [0 `@`0]))
|
||||
::
|
||||
%+ expect-eq
|
||||
!> ~[0 0 0 0 0 0 0 1]
|
||||
!> (flop (explode-words:base64 3 [3 `@`1]))
|
||||
::
|
||||
%+ expect-eq
|
||||
!> ~[0x0 0x12.3456 0x78.9abc 0xde.f012 0x34.5678]
|
||||
!> =/ inp [15 `@`0x1234.5678.9abc.def0.1234.5678]
|
||||
(flop (explode-words:base64 24 inp))
|
||||
==
|
||||
::
|
||||
++ test-base64
|
||||
;: weld
|
||||
%+ expect-eq
|
||||
|
55
tests/sys/hoon/bits.hoon
Normal file
55
tests/sys/hoon/bits.hoon
Normal file
@ -0,0 +1,55 @@
|
||||
/+ *test
|
||||
|%
|
||||
++ test-bits
|
||||
;: weld
|
||||
::
|
||||
:: Random sanity testing
|
||||
::
|
||||
%+ expect-eq
|
||||
!> ~[0x3 0x7 0x7]
|
||||
!> (flop (ripn 3 0xff))
|
||||
%+ expect-eq
|
||||
!> ~[0x1 0xee 0xff]
|
||||
!> (flop (ripn 8 0x1.eeff))
|
||||
%+ expect-eq
|
||||
!> ~[0x1 0xe 0xe 0xf 0xf]
|
||||
!> (flop (ripn 4 0x1.eeff))
|
||||
::
|
||||
:: Typical use-cases
|
||||
::
|
||||
%+ expect-eq
|
||||
!> ~[0x1 0x23.4567 0x89.abcd]
|
||||
!> (flop (ripn 24 0x1.2345.6789.abcd))
|
||||
::
|
||||
:: Edge cases
|
||||
::
|
||||
%+ expect-eq
|
||||
!> ~
|
||||
!> (flop (ripn 31 0x0))
|
||||
%+ expect-eq
|
||||
!> ~
|
||||
!> (flop (ripn 1 0x0))
|
||||
::
|
||||
:: Word boundaries
|
||||
::
|
||||
%+ expect-eq
|
||||
!> ~[0x7fff.ffff]
|
||||
!> (flop (ripn 31 0x7fff.ffff))
|
||||
%+ expect-eq
|
||||
!> ~[0x1 0x7fff.ffff]
|
||||
!> (flop (ripn 31 0xffff.ffff))
|
||||
%+ expect-eq
|
||||
!> ~[0x3 0x7fff.ffff]
|
||||
!> (flop (ripn 31 0x1.ffff.ffff))
|
||||
%+ expect-eq
|
||||
!> ~[0x3 0x7fff.ffff 0x7fff.ffff]
|
||||
!> (flop (ripn 31 0xffff.ffff.ffff.ffff))
|
||||
%+ expect-eq
|
||||
!> ~[0x1 0x1.ffff 0x1.ffff]
|
||||
!> (flop (ripn 17 0x7.ffff.ffff))
|
||||
%+ expect-eq
|
||||
!> ~[0x123 0x456 0x789 0xabc 0xdef 0x12 0x345 0x678]
|
||||
!> (flop (ripn 12 0x1234.5678.9abc.def0.1234.5678))
|
||||
==
|
||||
::
|
||||
--
|
@ -11,7 +11,7 @@
|
||||
^- manx
|
||||
;div
|
||||
;div
|
||||
=urb-component "TopicCreatePage"
|
||||
=urb-component "TopicCreatePage"
|
||||
=urb-ship "{(scow %p p.bem.gas)}"
|
||||
=urb-claypath "{<pax>}"
|
||||
=urb-content "{(trip body)}"
|
||||
|
83033
web/landscape/js/index.js
Normal file
83033
web/landscape/js/index.js
Normal file
File diff suppressed because one or more lines are too long
@ -14,7 +14,7 @@
|
||||
;div.flex-col-2;
|
||||
;div.flex-col-x
|
||||
;div.profile-avatar
|
||||
;div(urb-component "Sigil", urb-size "320", urb-ship "{(scow %p p.bem.gas)}", urb-suffix "false");
|
||||
;div(urb-component "Sigil", urb-size "310", urb-ship "{(scow %p p.bem.gas)}", urb-suffix "false");
|
||||
;div(urb-component "ProfileMsgBtn", urb-ship "{(scow %p p.bem.gas)}");
|
||||
==
|
||||
==
|
||||
|
@ -16,21 +16,6 @@
|
||||
;div.flex-col-2;
|
||||
;div.flex-col-x
|
||||
;a.vanilla.btn.btn-primary(href (trip 'javascript:(function(){document.querySelectorAll("[urb-devices]")[0].classList.add("hide"); document.querySelectorAll("[urb-qr]")[0].classList.remove("hide");})()')): Connect device
|
||||
;h2.mt-6: Devices
|
||||
;h3.text-mono.mt-4: 108.208.53.121
|
||||
;div: Current session
|
||||
;h3.text-mono.mt-4: 67.188.43.52
|
||||
;div: Chrome on OS X 10.12.6
|
||||
;div
|
||||
;span.mr-3: Last login:
|
||||
;span.text-mono: 2018.4.21
|
||||
==
|
||||
;h3.text-mono.mt-4: 43.222.12.64
|
||||
;div: iOS 14.11
|
||||
;div
|
||||
;span.mr-3: Last login:
|
||||
;span.text-mono: 2018.3.12
|
||||
==
|
||||
;div.mt-6
|
||||
;a.h3.vanilla.text-red(href "javascript:void(0)"): Log Out ↓
|
||||
==
|
||||
|
Loading…
Reference in New Issue
Block a user