bitcoin: split into seperate desk

This commit is contained in:
Liam Fitzgerald 2021-08-26 13:00:58 +10:00
parent b60aada75e
commit 76cc80af6c
42 changed files with 967 additions and 17 deletions

View File

@ -3,7 +3,7 @@
:: Scrys
:: x/scanned: (list xpub) of all scanned wallets
:: x/balance/xpub: balance (in sats) of wallet
/- *btc-wallet, bp=btc-provider, file-server, launch-store, settings
/- *btc-wallet, bp=btc-provider, settings
/+ dbug, default-agent, bl=btc, bc=bitcoin, bcu=bitcoin-utils, bip32
~% %btc-wallet-top ..part ~
|%
@ -80,19 +80,6 @@
(poke-our:hc %settings-store %settings-event !>(currency))
==
::
=/ has-file=? (gall-scry:hc ? %file-server /url/'~btc'/noun)
=/ has-tile=?
(~(has in (gall-scry:hc (set @tas) %launch /keys/noun)) %btc-wallet)
=? cards !has-file
=/ file=action:file-server [%serve-dir /'~btc' /app/btc-wallet %.n %.y]
:_ cards
(poke-our:hc %file-server %file-server-action !>(file))
=? cards !has-tile
=/ tile=action:launch-store
[%add %btc-wallet [%custom `'/~btc' `'/~btc/img/tile.svg'] %.y]
:_ cards
(poke-our:hc %launch %launch-action !>(tile))
::
:- cards
%_ this
state

6
pkg/bitcoin/desk.bill Normal file
View File

@ -0,0 +1,6 @@
:~ :- %apes
:~ %btc-provider
%btc-wallet
==
:- %fish ~
==

11
pkg/bitcoin/desk.docket Normal file
View File

@ -0,0 +1,11 @@
:~
title+'Bitcoin'
info+'BTC wallet for Urbit. Testing'
color+0xf9.8e40
glob+'https://bootstrap.urbit.org/glob-0v7.m1i81.cgaef.qd9h7.l05kj.5gq6n.glob'
image+'https://urbit.ewr1.vultrobjects.com/hastuc-dibtux/2021.8.24..02.57.38-bitcoin.svg'
base+'bitcoin'
version+[0 0 1]
license+'MIT'
website+'https://tlon.io'
==

View File

