urbit/app/btc-bridge.hoon

219 lines
5.1 KiB
Plaintext
Raw Normal View History

2020-10-13 15:31:15 +03:00
2020-10-02 13:40:57 +03:00
:: btc-bridge.hoon
:: Proxy for accessing BTC full node
2020-09-27 16:16:33 +03:00
::
/- *btc-bridge, bnh=btc-node-hook
2020-10-13 15:31:15 +03:00
/+ dbug, default-agent, base64, blib=btc-node-json, elib=electrum-rpc-http
2020-09-27 16:16:33 +03:00
|%
+$ versioned-state
$% state-0
==
::
2020-10-09 15:34:36 +03:00
+$ state-0 [%0 =credentials =status]
2020-09-27 16:16:33 +03:00
::
+$ card card:agent:gall
::
--
%- agent:dbug
=| state-0
=* state -
^- agent:gall
2020-10-05 15:21:23 +03:00
=<
2020-09-27 16:16:33 +03:00
|_ =bowl:gall
+* this .
def ~(. (default-agent this %|) bowl)
hc ~(. +> bowl)
::
++ on-init
^- (quip card _this)
2020-10-02 13:40:57 +03:00
~& > '%btc-bridge initialized successfully'
`this(status [%client connected=%.n host=~])
2020-09-27 16:16:33 +03:00
++ on-save
^- vase
!>(state)
++ on-load
|= old-state=vase
^- (quip card _this)
2020-10-02 13:40:57 +03:00
~& > '%btc-bridge recompiled successfully'
2020-09-27 16:16:33 +03:00
`this(state !<(versioned-state old-state))
++ on-poke
|= [=mark =vase]
^- (quip card _this)
2020-10-05 16:01:34 +03:00
:: Only allow poke from our ship, unless we're a host
2020-10-09 15:34:36 +03:00
::
2020-10-05 16:01:34 +03:00
?> ?|((team:title our.bowl src.bowl) ?=(%host -.status))
2020-10-05 15:21:23 +03:00
=^ cards state
?+ mark (on-poke:def mark vase)
%btc-bridge-command
(handle-command:hc !<(command vase))
2020-10-12 11:26:43 +03:00
%btc-bridge-rpc-action
2020-10-13 12:25:37 +03:00
(handle-rpc-action !<(rpc-action vase))
2020-09-27 16:16:33 +03:00
==
2020-10-05 15:21:23 +03:00
[cards this]
2020-09-27 16:16:33 +03:00
++ on-watch on-watch:def
:: TODO: handle /clients path here
:: only allow if we're a host
:: only allow if it's a valid client
::
2020-09-27 16:16:33 +03:00
++ on-leave on-leave:def
++ on-peek on-peek:def
2020-10-09 15:34:36 +03:00
++ on-agent on-agent:def
:: TODO: add our host to status if we're a client when subscription is ack'd here
2020-10-09 15:34:36 +03:00
++ on-arvo
|= [=wire =sign-arvo]
2020-10-02 14:05:41 +03:00
^- (quip card _this)
2020-10-09 15:34:36 +03:00
=* response client-response.sign-arvo
=^ cards state
?+ +<.sign-arvo (on-arvo:def wire sign-arvo)
%http-response
2020-10-13 15:31:15 +03:00
?+ wire (on-arvo:def wire sign-arvo)
[%erpc *]
~& >>> response
`state
[%brpc *]
(btc-http-response:hc wire response)
==
==
2020-10-09 15:34:36 +03:00
[cards this]
::
2020-09-27 16:16:33 +03:00
++ on-fail on-fail:def
--
:: helper core
2020-10-05 15:21:23 +03:00
|_ =bowl:gall
++ handle-command
|= comm=command
^- (quip card _state)
2020-10-05 16:01:34 +03:00
?- -.comm
2020-10-09 15:34:36 +03:00
%become-host
2020-10-12 11:56:32 +03:00
`state(credentials credentials.comm, status [%host connected=%.y clients=*(set ship)])
::
2020-10-05 16:01:34 +03:00
%connect-as-client
:_ state
~[[%pass /connect-client %agent [host.comm %btc-provider] %watch /clients]]
::
2020-10-05 16:01:34 +03:00
%allow-clients
?+ -.status ~&(>>> 'Only a %host can add clients' `state)
%host
`state(clients.status (~(uni in clients.status) users.comm))
==
==
++ is-client
|= user=ship ^- ?
%.n
2020-10-13 12:25:37 +03:00
++ btc-rpc-auth-header
=* user rpc-user.bc.credentials
=* pass rpc-password.bc.credentials
:- 'Authorization'
;: (cury cat 3)
'Basic '
%- ~(en base64 | &)
(as-octs:mimes:html :((cury cat 3) user ':' pass))
==
2020-10-13 15:31:15 +03:00
++ btc-gen-request
2020-10-13 12:25:37 +03:00
|= req=request:bitcoin-core:rpc
2020-10-09 15:34:36 +03:00
^- request:http
2020-10-13 12:25:37 +03:00
=* endpoint rpc-url.bc.credentials
2020-10-09 15:34:36 +03:00
=/ body=request:rpc:jstd
2020-10-13 12:25:37 +03:00
(request-to-rpc:btc-rpc:blib req)
2020-10-09 15:34:36 +03:00
=/ =header-list:http
:~ ['Content-Type' 'application/json']
2020-10-13 12:25:37 +03:00
btc-rpc-auth-header
==
2020-10-09 15:34:36 +03:00
:* %'POST'
endpoint
header-list
=, html
%- some
%- as-octt:mimes
(en-json (request-to-json:rpc:jstd body))
==
::
2020-10-13 15:31:15 +03:00
++ electrum-gen-request
2020-10-13 12:25:37 +03:00
|= req=request:electrum:rpc
2020-10-13 15:31:15 +03:00
%+ request-to-http:electrum-rpc:elib
rpc-url.ec.credentials req
2020-10-13 12:25:37 +03:00
++ gen-request
|= ract=rpc-action
^- request:http
?- -.ract
%erpc
2020-10-13 15:31:15 +03:00
(electrum-gen-request +.ract)
2020-10-13 12:25:37 +03:00
%brpc
2020-10-13 15:31:15 +03:00
(btc-gen-request +.ract)
2020-10-13 12:25:37 +03:00
==
::
++ handle-rpc-action
|= ract=rpc-action
2020-10-09 15:34:36 +03:00
^- (quip card _state)
2020-10-13 15:31:15 +03:00
=/ out-wire=path
/[-.ract]/[(scot %da now.bowl)]
2020-10-09 15:34:36 +03:00
=/ out *outbound-config:iris
=/ req=request:http
2020-10-13 12:25:37 +03:00
(gen-request ract)
2020-10-09 15:34:36 +03:00
:_ state
2020-10-13 15:31:15 +03:00
[%pass out-wire %arvo %i %request req out]~
2020-10-09 15:34:36 +03:00
::
++ httr-to-rpc-response
|= hit=httr:eyre
^- response:rpc:jstd
~| hit
=/ jon=json (need (de-json:html q:(need r.hit)))
?. =(%2 (div p.hit 100))
(parse-error jon)
=, dejs-soft:format
^- response:rpc:jstd
=; dere
=+ res=((ar dere) jon)
?~ res (need (dere jon))
[%batch u.res]
|= jon=json
^- (unit response:rpc:jstd)
=/ res=[id=(unit @t) res=(unit json) err=(unit json)]
%. jon
=, dejs:format
=- (ou -)
:~ ['id' (uf ~ (mu so))]
['result' (uf ~ (mu same))]
['error' (uf ~ (mu same))]
==
?: ?=([^ * ~] res)
`[%result [u.id.res ?~(res.res ~ u.res.res)]]
~| jon
`(parse-error jon)
::
++ parse-error
|= =json
^- response:rpc:jstd
:- %error
?~ json ['' '' '']
%. json
=, dejs:format
=- (ou -)
:~ =- ['id' (uf '' (cu - (mu so)))]
|*(a=(unit) ?~(a '' u.a))
:- 'error'
=- (uf ['' ''] -)
=- (cu |*(a=(unit) ?~(a ['' ''] u.a)) (mu (ou -)))
:~ ['code' (uf '' no)]
['message' (uf '' so)]
== ==
::
2020-10-13 15:31:15 +03:00
++ btc-http-response
2020-10-09 15:34:36 +03:00
|= [=wire response=client-response:iris]
^- (quip card _state)
?. ?=(%finished -.response)
[~ state]
=* status status-code.response-header.response
=/ rpc-resp=response:rpc:jstd
%- httr-to-rpc-response
%+ to-httr:iris
response-header.response
full-file.response
?. ?=([%result *] rpc-resp)
~& [%error +.rpc-resp]
[~ state]
2020-10-13 12:25:37 +03:00
~& > (parse-response:btc-rpc:blib rpc-resp)
2020-10-09 15:34:36 +03:00
[~ state]
::
2020-10-05 15:21:23 +03:00
--