@ -0,0 +1,451 @@
/- *group, sur=group-store
/+ resource
^?
=< [. sur]
=, sur
|%
::
++ dekebab
|= str=cord
^- cord
=- (fall - str)
%+ rush str
=/ name
%+ cook
|= part=tape
^- tape
?~ part part
:- (sub i.part 32)
t.part
(star low)
%+ cook
(cork (bake zing (list tape)) crip)
;~(plug (star low) (more hep name))
::
++ enkebab
|= str=cord
^- cord
~| str
=- (fall - str)
%+ rush str
=/ name
%+ cook
|= part=tape
^- tape
?~ part part
:- (add i.part 32)
t.part
;~(plug hig (star low))
%+ cook
|=(a=(list tape) (crip (zing (join "-" a))))
;~(plug (star low) (star name))
++ migrate-path-map
|* map=(map path *)
=/ keys=(list path)
(skim ~(tap in ~(key by map)) |=(=path =('~' (snag 0 path))))
|-
?~ keys
map
=* key i.keys
?> ?=(^ key)
=/ value
(~(got by map) key)
=. map
(~(put by map) t.key value)
=. map
(~(del by map) key)
$(keys t.keys, map (~(put by map) t.key value))
::
++ enjs
=, enjs:format
|%
++ frond
|= [p=@t q=json]
^- json
(frond:enjs:format (dekebab p) q)
++ pairs
|= a=(list [p=@t q=json])
^- json
%- pairs:enjs:format
%+ turn a
|= [p=@t q=json]
^- [@t json]
[(dekebab p) q]
::
++ update
|= =^update
^- json
%+ frond -.update
?- -.update
%add-group (add-group update)
%add-members (add-members update)
%add-tag (add-tag update)
%remove-members (remove-members update)
%remove-tag (remove-tag update)
%initial (initial update)
%initial-group (initial-group update)
%remove-group (remove-group update)
%change-policy (change-policy update)
%expose (expose update)
==
::
++ initial-group
|= =^update
?> ?=(%initial-group -.update)
%- pairs
:~ resource+(enjs:resource resource.update)
group+(group group.update)
==
::
++ initial
|= =^initial
?> ?=(%initial -.initial)
%- pairs
^- (list [@t json])
%+ turn
~(tap by groups.initial)
|= [rid=resource grp=^group]
^- [@t json]
:_ (group grp)
(enjs-path:resource rid)
::
++ group
|= =^group
^- json
%- pairs
:~ members+(set ship members.group)
policy+(policy policy.group)
tags+(tags tags.group)
hidden+b+hidden.group
==
::
++ rank
|= =rank:title
^- json
[%s rank]
++ tags
|= =^tags
^- json
%- pairs
%+ turn ~(tap by tags)
|= [=^tag ships=(^set ^ship)]
^- [@t json]
:_ (set ship ships)
?@ tag tag
;: (cury cat 3)
app.tag '\\'
tag.tag '\\'
(enjs-path:resource resource.tag)
==
::
++ set
|* [item=$-(* json) sit=(^set)]
^- json
:- %a
%+ turn
~(tap in sit)
item
::
++ tag
|= =^tag
^- json
?@ tag
(frond %tag s+tag)
%- pairs
:~ app+s+app.tag
tag+s+tag.tag
resource+s+(enjs-path:resource resource.tag)
==
::
++ policy
|= =^policy
%+ frond -.policy
%- pairs
?- -.policy
%invite
:~ pending+(set ship pending.policy)
==
%open
:~ banned+(set ship banned.policy)
ban-ranks+(set rank ban-ranks.policy)
==
==
++ policy-diff
|= =diff:^policy
%+ frond -.diff
|^
?- -.diff
%invite (invite +.diff)
%open (open +.diff)
%replace (policy +.diff)
==
++ open
|= =diff:open:^policy
%+ frond -.diff
?- -.diff
%allow-ranks (set rank ranks.diff)
%ban-ranks (set rank ranks.diff)
%allow-ships (set ship ships.diff)
%ban-ships (set ship ships.diff)
==
++ invite
|= =diff:invite:^policy
%+ frond -.diff
?- -.diff
%add-invites (set ship invitees.diff)
%remove-invites (set ship invitees.diff)
==
--
::
++ expose
|= =^update
^- json
?> ?=(%expose -.update)
(frond %resource (enjs:resource resource.update))
::
++ remove-group
|= =^update
^- json
?> ?=(%remove-group -.update)
(frond %resource (enjs:resource resource.update))
::
++ add-group
|= =action
^- json
?> ?=(%add-group -.action)
%- pairs
:~ resource+(enjs:resource resource.action)
policy+(policy policy.action)
hidden+b+hidden.action
==
::
++ add-members
|= =action
^- json
?> ?=(%add-members -.action)
%- pairs
:~ resource+(enjs:resource resource.action)
ships+(set ship ships.action)
==
::
++ remove-members
|= =action
^- json
?> ?=(%remove-members -.action)
%- pairs
:~ resource+(enjs:resource resource.action)
ships+(set ship ships.action)
==
::
++ add-tag
|= =action
^- json
?> ?=(%add-tag -.action)
%- pairs
^- (list [p=@t q=json])
:~ resource+(enjs:resource resource.action)
tag+(tag tag.action)
ships+(set ship ships.action)
==
::
++ remove-tag
|= =action
^- json
?> ?=(%remove-tag -.action)
%- pairs
:~ resource+(enjs:resource resource.action)
tag+(tag tag.action)
ships+(set ship ships.action)
==
::
++ change-policy
|= =action
^- json
?> ?=(%change-policy -.action)
%- pairs
:~ resource+(enjs:resource resource.action)
diff+(policy-diff diff.action)
==
--
++ dejs
=, dejs:format
|%
::
++ ruk-jon
|= [a=(map @t json) b=$-(@t @t)]
^+ a
=- (malt -)
|-
^- (list [@t json])
?~ a ~
:- [(b p.n.a) q.n.a]
%+ weld
$(a l.a)
$(a r.a)
::
++ of
|* wer=(pole [cord fist])
|= jon=json
?> ?=([%o [@ *] ~ ~] jon)
|-
?- wer
:: [[key=@t wit=*] t=*]
[[key=@t *] t=*]
=> .(wer [[* wit] *]=wer)
?: =(key.wer (enkebab p.n.p.jon))
[key.wer ~|(val+q.n.p.jon (wit.wer q.n.p.jon))]
?~ t.wer ~|(bad-key+p.n.p.jon !!)
((of t.wer) jon)
==
++ ot
|* wer=(pole [cord fist])
|= jon=json
~| jon
%- (ot-raw:dejs:format wer)
?> ?=(%o -.jon)
(ruk-jon p.jon enkebab)
::
++ update
^- $-(json ^update)
|= jon=json
^- ^update
%. jon
%- of
:~
add-group+add-group
add-members+add-members
remove-members+remove-members
add-tag+add-tag
remove-tag+remove-tag
change-policy+change-policy
remove-group+remove-group
expose+expose
==
++ rank
|= =json
^- rank:title
?> ?=(%s -.json)
?: =('czar' p.json) %czar
?: =('king' p.json) %king
?: =('duke' p.json) %duke
?: =('earl' p.json) %earl
?: =('pawn' p.json) %pawn
!!
++ tag
|= =json
^- ^tag
?> ?=(%o -.json)
?. (~(has by p.json) 'app')
=/ tag-json
(~(got by p.json) 'tag')
?> ?=(%s -.tag-json)
?: =('admin' p.tag-json) %admin
?: =('moderator' p.tag-json) %moderator
?: =('janitor' p.tag-json) %janitor
!!
%. json
%- ot
:~ app+so
resource+dejs-path:resource
tag+so
==
:: move to zuse also
++ oj
|* =fist
^- $-(json (jug cord _(fist *json)))
(om (as fist))
++ tags
^- $-(json ^tags)
*$-(json ^tags)
:: TODO: move to zuse
++ ship
(su ;~(pfix sig fed:ag))
++ policy
^- $-(json ^policy)
%- of
:~ invite+invite-policy
open+open-policy
==
++ invite-policy
%- ot
:~ pending+(as ship)
==
++ open-policy
%- ot
:~ ban-ranks+(as rank)
banned+(as ship)
==
++ open-policy-diff
%- of
:~ allow-ranks+(as rank)
allow-ships+(as ship)
ban-ranks+(as rank)
ban-ships+(as ship)
==
++ invite-policy-diff
%- of
:~ add-invites+(as ship)
remove-invites+(as ship)
==
++ policy-diff
^- $-(json diff:^policy)
%- of
:~ invite+invite-policy-diff
open+open-policy-diff
replace+policy
==
::
++ remove-group
|= =json
^- [resource ~]
?> ?=(%o -.json)
=/ rid=resource
(dejs:resource (~(got by p.json) 'resource'))
[rid ~]
::
++ expose
|= =json
^- [resource ~]
?> ?=(%o -.json)
=/ rid=resource
(dejs:resource (~(got by p.json) 'resource'))
[rid ~]
::
++ add-group
%- ot
:~ resource+dejs:resource
policy+policy
hidden+bo
==
++ add-members
%- ot
:~ resource+dejs:resource
ships+(as ship)
==
++ remove-members
^- $-(json [resource (set ^ship)])
%- ot
:~ resource+dejs:resource
ships+(as ship)
==
++ add-tag
%- ot
:~ resource+dejs:resource
tag+tag
ships+(as ship)
==
++ remove-tag
%- ot
:~ resource+dejs:resource
tag+tag
ships+(as ship)
==
++ change-policy
%- ot
:~ resource+dejs:resource
diff+policy-diff
==
--
--

134
pkg/bitcoin/lib/group.hoon Normal file
View File

@ -0,0 +1,134 @@
/- *group
/+ store=group-store, resource
::
|_ =bowl:gall
+$ card card:agent:gall
::
++ resource-for-update
|= =vase
^- (list resource)
=/ =update:store !<(update:store vase)
?: ?=(%initial -.update)
~
~[resource.update]
::
++ scry-for
|* [=mold =path]
=. path
(snoc path %noun)
.^ mold
%gx
(scot %p our.bowl)
%group-store
(scot %da now.bowl)
path
==
++ scry-tag
|= [rid=resource =tag]
^- (unit (set ship))
=/ group
(scry-group rid)
?~ group
~
`(~(gut by tags.u.group) tag ~)
::
++ scry-group
|= rid=resource
^- (unit group)
%+ scry-for ,(unit group)
`path`groups+(en-path:resource rid)
::
++ scry-groups
^- (set resource)
.^ ,(set resource)
%gy
(scot %p our.bowl)
%group-store
(scot %da now.bowl)
/groups
==
::
++ members
|= rid=resource
^- (set ship)
=; =group
members.group
(fall (scry-group rid) *group)
::
++ is-member
|= [=ship group=resource]
^- ?
=- (~(has in -) ship)
(members group)
::
++ is-admin
|= [=ship group=resource]
^- ?
=/ tags tags:(fall (scry-group group) *^group)
=/ admins=(set ^ship) (~(gut by tags) %admin ~)
(~(has in admins) ship)
:: +role-for-ship: get role for user
::
:: Returns ~ if no such group exists or user is not
:: a member of the group. Returns [~ ~] if the user
:: is a member with no additional role.
++ role-for-ship
|= [rid=resource =ship]
^- (unit (unit role-tag))
=/ grp=(unit group)
(scry-group rid)
?~ grp ~
(role-for-ship-with-group u.grp rid ship)
::
++ role-for-ship-with-group
|= [grp=group rid=resource =ship]
^- (unit (unit role-tag))
=* group grp
=* policy policy.group
=* tags tags.group
=/ admins=(set ^ship)
(~(gut by tags) %admin ~)
?: (~(has in admins) ship)
``%admin
=/ mods
(~(gut by tags) %moderator ~)
?: (~(has in mods) ship)
``%moderator
=/ janitors
(~(gut by tags) %janitor ~)
?: (~(has in janitors) ship)
``%janitor
?: (~(has in members.group) ship)
[~ ~]
~
::
++ can-join
|= [rid=resource =ship]
^- ?
%+ scry-for ,?
^- path
:- %groups
(weld (en-path:resource rid) /join/(scot %p ship))
::
++ get-tagged-ships
|= [rid=resource =tag]
^- (set ship)
=/ grp=(unit group)
(scry-group rid)
?~ grp ~
(get-tagged-ships-with-group u.grp rid tag)
::
++ get-tagged-ships-with-group
|= [grp=group rid=resource =tag]
^- (set ship)
(~(get ju tags.grp) tag)
::
++ is-managed
|= rid=resource
^- ?
=/ group=(unit group)
(scry-group rid)
?~ group %.n
!hidden.u.group
::
--

View File

@ -0,0 +1,57 @@
/- sur=resource
=< resource
|%
+$ resource resource:sur
++ en-path
|= =resource
^- path
~[%ship (scot %p entity.resource) name.resource]
::
++ de-path
|= =path
^- resource
(need (de-path-soft path))
::
++ de-path-soft
|= =path
^- (unit resource)
?. ?=([%ship @ @ *] path)
~
=/ ship
(slaw %p i.t.path)
?~ ship
~
`[u.ship i.t.t.path]
::
++ enjs
|= =resource
^- json
=, enjs:format
%- pairs
:~ ship+(ship entity.resource)
name+s+name.resource
==
::
++ enjs-path
|= =resource
%- spat
(en-path resource)
::
++ dejs-path
%- su:dejs:format
;~ pfix
(jest '/ship/')
;~((glue fas) ;~(pfix sig fed:ag) urs:ab)
==
::
++ dejs
=, dejs:format
^- $-(json resource)
|= jon=json
~| dejs+%resource
%. jon
%- ot
:~ ship+(su ;~(pfix sig fed:ag))
name+so
==
--

View File

@ -0,0 +1,39 @@
/- *group, *resource
^?
|%
::
:: $action: request to change group-store state
::
:: %add-group: add a group
:: %add-members: add members to a group
:: %remove-members: remove members from a group
:: %add-tag: add a tag to a set of ships
:: %remove-tag: remove a tag from a set of ships
:: %change-policy: change a group's policy
:: %remove-group: remove a group from the store
:: %expose: unset .hidden flag
::
+$ action
$% [%add-group =resource =policy hidden=?]
[%add-members =resource ships=(set ship)]
[%remove-members =resource ships=(set ship)]
[%add-tag =resource =tag ships=(set ship)]
[%remove-tag =resource =tag ships=(set ship)]
[%change-policy =resource =diff:policy]
[%remove-group =resource ~]
[%expose =resource ~]
==
:: $update: a description of a processed state change
::
:: %initial: describe groups upon new subscription
::
+$ update
$% initial
action
==
+$ initial
$% [%initial-group =resource =group]
[%initial =groups]
==
--

109
pkg/bitcoin/sur/group.hoon Normal file
View File

@ -0,0 +1,109 @@
/- *resource
::
^?
|%
::
++ groups-state-one
|%
+$ groups (map resource group)
::
+$ tag $@(group-tag [app=term tag=term])
::
+$ tags (jug tag ship)
::
+$ group
$: members=(set ship)
=tags
=policy
hidden=?
==
--
:: $groups: a mapping from group-ids to groups
::
+$ groups (map resource group)
:: $group-tag: an identifier used by groups
::
:: These tags should have precise semantics, as they are shared across all
:: apps.
::
+$ group-tag ?(role-tag)
:: $tag: an identifier used to identify a subset of members
::
:: Tags may be used and recognised differently across apps.
:: for example, you could use tags like `%author`, `%bot`, `%flagged`...
::
+$ tag $@(group-tag [app=term =resource tag=term])
:: $role-tag: a kind of $group-tag that identifies a privileged user
::
:: These roles are
:: %admin: Administrator, can do everything except delete the group
:: %moderator: Moderator, can add/remove/ban users
:: %janitor: Has no special meaning inside group-store,
:: but may be given additional privileges in other apps.
::
+$ role-tag
?(%admin %moderator %janitor)
:: $tags: a mapping from a $tag to the members it identifies
::
+$ tags (jug tag ship)
:: $group: description of a group of users
::
:: .members: members of the group
:: .tag-queries: a map of tags to subsets of members
:: .policy: permissions for the group
:: .hidden: is group unmanaged
+$ group
$: members=(set ship)
=tags
=policy
hidden=?
==
:: $policy: access control for a group
::
++ policy
=< policy
|%
::
+$ policy
$% invite
open
==
:: $diff: change group policy
+$ diff
$% [%invite diff:invite]
[%open diff:open]
[%replace =policy]
==
:: $invite: allow only invited ships
++ invite
=< invite-policy
|%
::
+$ invite-policy
[%invite pending=(set ship)]
:: $diff: add or remove invites
::
+$ diff
$% [%add-invites invitees=(set ship)]
[%remove-invites invitees=(set ship)]
==
--
:: $open: allow all unbanned ships of approriate rank
::
++ open
=< open-policy
|%
::
+$ open-policy
[%open ban-ranks=(set rank:title) banned=(set ship)]
:: $diff: ban or allow ranks and ships
::
+$ diff
$% [%allow-ranks ranks=(set rank:title)]
[%ban-ranks ranks=(set rank:title)]
[%ban-ships ships=(set ship)]
[%allow-ships ships=(set ship)]
==
--
--
--

View File

@ -0,0 +1,21 @@
:: json-rpc: protocol types
::
|%
+$ request
$: id=@t
method=@t
params=request-params
==
::
+$ request-params
$% [%list (list json)]
[%object (list (pair @t json))]
==
+$ response
$~ [%fail *httr:eyre]
$% [%result id=@t res=json]
[%error id=@t code=@t message=@t] ::TODO data?
[%fail hit=httr:eyre]
[%batch bas=(list response)]
==
--

View File

@ -0,0 +1,10 @@
^?
|%
+$ resource [=entity name=term]
+$ resources (set resource)
::
+$ entity
$@ ship
$% !!
==
--

View File

@ -0,0 +1,31 @@
|%
+$ settings-0 (map key bucket-0)
+$ bucket-0 (map key val-0)
+$ val-0
$% [%s p=@t]
[%b p=?]
[%n p=@]
==
::
+$ settings (map key bucket)
+$ bucket (map key val)
+$ key term
+$ val
$~ [%n 0]
$% [%s p=@t]
[%b p=?]
[%n p=@]
[%a p=(list val)]
==
+$ event
$% [%put-bucket =key =bucket]
[%del-bucket =key]
[%put-entry buc=key =key =val]
[%del-entry buc=key =key]
==
+$ data
$% [%all =settings]
[%bucket =bucket]
[%entry =val]
==
--

1
pkg/bitcoin/sys.kelvin Normal file
View File

@ -0,0 +1 @@
[%zuse 420]

View File

@ -0,0 +1,95 @@
:: Note: these are for BTC testnet
::
/- spider, rpc=json-rpc
/+ strandio, bc=bitcoin, bcu=bitcoin-utils
=, strand=strand:spider
=>
|%
++ url1 "http://localhost:50002"
++ addr ^-(address:bc [%bech32 'bc1q39wus23jwe7m2j7xmrfr2svhrtejmsn262x3j2'])
++ btc-req
^- request:http
=, enjs:format
:* method=%'POST'
url=`@ta`(crip (weld url1 "/btc-rpc"))
header-list=['Content-Type'^'application/json' ~]
^= body
%- some
%- as-octt:mimes:html
%- en-json:html
%- pairs
:~ jsonrpc+s+'2.0'
id+s+'block-info'
method+s+'getblockchaininfo'
==
==
++ electrs-req
^- request:http
=, enjs:format
:* method=%'POST'
url=`@ta`(crip (weld url1 "/electrs-rpc"))
header-list=['Content-Type'^'application/json' ~]
^= body
%- some
%- as-octt:mimes:html
%- en-json:html
%- pairs
:~ jsonrpc+s+'2.0'
id+s+'list-unspent'
method+s+'blockchain.scripthash.listunspent'
params+a+~[[%s '34aae877286aa09828803af27ce2315e72c4888efdf74d7d067c975b7c558789']]
==
==
::
:: convert address to Electrs ScriptHash that it uses to index
:: big-endian sha256 of the output script
::
++ electrs-script-hash
|= a=address:bc
^- hexb:bc
%- flip:byt:bcu
%- sha256:bcu
(to-script-pubkey:adr:bc a)
::
++ parse-json-rpc
|= =json
^- (unit response:rpc)
=/ res=(unit [@t ^json])
%. json
=, dejs-soft:format
(ot id+so result+some ~)
?^ res `[%result u.res]
~| parse-one-response=json
:+ ~ %error %- need
%. json
=, dejs-soft:format
(ot id+so error+(ot code+no message+so ~) ~)
::
++ parse-response
|= =client-response:iris
=/ m (strand:strandio ,(unit response:rpc))
^- form:m
?> ?=(%finished -.client-response)
?~ full-file.client-response
(pure:m ~)
=/ body=@t q.data.u.full-file.client-response
=/ jon=(unit json) (de-json:html body)
?~ jon (pure:m ~)
(pure:m (parse-json-rpc u.jon))
::
++ attempt-request
|= =request:http
=/ m (strand:strandio ,~)
^- form:m
(send-request:strandio request)
--
^- thread:spider
|= arg=vase
:: =+ !<([~ a=@ud] arg)
=/ m (strand ,vase)
^- form:m
;< ~ bind:m (attempt-request electrs-req)
;< rep=client-response:iris bind:m
take-client-response:strandio
;< rpc-resp=(unit response:rpc) bind:m (parse-response rep)
(pure:m !>(rpc-resp))

View File

@ -1,7 +1,5 @@
:~ :- %apes
:~ %btc-provider
%btc-wallet
%chat-cli
:~ %chat-cli
%chat-hook
%chat-store
%chat-view