Merge branch 'next/vere' into jo/secp-c3

This commit is contained in:
Jōshin 2022-02-02 17:57:51 -06:00
commit 8d3f19aba9
No known key found for this signature in database
GPG Key ID: A8BE5A9A521639D0
178 changed files with 87562 additions and 76765 deletions

6
.gitattributes vendored
View File

@ -8,4 +8,8 @@ pkg/arvo/tmp/landscape.jam filter=lfs diff=lfs merge=lfs -text
pkg/arvo/tmp/base.jam filter=lfs diff=lfs merge=lfs -text
pkg/arvo/tmp/bitcoin.jam filter=lfs diff=lfs merge=lfs -text
pkg/arvo/tmp/webterm.jam filter=lfs diff=lfs merge=lfs -text
*.hoon text eol=lf
*.kelvin text eol=lf
*.bill text eol=lf
*.docket-0 text eol=lf
*.ship text eol=lf

View File

@ -9,8 +9,12 @@ interface, see its [contribution guidelines][interface].
For information on Arvo's maintainers, see [pkg/arvo][main].
For more extensive information on Urbit development, such as how to set up an
environment and how to submit a grant, see the [developer documentation][dev].
[start]: https://urbit.org/using/install
[interface]: /pkg/interface/CONTRIBUTING.md
[dev]: https://urbit.org/docs/development
## Fake ships
@ -55,8 +59,9 @@ urbit -F zod -B "bin/solid.pill" -A "pkg/arvo"
The canonical source tree is the `master` branch of
[https://github.com/urbit/urbit][repo]. You should typically branch off of
`master` when commencing new work; similarly, when we pull in your
contribution, we'll do so by merging it to `master`.
`master` when commencing new work. Most pull requests should be merging into
one of the `next/*` branches, depending on what part of the system the pull
request is targeting.
Since we use GitHub, we request you contribute via a GitHub pull request. Tag
the [maintainer][main] for the component. If you have a question for the
@ -294,5 +299,5 @@ Questions or other communications about contributing to Urbit can go to
[repo]: https://github.com/urbit/urbit
[reba]: https://git-rebase.io/
[issu]: https://github.com/urbit/urbit/issues
[hoon]: https://urbit.org/docs/learn/hoon/style/
[main]: https://github.com/urbit/urbit/tree/master/pkg/arvo#maintainers
[hoon]: https://urbit.org/docs/hoon/reference/style
[main]: https://github.com/urbit/urbit/tree/master/pkg/arvo#maintainers

View File

@ -29,7 +29,7 @@ released.
### Release branches
Release branches are code that is ready to release. All release branch names
should start with `release/`.
should start with `next/`.
All code must be reviewed before being pushed to a release branch. Thus,
feature branches should be PR'd against a release branch, not master.
@ -41,57 +41,55 @@ be released together -- unless one of the underlying commits is separately put
on a release branch.
Here's a worked example. The rule is to make however many branches are useful,
and no more. This example is not prescriptive, the developers making the
and no more. This example is not prescriptive; the developers making the
changes may add, remove, or rename branches in this flow at will.
Suppose you (plural, the dev community at large) complete some work in a
userspace app, and you put it in `release/next-userspace`. Separately, you make
a small JS change. If you PR it to `release/next-userspace`, then it will only
be released at the same time as the app changes. Maybe this is fine, or maybe
you want this change to go out quickly, and the change in
`release/next-userspace` is relatively risky, so you don't want to push it out
on Friday afternoon. In this case, put the change in another release branch,
say `release/next-js`. Now either can be released independently.
userspace app, and you put it in `next/landscape`. Separately, you make a small
JS change. If you PR it to `next/landscape`, then it will only be released at
the same time as the app changes. Maybe this is fine, or maybe you want this
change to go out quickly, and the change in `next/landscape` is relatively
risky, so you don't want to push it out on Friday afternoon. In this case, put
the change in another release branch, say `next/js`. Now either can be released
independently.
Suppose you do further work that you want to PR to `release/next-userspace`, but
it depends on your fixes in `release/next-js`. Simply merge `release/next-js`
into either your feature branch or `release/next-userspace` and PR your finished
work to `release/next-userspace`. Now there is a one-way coupling:
`release/next-userspace` contains `release/next-js`, so releasing it will
implicitly release `release/next-js`. However, you can still release
`release/next-js` independently.
Suppose you do further work that you want to PR to `next/landscape`, but it
depends on your fixes in `next/js`. Simply merge `next/js` into either your
feature branch or `next/landscape` and PR your finished work to
`next/landscape`. Now there is a one-way coupling: `next/landscape` contains
`next/js`, so releasing it will implicitly release `next/js`. However, you can
still release `next/js` independently.
This scheme extends to other branches, like `release/next-kernel` or
`release/os1.1` or `release/ford-fusion`. Some branches may be long-lived and
represent simply the "next" release of something, while others will have a
definite lifetime that corresponds to development of a particular feature or
numbered release.
This scheme extends to other branches, like `next/base` or `next/os1.1` or
`next/ford-fusion`. Some branches may be long-lived and represent simply the
"next" release of something, while others will have a definite lifetime that
corresponds to development of a particular feature or numbered release.
Since they are "done", release branches should be considered "public", in the
sense that others may depend on them at will. Thus, never rebase a release
branch.
When cutting a new release, you can filter branches with `git branch --list
'release/*'` or by typing "release/" in the branch filter on Github. This will
give you the list of branches which have passed review and may be merged to
master and released. When choosing which branches to release, make sure you
understand the risks of releasing them immediately. If merging these produces
nontrivial conflicts, consider asking the developers on those branches to merge
between themselves. In many cases a developer can do this directly, but if it's
'next/*'` or by typing "next/" in the branch filter on Github. This will give
you the list of branches which have passed review and may be merged to master
and released. When choosing which branches to release, make sure you understand
the risks of releasing them immediately. If merging these produces nontrivial
conflicts, consider asking the developers on those branches to merge between
themselves. In many cases a developer can do this directly, but if it's
sufficiently nontrivial, this may be a reviewed PR of one release branch into
another.
### Non-OTAable release branches
#### Standard release branches
In some cases, work is completed which cannot be OTA'd as written. For example,
the code may lack state adapters, or it may not properly handle outstanding
subscriptions. It could also be code which is planned to be released only upon
a breach (network-wide or rolling).
While you can always create non-standard release branches to stage for a
particular release, most changes should go through the following:
In this case, the code may be PR'd to a `na-release/` branch. All rules are the
same as for release branches, except that the code does not need to apply
cleanly to an existing ship. If you later write state adapter or otherwise make
it OTAable, then you may PR it to a release branch.
- next/base -- changes to the %base desk in pkg/arvo
- next/garden -- changes to the %garden desk
- next/landscape -- changes to the %landscape desk
- next/bitcoin -- changes to the %bitcoin desk
- next/webterm -- changes to the %webterm desk
- next/vere -- changes to the runtime
### Other cases
@ -163,9 +161,10 @@ If you're making a Vere release, just play it safe and update all the pills.
For an Urbit OS release, after all the merge commits, make a release with the
commit message "release: urbit-os-v1.0.xx". This commit should have up-to-date
artifacts from pkg/interface and a new solid pill. If neither the pill nor the
JS need to be updated (e.g if the pill was already updated in the previous merge
commit), consider making the release commit with --allow-empty.
artifacts from pkg/interface and a new version number in the desk.docket-0 of
any desk which changed. If neither the pill nor the JS need to be updated (e.g
if the pill was already updated in the previous merge commit), consider making
the release commit with --allow-empty.
If anything in `pkg/interface` has changed, ensure it has been built and
deployed properly. You'll want to do this before making a pill, since you want
@ -191,21 +190,23 @@ What you should do here depends on the type of release being made.
First, for Urbit OS releases:
If it's a very trivial hotfix that you know isn't going to break
anything, tag it as `urbit-os-vx.y.z`. Here 'x' refers to the product version
(e.g. OS1, OS2..), 'y' to the continuity era in that version, and 'z' to an
OTA patch counter. So for a hotfix version, you'll just want to increment 'z'.
If it's a very trivial hotfix that you know isn't going to break anything, tag
it as `urbit-os-vx.y`. Here 'x' is the major version and 'y' is an OTA patch
counter. Change `urbit-os` to e.g. `landscape` or another desk if that's what you're
releasing. If you're releasing changes to more than one desk, add a separate
tag for each desk (but only make one announcment email/post, with all of the
desks listed).
Use an annotated tag, i.e.
```
git tag -a urbit-os-vx.y.z
git tag -a urbit-os-vx.y
```
The tag format should look something like this:
```
urbit-os-vx.y.z
urbit-os-vx.y
This release will be pushed to the network as an over-the-air update.
@ -236,17 +237,17 @@ If the commit descriptions are too poor to easily do this, then again, yell at
your fellow contributors to make them better in the future.
If it's *not* a trivial hotfix, you should probably make any number of release
candidate tags (e.g. `urbit-os-vx.y.z.rc1`, `urbit-os-vx.y.z.rc2`, ..), test
candidate tags (e.g. `urbit-os-vx.y.rc1`, `urbit-os-vx.y.rc2`, ..), test
them, and after you confirm one of them is good, tag the release as
`urbit-os-vx.y.z`.
`urbit-os-vx.y`.
For Vere releases:
Tag the release as `urbit-vx.y.z`. The tag format should look something like
Tag the release as `urbit-vx.y`. The tag format should look something like
this:
```
urbit-vx.y.z
urbit-vx.y
Note that this Vere release will by default boot fresh ships using an Urbit OS
va.b.c pill.
@ -254,10 +255,10 @@ va.b.c pill.
Release binaries:
(linux64)
https://bootstrap.urbit.org/urbit-vx.y.z-linux64.tgz
https://bootstrap.urbit.org/urbit-vx.y-linux64.tgz
(macOS)
https://bootstrap.urbit.org/urbit-vx.y.z-darwin.tgz
https://bootstrap.urbit.org/urbit-vx.y-darwin.tgz
Release notes:
@ -295,10 +296,10 @@ and stars to the rest of the network.
For consistency, I create a release tarball and then rsync the files in.
```
$ wget https://github.com/urbit/urbit/archive/urbit-os-vx.y.z.tar.gz
$ tar xzf urbit-os-vx.y.z.tar.gz
$ wget https://github.com/urbit/urbit/archive/urbit-os-vx.y.tar.gz
$ tar xzf urbit-os-vx.y.tar.gz
$ herb zod -p hood -d "+hood/mount /=home="
$ rsync -zr --delete urbit-urbit-os-vx.y.z/pkg/arvo/ zod/home
$ rsync -zr --delete urbit-urbit-os-vx.y/pkg/arvo/ zod/home
$ herb zod -p hood -d "+hood/commit %home"
$ herb zod -p hood -d "+hood/merge %kids our %home"
```
@ -306,16 +307,11 @@ $ herb zod -p hood -d "+hood/merge %kids our %home"
For Vere updates, this means simply shutting down each desired ship, installing
the new binary, and restarting the pier with it.
#### Continuous deployment
A subset of release branches are deployed continuously to the network. Thus far
this only includes `release/next-userspace`, which deploys livenet-compatible
changes to select QA ships. Any push to master will automatically
merge master into `release/next-userspace` to keep the streams at parity.
### Announce the update
Post an announcement to urbit-dev. The tag annotation, basically, is fine here
-- I usually add the %base hash (for Urbit OS releases) and the release binary
-- I usually add the %cz hash (for Urbit OS releases) and the release binary
URLs (for Vere releases). Check the urbit-dev archives for examples of these
announcements.
Post the same announcement to the group feed of Urbit Community.

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6f48518fe49584a6532a20018f4ac4eae3817b25d85d60536a99643eb5d65b2b
size 22872573
oid sha256:e660fba934c5b80eeda64037a1f28c71eff4b2ea0bd28809b91432ca3d5ef08a
size 23052691

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c29577dc949ac0689ba3c97ad13b812ea6c3c6cc9d255b770d2da95fd9af84b9
size 23121802
oid sha256:843387cce113f18b403f76b6ba97ddf1746a5436b107d087d1f33b38db6f8c1a
size 26237959

View File

@ -14,6 +14,12 @@ let
version = builtins.readFile "${src}/version";
# See https://github.com/urbit/urbit/issues/5561
oFlags =
if stdenv.hostPlatform.system == "aarch64-darwin"
then (if enableDebug then [ "-O0" "-g" ] else [ "-O3" ])
else [ (if enableDebug then "-O0" else "-O3") "-g" ];
in stdenv.mkDerivation {
inherit src version;
@ -59,8 +65,7 @@ in stdenv.mkDerivation {
then [ "--disable-shared" "--enable-static" ]
else [];
CFLAGS = [ (if enableDebug then "-O0" else "-O3") "-g" ]
++ lib.optionals (!enableDebug) [ "-Werror" ];
CFLAGS = oFlags ++ lib.optionals (!enableDebug) [ "-Werror" ];
MEMORY_DEBUG = enableDebug;
CPU_DEBUG = enableDebug;

View File

@ -54,13 +54,13 @@
?: =(broke-continuity i.topics.event-log)
=/ who=@ (decode-topics t.topics.event-log ~[%uint])
=/ num=@ (decode-results data.event-log ~[%uint])
`[who id %rift num]
`[who id %rift num %.n]
?: =(changed-keys i.topics.event-log)
=/ who=@ (decode-topics t.topics.event-log ~[%uint])
=/ [enc=octs aut=octs sut=@ud rev=@ud]
%+ decode-results data.event-log
~[[%bytes-n 32] [%bytes-n 32] %uint %uint]
`[who id %keys rev sut (pass-from-eth:azimuth enc aut sut)]
`[who id %keys [rev sut (pass-from-eth:azimuth enc aut sut)] %.n]
?: =(lost-sponsor i.topics.event-log)
=/ [who=@ pos=@]
(decode-topics t.topics.event-log ~[%uint %uint])

View File

@ -7,24 +7,21 @@
verb,
dbug
:: Generally don't update the snapshot until we have clay tombstoning.
:: To update, run:
:: =e -build-file %/lib/ethereum/hoon
:: =l .^((list event-log:rpc:e) %gx /=azimuth=/logs/noun)
:: */app/azimuth/logs/eth-logs &eth-logs l
::
/* snap %eth-logs /app/azimuth/logs/eth-logs
/* snap %azimuth-snapshot /app/azimuth/version-0/azimuth-snapshot
:: To update, run from dojo:
:: -azimuth-snap-state %default 'version-0'
::
=/ last-snap :: maybe just use the last one?
%+ roll `(list event-log:rpc:ethereum)`snap ::~
|= [log=event-log:rpc:ethereum last=@ud]
?~ mined.log
last
(max block-number.u.mined.log last)
:: To recreate from a full list of logs (at /app/azimuth/logs/eth-logs):
:: -azimuth-snap-logs %default 'version-0'
::
=/ snap=snap-state snap
=/ last-snap=@ number.id.snap
::
=, jael
|%
+$ app-state
$: %2
$: %5
url=@ta
=net
whos=(set ship)
@ -62,8 +59,14 @@
::
++ on-init
^- (quip card _this)
=/ points=@ud ~(wyt by points.nas.snap)
%- %- slog
[leaf+"ship: loading azimuth snapshot ({<points>} points)"]~
::
=: net.state %default
logs.state snap
nas.state nas.snap
own.state owners.snap
spo.state sponsors.snap
url.state 'http://eth-mainnet.urbit.org:8545'
==
:_ this
@ -89,18 +92,56 @@
?. ?=(%1 -.old-state)
`old-state
%- %- slog :_ ~
leaf+"azimuth: loading snapshot with {<(lent logs.old-state)>} events"
leaf+"ship: loading snapshot with {<(lent logs.old-state)>} events"
=. +.state +.old-state
=^ cards state
(%*(run-logs do nas.state *^state:naive) logs.state)
[(jael-update:do (to-udiffs:do cards)) state]
?> ?=(%2 -.old-state)
[cards-1 this(state old-state)]
=^ cards-2 old-state
?. ?=(%2 -.old-state)
`old-state
~& > '%azimuth: updating to state 3'
=. +.state +.old-state
:: replace naive state and indices with snapshot
::
=: nas.state nas.snap
own.state owners.snap
spo.state sponsors.snap
logs.state ~
:: TODO: shouldn't be needed but have seen eth-watcher
:: threads use a url='' if this is not used
::
url.state 'http://eth-mainnet.urbit.org:8545'
==
=/ points=@ud ~(wyt by points.nas.state)
%- %- slog :_ ~
leaf+"ship: processing azimuth snapshot ({<points>} points)"
=/ snap-cards=udiffs:point (run-state:do id.snap points.nas.state)
:_ [%3 +.state]
%+ weld
(jael-update:do snap-cards)
:: start getting new logs after the last id:block in the snapshot
::
start:do
=^ cards-3 old-state
?. ?=(%3 -.old-state) [cards-2 old-state]
:_ old-state(- %4)
~& > '%azimuth: updating to state 4'
[%pass /resend-pk %arvo %j %resend ~]^cards-2
=^ cards-4 old-state
?. ?=(%4 -.old-state) [cards-3 old-state]
=^ cards this
%- %*(. on-poke +.state.this +.old-state)
[%azimuth-poke !>([%watch [url net]:old-state])]
~& > '%azimuth: updating to state 5'
[cards state.this(- %5)]
?> ?=(%5 -.old-state)
[cards-4 this(state old-state)]
::
++ app-states $%(state-0 state-1 app-state)
++ app-states $%(state-0 state-1-2-3-4 app-state)
::
+$ state-1
$: %1
+$ state-1-2-3-4
$: ?(%1 %2 %3 %4)
url=@ta
=net
whos=(set ship)
@ -126,12 +167,13 @@
^- (quip card _this)
?: =(%noun mark)
?+ q.vase !!
::
%rerun
~& [%rerunning (lent logs.state)]
=. points.nas.state ~
=. own.state ~
=^ * state (run-logs:do logs.state)
`this
=/ points=@ud ~(wyt by points.nas.state)
~& > "rerunning ({<points>} points)"
=/ =udiffs:point
(run-state:do (last-block-id:dice logs.state) points.nas.state)
[(jael-update:do udiffs) this]
::
%resub
:_ this :_ ~
@ -140,13 +182,12 @@
==
::
%resnap
=. logs.state snap
$(mark %noun, vase !>(%rerun))
=: nas.state nas.snap
own.state owners.snap
spo.state sponsors.snap
==
`this
==
?: =(%eth-logs mark)
=+ !<(logs=(list event-log:rpc:ethereum) vase)
=. logs.state logs
$(mark %noun, vase !>(%rerun))
::
?. ?=(%azimuth-poke mark)
(on-poke:def mark vase)
@ -156,15 +197,12 @@
[[%pass /lo %arvo %j %listen (silt whos.poke) source.poke]~ this]
::
%watch
:: TODO: only wipe out state when switching networks?
:: ?: =(net.state net.poke)
:: [~ this]
=: nas.state *^state:naive
=: nas.state ?:(?=(%default net.poke) nas.snap *^state:naive)
own.state ?:(?=(%default net.poke) owners.snap ~)
spo.state ?:(?=(%default net.poke) sponsors.snap ~)
net.state net.poke
url.state url.poke
own.state ~
spo.state ~
logs.state ?:(?=(%default net.poke) snap ~)
logs.state ~
==
[start:do this]
==
@ -188,11 +226,13 @@
:: Slow to recalculate all the diffs, but this is necessary to make
:: sure Jael gets the updates from the snapshot
::
=/ points=@ud ~(wyt by points.nas.state)
%- %- slog :_ ~
leaf+"azimuth: loading snapshot with {<(lent logs.state)>} events"
=^ snap-cards state
(%*(run-logs do nas.state *^state:naive) logs.state)
[(weld (jael-update:do (to-udiffs:do snap-cards)) start:do) this]
:- %leaf
"ship: processing azimuth snapshot ({<points>} points)"
=/ snap-cards=udiffs:point
(%*(run-state do logs.state ~) id.snap points.nas.state)
[(weld (jael-update:do snap-cards) start:do) this]
::
++ on-leave on-leave:def
++ on-peek
@ -237,9 +277,13 @@
%history (welp logs.state loglist.diff)
%logs (welp logs.state loglist.diff)
==
=? nas.state ?=(%history -.diff) *^state:naive
=^ effects state (run-logs:do loglist.diff)
:: doing :azimuth|watch caused a l2-sig-fail when using the eth-log
:: snapshot because we were not updating nas with the saved logs.
::
:: now (L: 189) nas.state is loaded with the contents of the snapshot,
:: if we are on the %default network.
::
=^ effects state (run-logs:do loglist.diff)
:_ this
%+ weld
(event-update:do effects)
@ -287,16 +331,27 @@
^- (list ?(@ux (list @ux)))
~
::
++ data-to-hex
|= data=@t
?~ data *@ux
?: =(data '0x') *@ux
(hex-to-num:ethereum data)
++ run-state
|= [=id:block =points:naive]
::%- road |. :: count memory usage in a separate road
^- =udiffs:point
%- flop
%+ roll (tap:orp:dice points)
|= [[=ship naive-point=point:naive] =udiffs:point]
=, naive-point
=/ =pass
(pass-from-eth:azimuth [32^crypt 32^auth suite]:keys.net)
^- (list [@p udiff:point])
:* [ship id %rift rift.net %.y]
[ship id %keys [life.keys.net suite.keys.net pass] %.y]
[ship id %spon ?:(has.sponsor.net `who.sponsor.net ~)]
udiffs
==
::
++ run-logs
|= [logs=(list event-log:rpc:ethereum)]
^- (quip tagged-diff _state)
=+ net=(get-network net.state)
=+ net=(get-network:dice net.state)
=| effects=(list tagged-diff)
!. :: saves 700MB replaying snapshot
=- =/ res (mule -)
@ -309,11 +364,12 @@
[(flop effects) state]
?~ mined.i.logs
$(logs t.logs)
=/ [raw-effects=effects:naive new-nas=_nas.state]
=+ cache=nas.state
=^ raw-effects nas.state
=/ =^input:naive
:- block-number.u.mined.i.logs
?: =(azimuth.net address.i.logs)
=/ data (data-to-hex data.i.logs)
=/ data (data-to-hex:dice data.i.logs)
=/ =event-log:naive
[address.i.logs data topics.i.logs]
[%log event-log]
@ -321,28 +377,16 @@
[%bat *@]
[%bat u.input.u.mined.i.logs]
(%*(. naive lac |) verifier chain-id.net nas.state input)
:: TODO: move to /lib/dice ?
:: TODO: make index update optional?
::
=/ [new-own=_own.state new-spo=_spo.state]
=< [own spo]
?. =(azimuth.net address.i.logs)
%: apply-effects:dice
chain-id.net
raw-effects
nas.state
own.state
spo.state
==
%: update-indices:dice
raw-effects
nas.state
new-nas
own.state
spo.state
==
=: nas.state new-nas
own.state new-own
spo.state new-spo
=/ =indices [own spo]:state
=. indices
?: =(naive.net address.i.logs)
(tx-effects:dice chain-id.net raw-effects cache indices)
=< indices
(point-effects:dice raw-effects points.cache points.nas.state indices)
=: own.state own.indices
spo.state spo.indices
==
=/ effects-1
=/ =id:block [block-hash block-number]:u.mined.i.logs
@ -358,12 +402,12 @@
^- (unit [=ship =udiff:point])
?. ?=(%point +<.tag) ~
?+ +>+<.tag ~
%rift `[ship.tag id.tag %rift rift.tag]
%rift `[ship.tag id.tag %rift rift.tag %.n]
%sponsor `[ship.tag id.tag %spon sponsor.tag]
%keys
=/ =pass
(pass-from-eth:azimuth 32^crypt.keys.tag 32^auth.keys.tag suite.keys.tag)
`[ship.tag id.tag %keys life.keys.tag suite.keys.tag pass]
`[ship.tag id.tag %keys [life.keys.tag suite.keys.tag pass] %.n]
==
::
++ jael-update
@ -391,26 +435,14 @@
^- card
[%give %fact ~[/event] %naive-diffs !>(+.tag)]
::
++ get-network
|= =net
^- [azimuth=@ux naive=@ux chain-id=@ launch=@]
=< [azimuth naive chain-id launch]
=, azimuth
?- net
%mainnet mainnet-contracts
%ropsten ropsten-contracts
%local local-contracts
%default contracts
==
::
++ start
^- (list card)
=+ net=(get-network net.state)
=+ net=(get-network:dice net.state)
=/ args=vase !>
:+ %watch /[dap.bowl]
^- config:eth-watcher
:* url.state =(%czar (clan:title our.bowl)) refresh ~h30
(max launch.net ?:(=(net.state %default) last-snap 0))
(max launch.net ?:(=(net.state %default) +(last-snap) 0))
~[azimuth.net]
~[naive.net]
(topics whos.state)

Binary file not shown.

Binary file not shown.

View File

@ -200,6 +200,9 @@
=/ contracts (get-contracts network)
?+ -.call ecliptic:contracts
%send-point delegated-sending:contracts
::
?(%approve-batch-transfer %transfer-batch %withdraw)
linear-star-release:contracts
==
::
++ deed
@ -379,7 +382,7 @@
?> =(%king (clan:title s))
(~(put in ss) (^sein:title s))
|-
?~ parents txs
?~ parents !! ::txs
=. txs
%+ do-here ecliptic:mainnet-contracts
(set-spawn-proxy:dat i.parents lockup-contract)
@ -394,15 +397,18 @@
=. txs
%+ do-here ecliptic:mainnet-contracts
(set-transfer-proxy:dat i.what lockup-contract)
=. txs
%+ do-here lockup-contract
(deposit:dat to i.what)
$(what t.what)
==
:: depositing
::
|-
?~ what txs
=. txs
%+ do-here lockup-contract
(deposit:dat to i.what)
:: =. txs
:: %+ do-here lockup-contract
:: (deposit:dat to i.what)
$(what t.what)
++ do-here
|= [contract=address dat=tape]

View File

@ -902,6 +902,9 @@
%dv (dy-sing hand+q.bil %a p.bil (snoc q.bil %hoon))
%ge (dy-run-generator (dy-cage p.p.p.bil) q.p.bil)
%sa
=/ has-mark .?((get-fit:clay he-beak %mar p.bil))
?. has-mark
(he-diff(poy ~) %tan leaf+"dojo: %{(trip p.bil)} missing" ~)
=+ .^(=dais:clay cb+(en-beam he-beak /[p.bil]))
(dy-hand p.bil *vale:dais)
::
@ -910,8 +913,12 @@
=/ has-mark .?((get-fit:clay he-beak %mar p.bil))
?. has-mark :: yolo
(dy-hand p.bil q.cag)
=+ .^(=tube:clay cc+(en-beam he-beak /[p.cag]/[p.bil]))
(dy-hand p.bil (tube q.cag))
=/ res
=+ .^(=tube:clay cc+(en-beam he-beak /[p.cag]/[p.bil]))
(mule |.((tube q.cag)))
?: ?=(%| -.res)
(he-diff(poy ~) %tan leaf+"dojo: %as %{(trip p.bil)} failed" p.res)
(dy-hand p.bil p.res)
::
%do
=/ gat (dy-eval p.bil)

View File

@ -462,9 +462,9 @@
++ release-logs
|= [=path dog=watchdog]
^- (quip card watchdog)
?: (lth number.dog 0) :: TODO: 30!
?: (lth number.dog 30)
`dog
=/ rel-number (sub number.dog 0) :: TODO: 30!
=/ rel-number (sub number.dog 30)
=/ numbers=(list number:block) ~(tap in ~(key by pending-logs.dog))
=. numbers (sort numbers lth)
=^ logs=(list event-log:rpc:ethereum) dog

View File

@ -2,27 +2,28 @@
/+ drum=hood-drum, helm=hood-helm, kiln=hood-kiln
|%
+$ state
$~ [%22 *state:drum *state:helm *state:kiln]
$>(%22 any-state)
$~ [%23 *state:drum *state:helm *state:kiln]
$>(%23 any-state)
::
+$ any-state
$% [ver=?(%1 %2 %3 %4 %5 %6) lac=(map @tas fin-any-state)]
[%7 drum=state-2:drum helm=state:helm kiln=state-0:kiln]
[%8 drum=state-2:drum helm=state:helm kiln=state-0:kiln]
[%9 drum=state-2:drum helm=state:helm kiln=state-0:kiln]
[%10 drum=state-2:drum helm=state:helm kiln=state-0:kiln]
[%11 drum=state-2:drum helm=state:helm kiln=state-0:kiln]
[%12 drum=state-2:drum helm=state:helm kiln=state-0:kiln]
[%13 drum=state-2:drum helm=state:helm kiln=state-1:kiln]
[%14 drum=state-2:drum helm=state:helm kiln=state-1:kiln]
[%15 drum=state-2:drum helm=state:helm kiln=state-2:kiln]
[%16 drum=state-4:drum helm=state:helm kiln=state-3:kiln]
[%17 drum=state-4:drum helm=state:helm kiln=state-4:kiln]
[%18 drum=state-4:drum helm=state:helm kiln=state-5:kiln]
[%19 drum=state-4:drum helm=state:helm kiln=state-6:kiln]
[%20 drum=state-4:drum helm=state:helm kiln=state-7:kiln]
[%21 drum=state-4:drum helm=state:helm kiln=state-8:kiln]
[%22 drum=state-4:drum helm=state:helm kiln=state-9:kiln]
[%7 drum=state-2:drum helm=state-1:helm kiln=state-0:kiln]
[%8 drum=state-2:drum helm=state-1:helm kiln=state-0:kiln]
[%9 drum=state-2:drum helm=state-1:helm kiln=state-0:kiln]
[%10 drum=state-2:drum helm=state-1:helm kiln=state-0:kiln]
[%11 drum=state-2:drum helm=state-1:helm kiln=state-0:kiln]
[%12 drum=state-2:drum helm=state-1:helm kiln=state-0:kiln]
[%13 drum=state-2:drum helm=state-1:helm kiln=state-1:kiln]
[%14 drum=state-2:drum helm=state-1:helm kiln=state-1:kiln]
[%15 drum=state-2:drum helm=state-1:helm kiln=state-2:kiln]
[%16 drum=state-4:drum helm=state-1:helm kiln=state-3:kiln]
[%17 drum=state-4:drum helm=state-1:helm kiln=state-4:kiln]
[%18 drum=state-4:drum helm=state-1:helm kiln=state-5:kiln]
[%19 drum=state-4:drum helm=state-1:helm kiln=state-6:kiln]
[%20 drum=state-4:drum helm=state-1:helm kiln=state-7:kiln]
[%21 drum=state-4:drum helm=state-1:helm kiln=state-8:kiln]
[%22 drum=state-4:drum helm=state-1:helm kiln=state-9:kiln]
[%23 drum=state-4:drum helm=state-2:helm kiln=state-9:kiln]
==
+$ any-state-tuple
$: drum=any-state:drum
@ -48,6 +49,7 @@
++ on-fail on-fail:def
++ on-init
^- step:agent:gall
=^ h helm.state on-init:helm-core
=^ d drum.state on-init:drum-core
=^ k kiln.state on-init:kiln-core
[:(welp d k) this]

View File

@ -151,12 +151,16 @@
?: ?=(l2-tx method)
(process-rpc id +.params method over-quota:scry)
?+ method [~ ~(method error:json-rpc id)]
%cancel-transaction (cancel-tx id +.params)
%when-next-batch `(next-timer id +.params next-batch:scry)
%when-next-slice `(next-timer id +.params next-slice:scry)
%spawns-remaining `(spawns-remaining id +.params unspawned:scry)
%get-remaining-quota `(quota-remaining id +.params ship-quota:scry)
%get-allowance `(ship-allowance id +.params allowance:scry)
%get-point `(get-point id +.params point:scry)
%get-ships `(get-ships id +.params ships:scry)
%cancel-transaction (cancel-tx id +.params)
%get-spawned `(get-spawned id +.params spawned:scry)
%get-unspawned `(get-spawned id +.params unspawned:scry)
%spawns-remaining `(spawns-remaining id +.params unspawned:scry)
%get-sponsored-points `(sponsored-points id +.params sponsored:scry)
%get-owned-points `(get-ships id +.params owned:scry)
%get-transferring-for `(get-ships id +.params transfers:scry)
@ -168,18 +172,13 @@
%get-pending-by-address `(addr:pending id +.params addr:pending:scry)
%get-pending-tx `(hash:pending id +.params hash:pending:scry)
%get-transaction-status `(status id +.params tx-status:scry)
%when-next-batch `(next-batch id +.params next-batch:scry)
%get-predicted-state `(get-naive id +.params predicted:scry)
%get-nonce `(nonce id +.params nonce:scry)
%get-history `(history id +.params addr:history:scry)
%get-roller-config `(get-config id +.params config:scry)
%prepare-for-signing `(hash-transaction id +.params chain:scry | &)
%get-unsigned-tx `(hash-transaction id +.params chain:scry & |)
%get-predicted-state `(get-naive id +.params predicted:scry)
%prepare-for-signing `(hash-transaction id +.params chain:scry | &)
%hash-raw-transaction `(hash-raw-transaction id +.params)
:: TODO: deprecated, remove (used together with personal_sign)
::
%hash-transaction ::`(hash-transaction id +.params chain:scry | &)
`(hash-transaction id +.params chain:scry & |)
==
--
::
@ -307,7 +306,13 @@
++ next-batch
.^ time
%gx
(~(scry agentio bowl) %roller /next-batch/noun)
(~(scry agentio bowl) %roller /next-batch/atom)
==
::
++ next-slice
.^ time
%gx
(~(scry agentio bowl) %roller /next-slice/atom)
==
::
++ nonce
@ -356,6 +361,20 @@
(~(scry agentio bowl) %roller /over-quota/(scot %p ship)/atom)
==
::
++ ship-quota
|= =ship
.^ @ud
%gx
(~(scry agentio bowl) %roller /ship-quota/(scot %p ship)/atom)
==
::
++ allowance
|= =ship
.^ (unit @ud)
%gx
(~(scry agentio bowl) %roller /allowance/(scot %p ship)/noun)
==
::
++ ready
.^ ?
%gx

File diff suppressed because it is too large Load Diff

View File

@ -30,4 +30,4 @@
?. =(*^rift rift)
rift
+(.^(^rift j+/(scot %p our)/rift/(scot %da now)/(scot %p mon)))
`[mon *id:block:jael %rift rift]
`[mon *id:block:jael %rift rift %.n]

View File

@ -42,4 +42,4 @@
leaf+(scow %uw (jam seed))
==
pub:ex:cub
`[mon *id:block:jael %keys life 1 pass]
`[mon *id:block:jael %keys [life 1 pass] %.n]

View File

@ -41,4 +41,4 @@
leaf+(scow %uw (jam seed))
==
pub:ex:cub
`[mon *id:block:jael %keys 1 1 pass]
`[mon *id:block:jael %keys [1 1 pass] %.n]

View File

@ -0,0 +1,6 @@
:: Assigns a specific quota to the given ship
:: Not providing a quota allows the ship to submit any number of transactions
::
:- %say
|= [* [=ship quota=(unit @ud) ~] ~]
[%roller-action %assign ship quota]

View File

@ -0,0 +1,5 @@
:: Bumps the gas price for a sending transaction
::
:- %say
|= [* [nonce=@ gas=@ud address=(unit @ux) ~] ~]
[%roller-action %refuel nonce address gas]

View File

@ -599,7 +599,7 @@
~(parse error:json-rpc id)
[%result id (tx-status:to-json (scry u.hash))]
::
++ next-batch
++ next-timer
|= [id=@t params=(map @t json) when=time]
^- response:rpc
?. =((lent ~(tap by params)) 0)
@ -680,4 +680,25 @@
?. =((lent ~(tap by params)) 0)
~(params error:json-rpc id)
[%result id (azimuth-config:to-json azimuth-config)]
::
++ quota-remaining
|= [id=@t params=(map @t json) quota-left=$-(@p @ud)]
^- response:rpc
?. =((lent ~(tap by params)) 1)
~(params error:json-rpc id)
?~ ship=(ship:from-json params)
~(params error:json-rpc id)
[%result id (numb:enjs:format (quota-left u.ship))]
::
++ ship-allowance
|= [id=@t params=(map @t json) allowance=$-(@p (unit @ud))]
^- response:rpc
?. =((lent ~(tap by params)) 1)
~(params error:json-rpc id)
?~ ship=(ship:from-json params)
~(params error:json-rpc id)
:+ %result id
?^ allow=(allowance u.ship)
(numb:enjs:format u.allow)
s+(crip "No quota restrictions for {(scow %p u.ship)}")
--

View File

@ -42,8 +42,14 @@
%adopt (adopt:dat +.call)
%start-document-poll (start-document-poll:dat +.call)
%cast-document-vote (cast-document-vote:dat +.call)
%start-upgrade-poll (start-upgrade-poll:dat +.call)
%cast-upgrade-vote (cast-upgrade-vote:dat +.call)
::
%send-point (send-point:dat +.call)
::
%approve-batch-transfer (approve-batch-transfer:dat +.call)
%transfer-batch (transfer-batch:dat +.call)
%withdraw (withdraw:dat +.call)
==
::
+$ call-data call-data:rpc
@ -67,12 +73,18 @@
++ adopt (enc adopt:cal)
++ start-document-poll (enc start-document-poll:cal)
++ cast-document-vote (enc cast-document-vote:cal)
++ start-upgrade-poll (enc start-upgrade-poll:cal)
++ cast-upgrade-vote (enc cast-upgrade-vote:cal)
::
++ register-linear (enc register-linear:cal)
++ register-conditional (enc register-conditional:cal)
++ deposit (enc deposit:cal)
::
++ send-point (enc send-point:cal)
::
++ approve-batch-transfer (enc approve-batch-transfer:cal)
++ transfer-batch (enc transfer-batch:cal)
++ withdraw (enc withdraw:cal)
--
::
::TODO lib
@ -170,6 +182,25 @@
[%bool support]
==
::
++ start-upgrade-poll
|= [gal=ship =address]
^- call-data
?> =(%czar (clan:title gal))
:- 'startUpgradePoll(uint8,address)'
:~ [%uint `@`gal]
[%address address]
==
::
++ cast-upgrade-vote
|= [gal=ship =address support=?]
^- call-data
?> =(%czar (clan:title gal))
:- 'castUpgradeVote(uint8,address,bool)'
:~ [%uint `@`gal]
[%address address]
[%bool support]
==
::
::
++ set-dns-domains
|= [pri=tape sec=tape ter=tape]
@ -252,6 +283,27 @@
[%address to]
==
::
++ approve-batch-transfer
|= to=address
^- call-data
:- 'approveBatchTransfer(address)'
:~ [%address to]
==
::
++ transfer-batch
|= from=address
^- call-data
:- 'transferBatch(address)'
:~ [%address from]
==
::
++ withdraw
|= to=address
^- call-data
:- 'withdraw(address)'
:~ [%address to]
==
::
:: read calls
::
++ rights

View File

@ -1,207 +1,388 @@
:: dice: helper functions for L2 Rollers
::
/- *dice
/+ naive, *naive-transactions
/+ naive, *naive-transactions, ethereum, azimuth
:: verbose bit
::
=| verb=?
::
|%
:: orp: ordered points in naive state by parent ship
::
++ orp ((on ship point:naive) por:naive)
:: ors: ordered sending map by (increasing) L1 nonce
::
++ ors ((on l1-tx-pointer send-tx) nonce-order)
:: orh: ordered tx history by (decreasing) timestamp
::
++ orh ((on time roll-tx) gth)
::
++ nonce-order
|= [a=[* =nonce:naive] b=[* =nonce:naive]]
(lte nonce.a nonce.b)
::
++ apply-effects
|= [chain-t=@ =effects:naive =indices]
++ data-to-hex
|= data=@t
?~ data *@ux
?: =(data '0x') *@ux
(hex-to-num:ethereum data)
::
++ get-network
|= =net
^- [azimuth=@ux naive=@ux chain-id=@ launch=@]
=< [azimuth naive chain-id launch]
=, azimuth
?- net
%mainnet mainnet-contracts
%ropsten ropsten-contracts
%local local-contracts
%default contracts
==
::
++ last-block-id
|= logs=(list event-log:rpc:ethereum)
^- id:block:jael
%+ roll logs
|= [log=event-log:rpc:ethereum =id:block:jael]
?~ mined.log id
?. (gth block-number.u.mined.log number.id)
id
[block-hash block-number]:u.mined.log
::
++ tx-effects
|= [chain-t=@ =effects:naive nas=^state:naive =indices]
^+ indices
%+ roll effects
|= [=diff:naive indices=_indices]
?. ?=([%tx *] diff) indices::[nas own spo]
=< indices
(apply-raw-tx | chain-t raw-tx.diff indices)
%+ roll effects
|= [=diff:naive nas=_nas indices=_indices]
?. ?=([%tx *] diff) [nas indices]
=< [nas indices]
%- %*(. apply-raw-tx verb |)
[| chain-t raw-tx.diff nas indices]
::
++ apply-raw-tx
|= [force=? chain-t=@ =raw-tx:naive =indices]
^- [? ups=(list update) indices=_indices]
=+ cache-nas=nas.indices
|= [force=? chain-t=@ =raw-tx:naive nas=^state:naive =indices]
^- [? (list update) nas=_nas indices=_indices]
=+ cache=nas
=/ chain-t=@t (ud-to-ascii:naive chain-t)
?. (verify-sig-and-nonce:naive verifier chain-t nas.indices raw-tx)
~& [%verify-sig-and-nonce %failed tx.raw-tx]
[force ~ indices]
=^ * points.nas.indices
(increment-nonce:naive nas.indices from.tx.raw-tx)
?~ nex=(receive-tx:naive nas.indices tx.raw-tx)
~& [%receive-tx %failed]
=? nas.indices !force cache-nas
[force ~ indices]
?. (verify-sig-and-nonce:naive verifier chain-t nas raw-tx)
=+ [force ~ nas indices]
?. verb -
~& >>> [verb+verb %verify-sig-and-nonce %failed tx.raw-tx] -
=^ effects-1 points.nas
(increment-nonce:naive nas from.tx.raw-tx)
?~ nex=(receive-tx:naive nas tx.raw-tx)
=+ [force ~ ?:(force nas cache) indices]
?. verb -
~& >>> [verb+verb %receive-tx %failed] -
=* new-nas +.u.nex
=* effects -.u.nex
=/ [updates=(list update) own=_own.indices spo=_spo.indices]
(update-indices effects cache-nas new-nas [own spo]:indices)
=: nas.indices new-nas
own.indices own
spo.indices spo
==
[& updates indices]
=/ effects (welp effects-1 -.u.nex)
=^ updates indices
(point-effects effects points.cache points.new-nas [own spo]:indices)
[& updates new-nas indices]
::
++ update-indices
|= $: =effects:naive
cache-nas=^state:naive
nas=^state:naive
=owners
=sponsors
==
^- [(list update) own=_owners spo=_sponsors]
%+ roll effects
|= $: =diff:naive
ups=(list update)
owners=_owners
sponsors=_sponsors
==
=, orm:naive
?. ?=([%point *] diff) [ups owners sponsors]
=* ship ship.diff
=/ old=(unit point:naive)
(get points.cache-nas ship)
=/ new=point:naive
(need (get points.nas ship))
++ point-effects
|= [=effects:naive cache=points:naive =points:naive =indices]
^- [(list update) indices=_indices]
=^ updates=(list update) indices
%+ roll effects
|= [=diff:naive updates=(list update) indices=_indices]
?. |(?=([%point *] diff) ?=([%nonce *] diff))
[updates indices]
?: ?=([%nonce *] diff)
:_ indices
(welp (nonce-updates diff cache points) updates)
?> ?=([%point *] diff)
=* ship ship.diff
=* sponsors spo.indices
=* owners own.indices
=/ old=(unit point:naive) (get:orp cache ship)
=/ new=point:naive (need (get:orp points ship))
=^ update-1 sponsors
(sponsorship-diff diff ship new old sponsors)
=^ update-2 owners
(ownership-diff diff ship new old owners)
=/ update-3=_updates
(point-data-updates diff ship new old)
:_ indices
:(welp update-3 update-2 update-1 updates)
[(flop updates) indices]
::
++ sponsorship-diff
|= [=diff:naive =ship new=point:naive old=(unit point:naive) =sponsors]
^- (quip update _sponsors)
?. ?=([%point *] diff) `sponsors
=* event +>.diff
|^
=^ updates owners ownership
=+ sponsors=sponsorship
:+ (weld ups updates)
owners
sponsors
::
++ sponsorship
^+ sponsors
?+ -.event sponsors
%owner
?^ old
:: ownership change
::
sponsors
:: owner event with ?=(~ old) is a spawn
?+ -.event `sponsors
%owner
?^ old
:: ownership change
::
=* parent who.sponsor.net.new
?: =(parent ship) sponsors
%+ ~(put by sponsors) parent
?~ sponsor=(~(get by sponsors) parent)
:_ *(set @p)
(~(put in *(set @p)) ship)
:_ requests.u.sponsor
(~(put in residents.u.sponsor) ship)
`sponsors
:: owner event with ?=(~ old) is a spawn
::
%escape
?~ old sponsors
=* from who.sponsor.net.u.old
=* to to.event
=* escape escape.net.u.old
?~ to
:: cancel/reject escape
::
?~ escape sponsors
?~ receiver=(~(get by sponsors) u.escape)
sponsors
%+ ~(put by sponsors) u.escape
:- residents.u.receiver
(~(del in requests.u.receiver) ship)
:: normal escape
=* parent who.sponsor.net.new
?: =(parent ship) `sponsors
:: updates for proxy %own are taken care of
:: in +sponsorship to avoid duplicates
::
:- ~
%+ ~(put by sponsors) parent
?~ sponsor=(~(get by sponsors) parent)
:_ *(set @p)
(~(put in *(set @p)) ship)
:_ requests.u.sponsor
(~(put in residents.u.sponsor) ship)
::
%escape
?~ old `sponsors
=* from who.sponsor.net.u.old
=* to to.event
=* escape escape.net.u.old
?~ to
:: cancel/reject escape
::
%+ ~(put by sponsors) u.to
?~ receiver=(~(get by sponsors) u.to)
:- *(set @p)
(~(put in *(set @p)) ship)
?~ escape `sponsors
?~ receiver=(~(get by sponsors) u.escape)
`sponsors
::
:- (proxy-updates diff ship new old)
::
%+ ~(put by sponsors) u.escape
:- residents.u.receiver
(~(put in requests.u.receiver) ship)
(~(del in requests.u.receiver) ship)
:: normal escape
::
%sponsor
?~ old sponsors
=* from who.sponsor.net.u.old
=* to sponsor.event
=/ previous (~(get by sponsors) from)
?~ to
:: detach
::
?~ previous sponsors
%+ ~(put by sponsors) from
:_ requests.u.previous
(~(del in residents.u.previous) ship)
:: accepted
::
=/ receiver (~(get by sponsors) u.to)
=? sponsors ?=(^ receiver)
%+ ~(put by sponsors) u.to
:- (~(put in residents.u.receiver) ship)
(~(del in requests.u.receiver) ship)
=? sponsors ?=(^ previous)
%+ ~(put by sponsors) from
:_ requests.u.previous
(~(del in residents.u.previous) ship)
sponsors
==
:- (proxy-updates diff ship new old)
::
%+ ~(put by sponsors) u.to
?~ receiver=(~(get by sponsors) u.to)
:- *(set @p)
(~(put in *(set @p)) ship)
:- residents.u.receiver
(~(put in requests.u.receiver) ship)
::
++ ownership
^- (quip update _owners)
=; [to=(unit owner) from=(unit owner)]
=? owners &(?=(^ from) !=(address.u.from 0x0))
(~(del ju owners) u.from ship)
?: ?| =(~ to)
&(?=(^ to) =(address.u.to 0x0))
==
[ups owners]
?~ to [ups owners]
:_ (~(put ju owners) u.to ship)
(snoc ups [%point ship new u.to from])
?+ -.event [~ ~]
%owner
:- `[%own +.event]
?~ old ~
`[%own address.owner.own.u.old]
%sponsor
?~ old `sponsors
=* from who.sponsor.net.u.old
=* to sponsor.event
=/ previous (~(get by sponsors) from)
?~ to
:: detach
::
?~ previous `sponsors
::
:- (proxy-updates diff ship new old)
::
%+ ~(put by sponsors) from
:_ requests.u.previous
(~(del in residents.u.previous) ship)
:: accepted
::
%management-proxy
:- `[%manage +.event]
?~ old ~
`[%manage address.management-proxy.own.u.old]
=/ receiver (~(get by sponsors) u.to)
=? sponsors ?=(^ receiver)
%+ ~(put by sponsors) u.to
:- (~(put in residents.u.receiver) ship)
(~(del in requests.u.receiver) ship)
=? sponsors ?=(^ previous)
%+ ~(put by sponsors) from
:_ requests.u.previous
(~(del in residents.u.previous) ship)
:_ sponsors
(proxy-updates diff ship new old)
==
::
++ ownership-diff
|= [=diff:naive =ship new=point:naive old=(unit point:naive) =owners]
^- (quip update _owners)
?. ?=([%point *] diff) `owners
=* event +>.diff
=; [to=(unit owner) from=(unit owner)]
=? owners &(?=(^ from) !=(address.u.from 0x0))
(~(del ju owners) u.from ship)
?: ?| =(~ to)
&(?=(^ to) =(address.u.to 0x0))
==
[~ owners]
?~ to [~ owners]
:_ (~(put ju owners) u.to ship)
[%point diff ship new old u.to from]~
?+ -.event [~ ~]
%owner
:- `[%own +.event]
?~ old ~
`[%own address.owner.own.u.old]
::
%management-proxy
:- `[%manage +.event]
?~ old ~
`[%manage address.management-proxy.own.u.old]
::
%spawn-proxy
:- `[%spawn +.event]
?~ old ~
`[%spawn address.spawn-proxy.own.u.old]
::
%voting-proxy
:- `[%vote +.event]
?~ old ~
`[%vote address.voting-proxy.own.u.old]
::
%transfer-proxy
:- `[%transfer +.event]
?~ old ~
`[%transfer address.transfer-proxy.own.u.old]
==
::
++ create-indices
|= nas=^state:naive
^- [sponsors owners]
%+ roll (tap:orp points.nas)
|= [[=ship =point:naive] =sponsors =owners]
|^
=? sponsors has.sponsor.net.point
^+ sponsors
(add-resident who.sponsor.net.point)
=? sponsors ?=(^ escape.net.point)
(add-request u.escape.net.point)
[sponsors add-ownership]
::
++ add-resident
|= sponsor=@p
^+ sponsors
:: galaxies have themselves as their sponsors
::
%spawn-proxy
:- `[%spawn +.event]
?~ old ~
`[%spawn address.spawn-proxy.own.u.old]
?: =(sponsor ship) sponsors
%+ ~(put by sponsors) sponsor
?~ sponsees=(~(get by sponsors) sponsor)
:_ *(set @p)
(~(put in *(set @p)) ship)
:_ requests.u.sponsees
(~(put in residents.u.sponsees) ship)
::
++ add-request
|= sponsor=@p
^+ sponsors
:: galaxies have themselves as their sponsors
::
%voting-proxy
:- `[%vote +.event]
?~ old ~
`[%vote address.voting-proxy.own.u.old]
::
%transfer-proxy
:- `[%transfer +.event]
?~ old ~
`[%transfer address.transfer-proxy.own.u.old]
==
?: =(sponsor ship) sponsors
%+ ~(put by sponsors) sponsor
?~ receiver=(~(get by sponsors) sponsor)
:- *(set @p)
(~(put in *(set @p)) ship)
:- residents.u.receiver
(~(put in requests.u.receiver) ship)
::
++ add-ownership
^+ owners
=/ proxies=(list proxy:naive)
~[%own %spawn %manage %vote %transfer]
%+ roll proxies
|= [=proxy:naive own=_owners]
?~ owner=(get-owner point proxy)
own
(~(put ju own) u.owner ship)
--
::
++ proxy-updates
|= [=diff:naive =ship =point:naive old=(unit point:naive)]
^- (list update)
=/ proxies=(list proxy:naive)
~[%own %spawn %manage %vote %transfer]
?~ old ~
%- flop
%+ roll proxies
|= [=proxy:naive updates=(list update)]
?~ owner=(get-owner u.old proxy) updates
:_ updates
[%point diff ship point old u.owner ~]
::
++ nonce-updates
|= [=diff:naive cache=points:naive =points:naive]
^- (list update)
?. ?=([%nonce *] diff) ~
=/ old=(unit point:naive) (get:orp cache ship.diff)
=/ new=point:naive (need (get:orp points ship.diff))
(point-data-updates diff ship.diff new old)
::
++ point-data-updates
|= [=diff:naive =ship =point:naive old=(unit point:naive)]
^- (list update)
?. ?=([%point *] diff) ~
=* event +>.diff
?+ -.event ~
%rift (proxy-updates +<)
%keys (proxy-updates +<)
%dominion (proxy-updates +<)
==
::
++ get-owner
|= [=point:naive =proxy:naive]
^- [nonce=@ _point]
=* own own.point
^- (unit owner)
=, own.point
?- proxy
%own
:- nonce.owner.own
point(nonce.owner.own +(nonce.owner.own))
?:(=(address.owner 0x0) ~ `own+address.owner)
::
%spawn
:- nonce.spawn-proxy.own
point(nonce.spawn-proxy.own +(nonce.spawn-proxy.own))
?:(=(address.spawn-proxy 0x0) ~ `spawn+address.spawn-proxy)
::
%manage
:- nonce.management-proxy.own
point(nonce.management-proxy.own +(nonce.management-proxy.own))
?:(=(address.management-proxy 0x0) ~ `manage+address.management-proxy)
::
%vote
:- nonce.voting-proxy.own
point(nonce.voting-proxy.own +(nonce.voting-proxy.own))
?:(=(address.voting-proxy 0x0) ~ `vote+address.voting-proxy)
::
%transfer
:- nonce.transfer-proxy.own
point(nonce.transfer-proxy.own +(nonce.transfer-proxy.own))
?:(=(address.transfer-proxy 0x0) ~ `transfer+address.transfer-proxy)
==
::
++ get-nonce
|= [=point:naive =proxy:naive]
^- nonce:naive
=, own.point
?- proxy
%own nonce.owner
%spawn nonce.spawn-proxy
%manage nonce.management-proxy
%vote nonce.voting-proxy
%transfer nonce.transfer-proxy
==
::
++ controlled-ships
|= [=address:ethereum =owners]
^- (list [=proxy:naive =ship])
=/ proxies=(list proxy:naive)
~[%own %spawn %manage %vote %transfer]
%+ roll proxies
|= [=proxy:naive ships=(list [=proxy:naive ship])]
%+ welp
%+ turn
~(tap in (~(get ju owners) [proxy address]))
(lead proxy)
ships
:: +update-history: updates status for all given list of transaction
::
++ update-history
|= [=history txs=(list pend-tx) =status]
^- (quip update _history)
=^ updates=(list update) history
%+ roll txs
|= [=pend-tx ups=(list update) history=_history]
=, pend-tx
=/ =roll-tx
=, pend-tx
:* ship.from.tx.raw-tx
status
(hash-raw-tx raw-tx)
(l2-tx +<.tx.raw-tx)
==
=/ txs=(tree hist-tx)
?~ txs=(~(get by history) address) ~
u.txs
=? txs ?=(^ txs) +:(del:orh txs time)
:- [tx+[pend-tx status] ups]
%+ ~(put by history) address
(put:orh txs [time roll-tx])
[(flop updates) history]
--

View File

@ -136,6 +136,7 @@
::
++ poke
|= [=mark =vase]
?> =(our src):hid
?+ mark ~|([%poke-drum-bad-mark mark] !!)
%drum-dill-belt =;(f (f !<(_+<.f vase)) poke-dill-belt)
%drum-dill-blit =;(f (f !<(_+<.f vase)) poke-dill-blit)

View File

@ -1,27 +1,33 @@
/+ pill
=* card card:agent:gall
|%
+$ state state-1
+$ state state-2
+$ any-state
$~ *state
$% state-1
$% state-2
state-1
state-0
==
+$ state-1
$: %1
mass-timer=[way=wire nex=@da tim=@dr]
==
+$ state-2 [%2 =mass-timer]
+$ state-1 [%1 =mass-timer]
+$ state-0 [%0 hoc=(map bone session-0)]
+$ session-0
$: say=*
mud=*
mass-timer=[way=wire nex=@da tim=@dr]
=mass-timer
==
::
+$ mass-timer [way=wire nex=@da tim=@dr]
::
++ state-0-to-1
|= s=state-0
^- state
^- state-1
[%1 mass-timer:(~(got by hoc.s) 0)]
::
++ state-1-to-2
|= s=state-1
^- state-2
[%2 +.s]
--
|= [=bowl:gall sat=state]
=| moz=(list card)
@ -39,11 +45,17 @@
^+ this
?~(caz this $(caz t.caz, this (emit i.caz)))
::
++ on-init
(poke-serve [~ /who] %base /gen/who/hoon ~)
::
++ on-load
|= [hood-version=@ud old=any-state]
=< abet
=? old ?=(%0 -.old) (state-0-to-1 old)
?> ?=(%1 -.old)
=? old ?=(%0 -.old) (state-0-to-1 old)
=? this ?=(%1 -.old)
(emil -:(poke-serve [~ /who] %base /gen/who/hoon ~))
=? old ?=(%1 -.old) (state-1-to-2 old)
?> ?=(%2 -.old)
this(sat old)
::
++ poke-rekey :: rotate private keys
@ -199,6 +211,9 @@
::
++ poke
|= [=mark =vase]
?> ?| ?=(%helm-hi mark)
=(our src):bowl
==
?+ mark ~|([%poke-helm-bad-mark mark] !!)
%helm-ames-sift =;(f (f !<(_+<.f vase)) poke-ames-sift)
%helm-ames-verb =;(f (f !<(_+<.f vase)) poke-ames-verb)

View File

@ -0,0 +1,20 @@
:: /app/azimuth state snapshot
::
/- *dice
::
|_ snap=snap-state
++ grab
|%
++ noun snap-state
++ mime
|= [mite =octs]
(noun (cue q.octs))
--
::
++ grow
|%
++ mime
[/application/octet-stream (as-octs:mimes:html (jam snap))]
--
++ grad %mime
--

View File

@ -66,8 +66,14 @@
[%adopt who=ship]
[%start-document-poll gal=ship hash=@]
[%cast-document-vote gal=ship hash=@ vote=?]
[%start-upgrade-poll gal=ship =address]
[%cast-upgrade-vote gal=ship =address vote=?]
::
[%send-point as=ship point=ship to=address]
::
[%approve-batch-transfer to=address]
[%transfer-batch from=address]
[%withdraw to=address]
==
::
++ prep-result

View File

@ -1,15 +1,18 @@
:: dice: structures for L2 rollers
:: dice: structures for Azimuth L2 rollers
::
/+ naive, ethereum
::
|%
+$ owner [=proxy:naive =address:naive]
+$ owners (jug owner ship)
+$ sponsors (map ship [residents=(set ship) requests=(set ship)])
+$ net ?(%mainnet %ropsten %local %default)
+$ owner [=proxy:naive =address:naive]
+$ owners (jug owner ship)
+$ sponsors (map ship [residents=(set ship) requests=(set ship)])
+$ history (map address:ethereum (tree hist-tx))
+$ net ?(%mainnet %ropsten %local %default)
+$ snap-state [%0 =id:block:jael nas=^state:naive =owners =sponsors]
::
+$ config
$% [%frequency frequency=@dr]
[%fallback gas=@ud]
[%setkey pk=@]
[%endpoint endpoint=@t =net]
[%resend-time time=@dr]
@ -19,8 +22,7 @@
==
::
+$ indices
$: nas=^state:naive
own=owners
$: own=owners
spo=sponsors
==
::
@ -69,9 +71,16 @@
==
::
+$ update
$% [%point =ship =point:naive new=owner old=(unit owner)]
[%tx =address:ethereum =roll-tx]
==
$% [%tx =pend-tx =status]
::
$: %point
=diff:naive
=ship
new=point:naive
old=(unit point:naive)
to=owner
from=(unit owner)
== ==
::
+$ hist-tx [p=time q=roll-tx]
+$ roll-tx [=ship =status hash=keccak type=l2-tx]
@ -90,7 +99,12 @@
pk=@
::
nonce=@ud
fallback-gas-price=@ud
next-gas-price=@ud
txs=(list raw-tx:naive)
==
::
+$ roller-data
[chain-id=@ =points:naive history=(tree hist-tx) =owners =sponsors]
::
--

View File

@ -48,7 +48,7 @@
+$ dock (pair @p term)
+$ gang (unit (set ship))
+$ mark @tas
+$ mein [our=ship now=@da eny=@uvJ]
+$ mien [our=ship now=@da eny=@uvJ]
++ omen |$ [a] (pair path (cask a))
+$ ship @p
+$ sink (trel bone ship path)
@ -214,7 +214,7 @@
:: zen: Outside knowledge
:: mod: internal modules
::
mein
mien
$= fad
$: :: lac: not verbose
::
@ -1294,31 +1294,30 @@
^- mass
=; sam=(list mass)
:+ %arvo %|
:~ hoon+&+pit
zuse+&+zus.mod
:~ :+ %hoon %|
:~ one+&+..bloq
two+&+..turn
tri+&+..year
qua+&+..sane
pen+&+..ride
==
hex+&+..part
pit+&+pit
lull+|+[dot+&+q typ+&+p ~]:lul.mod
zuse+|+[dot+&+q typ+&+p ~]:zus.mod
vane+|+sam
==
::
=/ von
%+ turn
(sort ~(tap by van.mod) |=([[a=@tas *] [b=@tas *]] (aor a b)))
::
:~ :+ %reports %|
=/ bem=beam [[our %home da+now] /whey] ::TODO %base?
%+ turn von
|= [nam=term =vane]
=/ met (peek [~ ~] nam bem)
~| mass/nam
?> &(?=(^ met) ?=(^ u.met)) :: XX make optional
nam^|+;;((list mass) q.q.u.u.met)
::
:+ %caches %|
%+ turn von
|=([nam=term =vane] nam^&+worm.vane)
::
:+ %dregs %|
%+ turn von
|=([nam=term =vane] nam^&+vase.vane)
==
=/ bem=beam [[our %home da+now] /whey] ::TODO %base?
|= [nam=term =vane]
=; mas=(list mass)
nam^|+(welp mas [dot+&+q.vase typ+&+p.vase sac+&+worm ~]:vane)
?~ met=(peek [~ ~] nam bem) ~
?~ u.met ~
~| mass+nam
;;((list mass) q.q.u.u.met)
:: +peek: read from the entire namespace
::
++ peek

View File

@ -1906,6 +1906,7 @@
[%private-keys ~] :: sub to privates
[%public-keys ships=(set ship)] :: sub to publics
[%rekey =life =ring] :: update private keys
[%resend ~] :: resend private key
[%ruin ships=(set ship)] :: pretend breach
$>(%trim vane-task) :: trim state
[%turf ~] :: view domains
@ -1980,8 +1981,8 @@
+$ udiffs (list [=ship =udiff])
+$ udiff
$: =id:block
$% [%rift =rift]
[%keys key-update]
$% [%rift =rift boot=?]
[%keys key-update boot=?]
[%spon sponsor=(unit @p)]
[%disavow ~]
== ==
@ -1995,14 +1996,14 @@
%rift
?. (gth rift.a-udiff rift.a-point)
~
~? !=(rift.a-udiff +(rift.a-point))
~? &(!=(rift.a-udiff +(rift.a-point)) !boot.a-udiff)
[%udiff-to-diff-skipped-rift a-udiff a-point]
`[%rift rift.a-point rift.a-udiff]
::
%keys
?. (gth life.a-udiff life.a-point)
~
~? !=(life.a-udiff +(life.a-point))
~? &(!=(life.a-udiff +(life.a-point)) !boot.a-udiff)
[%udiff-to-diff-skipped-life a-udiff a-point]
:^ ~ %keys
[life.a-point (~(gut by keys.a-point) life.a-point *[@ud pass])]

View File

@ -1593,10 +1593,12 @@
?~ sponsor
~| %ames-lost-sponsor^our^ship !!
::
=/ =peer-state (got-peer-state ship)
=. sponsor.peer-state u.sponsor
::
=. peers.ames-state (~(put by peers.ames-state) ship %known peer-state)
=/ state=(unit peer-state) (get-peer-state ship)
?~ state
%- (slog leaf+"ames: missing peer-state, ignoring" ~)
event-core
=. sponsor.u.state u.sponsor
=. peers.ames-state (~(put by peers.ames-state) ship %known u.state)
event-core
:: +on-publ-full: handle new pki data for peer(s)
::

View File

@ -427,6 +427,13 @@
%- curd =< abet
(private-keys:~(feel su hen now pki etn) life.tac ring.tac)
::
:: resend private key to subscribers
::
%resend
%- curd =< abet
%- ~(exec su hen now pki etn)
[yen.own.pki [%give %private-keys [lyf jaw]:own.pki]]
::
:: register moon keys
::
%moon
@ -733,14 +740,18 @@
=/ a-point=point (~(gut by pos.zim.pki) ship.i.udiffs *point)
=/ a-diff=(unit diff:point) (udiff-to-diff:point udiff.i.udiffs a-point)
=? this-su ?=(^ a-diff)
:: if this about our keys, and we already know these, start using them
::
=? lyf.own
=? this-su
?& =(our ship.i.udiffs)
?=(%keys -.u.a-diff)
(~(has by jaw.own) life.to.u.a-diff)
==
life.to.u.a-diff
:: if this about our keys, and we already know these, start using them
::
=. lyf.own life.to.u.a-diff
:: notify subscribers (ames) to start using our new private keys
::
(exec yen.own [%give %private-keys [lyf jaw]:own])
::
(public-keys:feel original-pos %diff ship.i.udiffs u.a-diff)
$(udiffs t.udiffs)
::

View File

@ -4422,7 +4422,7 @@
:: :: ++chrd:de-xml:html
++ chrd :: character data
%+ cook |=(a=tape ^-(mars ;/(a)))
(plus ;~(less doq ;~(pose (just `@`10) escp)))
(plus ;~(pose (just `@`10) escp))
:: :: ++comt:de-xml:html
++ comt :: comments
=- (ifix [(jest '<!--') (jest '-->')] (star -))

View File

@ -0,0 +1,72 @@
:: Creates a snapshot of the azimuth state and its indices
:: (owners and sposnors) from a list of ethereum logs
::
/- spider, *dice
/+ strand,
azimuth,
strandio,
naive,
lib=naive-transactions,
ethereum,
dice
/* logs %eth-logs /app/azimuth/logs/eth-logs
=, strand=strand:spider
::
=> |% +$ card card:agent:gall
+$ task task:clay
+$ id id:block:jael
+$ events (list event-log:rpc:ethereum)
--
::
^- thread:spider
|= arg=vase
=/ m (strand ,vase)
^- form:m
=+ !<([~ =net file-name=@t] arg)
::
=/ [azimuth-contract=@ux chain-id=@]
[azimuth chain-id]:(get-network:dice net)
::
%- %- slog :_ ~
leaf+"azimuth: creating snapshot with {<(lent logs)>} events"
::
=/ [=id nas=^state:naive]
%+ roll `events`logs
|= [log=event-log:rpc:ethereum =id nas=^state:naive]
?~ mined.log
id^nas
=/ =^input:naive
:- block-number.u.mined.log
?: =(azimuth-contract address.log)
:- %log
[address.log (data-to-hex:dice data.log) topics.log]
?~ input.u.mined.log
[%bat *@]
[%bat u.input.u.mined.log]
=. id
?. (gth block-number.u.mined.log number.id)
id
[block-hash block-number]:u.mined.log
=^ * nas
(%*(. naive lac |) verifier:lib chain-id nas input)
id^nas
::
=/ [=sponsors =owners] (create-indices:dice nas)
::
%- %- slog
:~ leaf+"points: {<~(wyt by points.nas)>}"
leaf+"sponsors: {<~(wyt by sponsors)>}"
leaf+"owners: {<~(wyt by owners)>}"
leaf+"block-number: {<number.id>}"
leaf+"block-hash: {<hash.id>}"
==
::
=/ =path /app/azimuth/[file-name]/azimuth-snapshot
=/ =cage
:- %azimuth-snapshot
!> ^- snap-state
[%0 id nas owners sponsors]
=/ =task [%info %base %& [path %ins cage]~]
=/ =card [%pass /next %arvo %c task]
;< ~ bind:m (send-raw-card:strandio card)
(pure:m !>('azimuth logs processed'))

View File

@ -0,0 +1,43 @@
:: Creates a snapshot of the azimuth state and its indices
:: (owners and sposnors) from scrying /app/azimuth
::
::
/- spider, *dice
/+ strand, strandio, naive, ethereum, dice
=, strand=strand:spider
=, jael
::
=> |% +$ card card:agent:gall
+$ task task:clay
+$ events (list event-log:rpc:ethereum)
--
::
^- thread:spider
|= arg=vase
=/ m (strand ,vase)
^- form:m
=+ !<([~ file-name=@t] arg)
::
;< nas=^state:naive bind:m (scry:strandio ^state:naive /gx/azimuth/nas/noun)
;< =owners bind:m (scry:strandio owners /gx/azimuth/own/noun)
;< =sponsors bind:m (scry:strandio sponsors /gx/azimuth/spo/noun)
;< =events bind:m (scry:strandio events /gx/azimuth/logs/noun)
=/ =id:block (last-block-id:dice events)
::
%- %- slog
:~ leaf+"points: {<~(wyt by points.nas)>}"
leaf+"sponsors: {<~(wyt by sponsors)>}"
leaf+"owners: {<~(wyt by owners)>}"
leaf+"block-number: {<number.id>}"
leaf+"block-hash: {<hash.id>}"
==
::
=/ =path /app/azimuth/[file-name]/azimuth-snapshot
=/ =cage
:- %azimuth-snapshot
!> ^- snap-state
[%0 id nas owners sponsors]
=/ =task [%info %base %& [path %ins cage]~]
=/ =card [%pass /next %arvo %c task]
;< ~ bind:m (send-raw-card:strandio card)
(pure:m !>('azimuth state saved'))

View File

@ -82,8 +82,8 @@
|= [pup=watchpup =latest=number:block]
=/ m (strand:strandio ,watchpup)
^- form:m
=/ zoom-margin=number:block 0 :: TODO: 30!
=/ zoom-step=number:block 100.000
=/ zoom-margin=number:block 30
=/ zoom-step=number:block 100.000
?: (lth latest-number (add number.pup zoom-margin))
(pure:m pup)
=/ up-to-number=number:block

View File

@ -9,32 +9,40 @@
=/ m (strand:strandio ,vase)
|^
^- form:m
:: =* not-sent (pure:m !>(%.n^next-gas-price))
::
=/ =address:ethereum (address-from-prv:key:ethereum pk)
;< expected-nonce=@ud bind:m
(get-next-nonce:ethio endpoint address)
:: if chain expects a different nonce, don't send this transaction
::
?. =(nonce expected-nonce)
~& [%unexpected-nonce nonce expected+expected-nonce]
(pure:m !>(%.n^[%not-sent %unexpected-nonce]))
:: if a gas-price of 0 was specified, fetch the recommended one
::
;< use-gas-price=@ud bind:m
?: =(0 next-gas-price) fetch-gas-price
(pure:(strand:strandio @ud) next-gas-price)
::
=/ batch-data=octs
%+ cad:naive 3
%- flop
%+ roll txs
|= [=raw-tx:naive out=(list octs)]
[raw.raw-tx 65^sig.raw-tx out]
:: TODO: keep this to avoid sending bad batches or disregard?
:: if the batch is malformed, emit error to kick it out of sending
::
?~ (parse-roll:naive q.batch-data)
(pure:m !>(%.n^[%not-sent %batch-parse-error]))
:: if chain expects a different nonce, don't send this transaction
::
?. =(nonce expected-nonce)
~& >>> [%unexpected-nonce nonce expected+expected-nonce]
%- pure:m
!> ^- [%.n @tas @t]
:+ %.n
%not-sent
?: (lth expected-nonce nonce)
:: if ahead, it will use the same next-gas-price when resending
::
%ahead-nonce
:: if behind, start out-of-sync flow
::
%behind-nonce
:: if a gas-price of 0 was specified, fetch the recommended one
::
;< use-gas-price=@ud bind:m
?: =(0 next-gas-price) fetch-gas-price
(pure:(strand:strandio @ud) next-gas-price)
::
:: each l2 signature is 65 bytes + XX bytes for the raw data
:: from the ethereum yellow paper:
@ -72,7 +80,8 @@
:: log batch tx-hash to getTransactionReceipt(tx-hash)
::
~? &(?=(%result -.response) ?=(%s -.res.response))
^-([nonce=@ud batch-hash=@t] nonce^(so:dejs:format res.response))
^- [nonce=@ud batch-hash=@t gas=@ud]
nonce^(so:dejs:format res.response)^use-gas-price
%- pure:m
!> ^- (each @ud [term @t])
:: TODO: capture if the tx fails (e.g. Runtime Error: revert)
@ -101,10 +110,13 @@
;< rep=(unit client-response:iris) bind:m
take-maybe-response:strandio
=* fallback
~& %fallback-gas-price
(pure:m 10.000.000.000)
~& >> %fallback-gas-price
(pure:m fallback-gas-price)
?. ?& ?=([~ %finished *] rep)
?=(^ full-file.u.rep)
:: get suggested price only for mainnet txs
::
=(chain-id 1)
==
fallback
?~ jon=(de-json:html q.data.u.full-file.u.rep)
@ -115,7 +127,7 @@
(mul 1.000.000.000 u.res) ::NOTE gwei to wei
%. u.jon
=, dejs-soft:format
(ot 'result'^(ot 'FastGasPrice'^ni ~) ~)
(ot 'result'^(ot 'FastGasPrice'^(su dem) ~) ~)
::
++ send-batch
|= [endpoint=@ta batch=@ux]

View File

@ -87,7 +87,7 @@
0x223c.067f.8cf2.8ae1.73ee.5caf.ea60.ca44.c335.fecb
::
++ ecliptic
0xa5b6.109a.d2d3.5191.b3bc.32c0.0e45.26be.56fe.321f
0x33ee.cbf9.0847.8c10.6146.26a9.d304.bfe1.8b78.dd73
::
++ linear-star-release
0x86cd.9cd0.992f.0423.1751.e376.1de4.5cec.ea5d.1801

View File

@ -1,5 +1,6 @@
:: |pill: helper functions for making pills
::
/- dice
^?
|%
::
@ -80,7 +81,13 @@
=/ pax (weld bas lyt)
=/ lon .^(arch %cy pax)
=? hav ?=(^ fil.lon)
:_(hav [lyt mark=;;(@tas (head tyl)) noun=.^(* %cx pax)])
:_ hav
:- lyt
?. ?=([%azimuth-snapshot *] tyl)
[mark=;;(@tas (head tyl)) noun=.^(* %cx pax)]
=; convert
mime/(convert .^(snap-state:dice %cx pax))
.^($-(snap-state:dice mime) %cf (weld bas /azimuth-snapshot/mime))
=/ all ~(tap by dir.lon)
|- ^+ hav
?~ all hav

View File

@ -349,7 +349,7 @@
++ on-peek
|= =path
^- (unit (unit cage))
?. =(/x/dbug/state path) ~
?. =(/x/dbug/state path) (on-peek:og path)
``noun+(slop on-save:og !>(shoe=state))
::
++ on-agent

View File

@ -168,6 +168,11 @@
%+ turn ~(tap by charges)
|= [=desk =charge]
[desk (get-light-charge charge)]
::
[%x %charges @ %version ~]
?~ charge=(~(get by charges) i.t.t.path)
[~ ~]
``noun+!>(version.docket.u.charge)
==
::
++ on-agent

View File

@ -1,10 +1,10 @@
:~ title+'System'
info+'An app launcher for Urbit.'
color+0xee.5432
glob-http+['https://bootstrap.urbit.org/glob-0v4.64ana.19ug9.ik7l6.og080.68ce4.glob' 0v4.64ana.19ug9.ik7l6.og080.68ce4]
glob-http+['https://bootstrap.urbit.org/glob-0v5.1o2c9.g1btf.nandl.703oh.40up1.glob' 0v5.1o2c9.g1btf.nandl.703oh.40up1]
::glob-ames+~zod^0v0
base+'grid'
version+[1 0 2]
version+[1 0 3]
website+'https://tlon.io'
license+'MIT'
==

View File

@ -0,0 +1 @@
../../garden-dev/lib/hark-store.hoon

View File

@ -4,4 +4,5 @@ bin/
.vscode/
.husky/
*.config.js
*.config.ts
*.config.ts
package.json

47
pkg/grid/CONTRIBUTING.md Normal file
View File

@ -0,0 +1,47 @@
# Contributing to Landscape
Thank you for your interest in contributing to the Urbit ecosystem.
Landscape is entirely open to contributions from the community. We mainly organize through our [project board], [issues], and [weekly call].
For now our code is stored in the main [urbit repo]. If you would like to contribute feel free to open up a PR there.
## Git Conventions
For Landscape we follow the same conventions as the main repo which can be found in it's [contributing doc]. This can be summarized as the following:
Commits should try to be atomic and focused on one feature at a time. Work-in-progress commits should be rebased and combined into one so that the commit history stays clean.
Commits should follow this format:
> component: short description
>
> long description
Where `component` is the closest most relevant area of the code base written as concisely as possible. The short description that accompanies should be a super concise summary of the changes. The total length of the commit message should strive to be 50 characters or less. The long description is optional, but should be used if further explanation is necessary.
### Pull Requests
A pull request (PR) should have a title similar in structure to our commit messages where it has a short identifier component followed by a very concise summary of the PR's intent. All PRs should have a description further laying out what it accomplishes. If the PR addresses certain Github issues, those should be referenced in the body of the description so they get linked.
PRs to this repo should currently tag (or request review) from one of the following contributors:
- [Liam - @liam-fitzgerald](https://github.com/liam-fitzgerald)
- [Hunter - @arthyn](https://github.com/arthyn)
- [James - @nerveharp](https://github.com/nerveharp)
If design or visual changes are made, please provide screenshots and also tag (or request a review) from one of the following contributors:
- [Éd - @urcades](https://github.com/urcades)
- [Gavin - @g-a-v-i-n](https://github.com/g-a-v-i-n)
## Further Information
If you haven't yet, check out the main [contributing doc] at the base of the repo for information on how to get started developing on Urbit. Also you can find a host of resources on [developers.urbit.org], including ways to earn address space by contributing.
[project board]: https://github.com/orgs/urbit/projects/17
[issues]: https://github.com/urbit/landscape/issues
[weekly call]: https://github.com/urbit/landscape/issues/792
[urbit repo]: https://github.com/urbit/urbit
[contributing doc]: ../../CONTRIBUTING.md
[developers.urbit.org]: https://developers.urbit.org/

43
pkg/grid/README.md Normal file
View File

@ -0,0 +1,43 @@
# Landscape
Landscape provides the primary launching interface for Tlon's suite of userspace applications. This directory contains the front-end web application to power said interface.
Landscape is built primarily using [React], [Typescript], and [Tailwind CSS]. [Vite] ensures that all code and assets are loaded appropriately, bundles the application for distribution and provides a functional dev environment.
## Getting Started
To get started using Landscape first you need to run, `npm i && npm run bootstrap` at the top level of the greater urbit repo. This will install your npm dependencies and correctly link the current implementation of the packages at `pkg/npm/*` to your dependencies.
If you intend to edit those packages will developing on Landscape, you should also have `npm run watch-libs` running to build and re-link them after every change.
Once that's done, you can then run `npm run mock` if you'd like to get started immediately. This will use hard-coded mock data to power the interface so you can work on the interface without being connected to a ship.
To develop against a working ship, you first need to add a `.env.local` file to the root of this directory. This file will not be committed. Adding `VITE_SHIP_URL={URL}` where **{URL}** is the URL of the ship you would like to point to, will allow you to run `npm run dev`. This will proxy all requests to the ship except for those powering the interface, allowing you to see live data.
Regardless of what you run to develop, Vite will hot-reload code changes as you work so you don't have to constantly refresh.
## Deploying
To deploy, run `npm run build` which will bundle all the code and assets into the `dist/` folder. This can then be made into a glob by doing the following:
1. Create or launch an urbit using the -F flag
2. On that urbit, if you don't already have a desk to run from, run `|merge %work our %base` to create a new desk and mount it with `|mount %work`.
3. Now the `%work` desk is accessible through the host OS's filesystem as a directory of that urbit's pier ie `~/zod/work`.
4. From the directory of grid you can run `rsync -avL --delete dist/ ~/zod/work/grid` where `~/zod` is your fake urbit's pier.
5. Once completed you can then run `|commit %work` on your urbit and you should see your files logged back out from the dojo.
6. Now run `=dir /=garden` to switch to the garden desk directory
7. You can now run `-make-glob %work /grid` which will take the grid folder where you just added files and create a glob which can be thought of as a sort of bundle. It will be output to `~/zod/.urb/put`.
8. If you navigate to `~/zod/.urb/put` you should see a file that looks like this `glob-0v5.fdf99.nph65.qecq3.ncpjn.q13mb.glob`. The characters between `glob-` and `.glob` are a hash of the glob's contents.
9. If you're working at Tlon, you can upload this to our Google storage using `gsutil cp glob-*.* gs://bootstrap.urbit.org`. Otherwise any publicly available HTTP endpoint that can serve files should be sufficient for distributing the glob.
10. Once you've uploaded the glob, you should then update the corresponding entry in the docket file that represents Landscape which currently resides at `pkg/garden/desk.docket-0`. Both the full URL and the hash should be updated to match the glob we just created, on the line that looks like this:
```hoon
glob-http+['https://bootstrap.urbit.org/glob-0v5.fdf99.nph65.qecq3.ncpjn.q13mb.glob' 0v5.fdf99.nph65.qecq3.ncpjn.q13mb]
```
11. This can now be safely committed and deployed.
[react]: https://reactjs.org/
[typescript]: https://www.typescriptlang.org/
[tailwind css]: https://tailwindcss.com/
[vite]: https://vitejs.dev/

View File

@ -3,12 +3,14 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Urbit • Home</title>
<meta name="theme-color" content="#ffffff" />
<title>Urbit • Home</title>
<link rel="icon" href="/src/assets/favicon.svg" sizes="any" type="image/svg+xml" />
<link rel="mask-icon" href="/src/assets/safari-pinned-tab.svg" color="#000000" />
<link rel="apple-touch-icon" sizes="180x180" href="/src/assets/apple-touch-icon.png" />
<link rel="manifest" href="/src/assets/manifest.json" />
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)" />
<meta name="theme-color" content="#000000" media="(prefers-color-scheme: dark)" />
<meta name="theme-color" content="#ffffff" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link

27529
pkg/grid/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
{
"name": "landscape",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"mock": "vite --mode mock",
@ -21,8 +22,8 @@
"@radix-ui/react-toggle": "^0.0.10",
"@tlon/sigil-js": "^1.4.4",
"@types/lodash": "^4.14.172",
"@urbit/api": "^1.4.0",
"@urbit/http-api": "^1.3.1",
"@urbit/api": "^2.1.0",
"@urbit/http-api": "^2.1.0",
"big-integer": "^1.6.48",
"classnames": "^2.3.1",
"clipboard-copy": "^4.0.1",

View File

@ -1,8 +1,7 @@
import { chadIsRunning, Treaty } from '@urbit/api';
import { chadIsRunning, Treaty, Vat } from '@urbit/api';
import clipboardCopy from 'clipboard-copy';
import React, { FC, useCallback, useState } from 'react';
import cn from 'classnames';
import { Vat } from '@urbit/api/hood';
import { Button, PillButton } from './Button';
import { Dialog, DialogClose, DialogContent, DialogTrigger } from './Dialog';
import { DocketHeader } from './DocketHeader';
@ -137,19 +136,19 @@ export const AppInfo: FC<AppInfoProps> = ({ docket, vat, className }) => {
</div>
</DocketHeader>
<div className="space-y-6">
{vat ? (
<>
<hr className="-mx-5 sm:-mx-8 border-gray-50" />
<VatMeta vat={vat} />
</>
) : null}
{!treaty ? null : (
<>
<hr className="-mx-5 sm:-mx-8 border-gray-50" />
<TreatyMeta treaty={treaty} />
</>
)}
</div>
{vat ? (
<>
<hr className="-mx-5 sm:-mx-8 border-gray-50" />
<VatMeta vat={vat} />
</>
) : null}
{!treaty ? null : (
<>
<hr className="-mx-5 sm:-mx-8 border-gray-50" />
<TreatyMeta treaty={treaty} />
</>
)}
</div>
</div>
);
};

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { Docket } from '@urbit/api/docket';
import { Docket } from '@urbit/api';
import cn from 'classnames';
import { useTileColor } from '../tiles/useTileColor';

View File

@ -7,7 +7,13 @@ type ShipNameProps = {
export const ShipName = ({ name, ...props }: ShipNameProps) => {
const separator = /([_^-])/;
const parts = cite(name).replace('~', '').split(separator);
const citedName = cite(name);
if (!citedName) {
return null;
}
const parts = citedName.replace('~', '').split(separator);
const first = parts.shift();
return (

View File

@ -1,5 +1,5 @@
import React from 'react';
import { Vat } from '@urbit/api/hood';
import { Vat } from '@urbit/api';
import { Attribute } from './Attribute';

View File

@ -3,7 +3,7 @@ import classNames from 'classnames';
import clipboardCopy from 'clipboard-copy';
import React, { HTMLAttributes, useCallback, useState } from 'react';
import { Link, Route, useHistory } from 'react-router-dom';
import { Vat } from '@urbit/api/hood';
import { Vat } from '@urbit/api';
import { Adjust } from '../components/icons/Adjust';
import { useVat } from '../state/kiln';
import { disableDefault, handleDropdownLink } from '../state/util';

View File

@ -1,6 +1,6 @@
import { pick, pickBy, partition } from 'lodash';
import React, { useCallback } from 'react';
import { kilnBump } from '@urbit/api/hood';
import { kilnBump } from '@urbit/api';
import { AppList } from '../../components/AppList';
import { Button } from '../../components/Button';
import { Dialog, DialogClose, DialogContent, DialogTrigger } from '../../components/Dialog';

View File

@ -1,4 +1,4 @@
import { setMentions } from '@urbit/api/dist';
import { setMentions } from '@urbit/api';
import React from 'react';
import { Setting } from '../../components/Setting';
import { pokeOptimisticallyN } from '../../state/base';

View File

@ -1,5 +1,6 @@
/* eslint-disable no-param-reassign */
import {
BigIntOrderedMap,
makePatDa,
decToUd,
unixToDa,
@ -13,7 +14,6 @@ import {
NotificationGraphConfig,
archiveAll
} from '@urbit/api';
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
/* eslint-disable-next-line camelcase */
import { unstable_batchedUpdates } from 'react-dom';
import produce from 'immer';

View File

@ -1,5 +1,13 @@
import { getVats, Vats, scryLag, getBlockers, Vat, kilnInstall } from '@urbit/api';
import { kilnPause, kilnResume } from '@urbit/api/hood';
import {
getVats,
Vats,
scryLag,
getBlockers,
Vat,
kilnInstall,
kilnPause,
kilnResume
} from '@urbit/api';
import create from 'zustand';
import produce from 'immer';
import { useCallback } from 'react';

View File

@ -5,7 +5,7 @@ import {
putEntry as doPutEntry,
getDeskSettings,
DeskData
} from '@urbit/api/settings';
} from '@urbit/api';
import _ from 'lodash';
import {
BaseState,

View File

@ -1,4 +1,4 @@
import { Docket, DocketHref, Treaty } from '@urbit/api/docket';
import { Docket, DocketHref, Treaty } from '@urbit/api';
import { hsla, parseToHsla } from 'color2k';
import _ from 'lodash';

View File

@ -9,15 +9,14 @@ const { execSync } = require('child_process');
const GIT_DESC = execSync('git describe --always', { encoding: 'utf8' }).trim();
let devServer = {
contentBase: path.join(__dirname, '../public'),
hot: true,
port: 9000,
host: '0.0.0.0',
disableHostCheck: true,
historyApiFallback: {
index: '/apps/landscape/index.html',
disableDotRule: true
},
publicPath: '/apps/landscape/'
}
};
const router = _.mapKeys(urbitrc.FLEET || {}, (value, key) => `${key}.localhost:9000`);
@ -25,7 +24,6 @@ const router = _.mapKeys(urbitrc.FLEET || {}, (value, key) => `${key}.localhost
if(urbitrc.URL) {
devServer = {
...devServer,
index: 'index.html',
// headers: {
// 'Service-Worker-Allowed': '/'
// },
@ -73,7 +71,7 @@ module.exports = {
]
}
},
exclude: /node_modules\/(?!(@tlon\/indigo-dark|@tlon\/indigo-light|@tlon\/indigo-react)\/).*/
exclude: /node_modules\/(?!(@tlon\/indigo-dark|@tlon\/indigo-light|@tlon\/indigo-react|@urbit\/api)\/).*/
},
{
test: /\.css$/i,

View File

@ -30,7 +30,7 @@ module.exports = {
]
}
},
exclude: /node_modules\/(?!(@tlon\/indigo-dark|@tlon\/indigo-light|@tlon\/indigo-react)\/).*/
exclude: /node_modules\/(?!(@tlon\/indigo-dark|@tlon\/indigo-light|@tlon\/indigo-react|@urbit\/api)\/).*/
},
{
test: /\.css$/i,

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,8 @@
"@tlon/indigo-light": "^1.0.7",
"@tlon/indigo-react": "^1.2.27",
"@tlon/sigil-js": "^1.4.3",
"@urbit/api": "^1.4.0",
"@urbit/http-api": "^1.2.1",
"@urbit/api": "^2.1.0",
"@urbit/http-api": "^2.1.0",
"any-ascii": "^0.1.7",
"aws-sdk": "^2.830.0",
"big-integer": "^1.6.48",
@ -25,6 +25,7 @@
"css-loader": "^3.6.0",
"file-saver": "^2.0.5",
"formik": "^2.1.5",
"fuzzy": "^0.1.3",
"immer": "^9.0.2",
"lodash": "^4.17.21",
"moment": "^2.29.1",

View File

@ -1,7 +1,7 @@
import Urbit from '@urbit/http-api';
const api = new Urbit('', '', (window as any).desk);
api.ship = window.ship;
api.verbose = true;
// api.verbose = true;
// @ts-ignore TODO window typings
window.api = api;

View File

@ -1,5 +1,4 @@
import { Content, GraphNode, unixToDa } from '@urbit/api';
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import { BigIntOrderedMap, Content, GraphNode, unixToDa } from '@urbit/api';
import bigInt, { BigInteger } from 'big-integer';
export const makeComment = (

View File

@ -1,5 +1,4 @@
import { deSig, Path, PatpNoSig } from '@urbit/api';
import { Group, Resource, roleTags, RoleTags } from '@urbit/api/groups';
import { deSig, Path, PatpNoSig, Group, Resource, roleTags, RoleTags } from '@urbit/api';
import _ from 'lodash';
export function roleForShip(

View File

@ -1,17 +1,18 @@
import useMetadataState from '../state/metadata';
import ob from 'urbit-ob';
import useInviteState from '../state/invite';
import {resourceAsPath} from '../../../../npm/api/dist';
import { deSig, resourceAsPath } from '@urbit/api';
import { createJoinParams } from '~/views/landscape/components/Join/Join';
function getGroupResourceRedirect(key: string) {
const association = useMetadataState.getState().associations.graph[`/ship/${key}`];
const { metadata } = association;
if(!association || !('graph' in metadata.config)) {
const graphs = useMetadataState.getState().associations.graph;
const association = graphs[`/ship/${key}`];
if(!association || !('graph' in association.metadata.config)) {
return '';
}
const section = association.group === association.resource ? '/messages' : association.group;
return `/~landscape${section}/resource/${metadata.config.graph}${association.resource}`;
return `/~landscape${section}/resource/${association.metadata.config.graph}${association.resource}`;
}
function getPostRedirect(key: string, segs: string[]) {
@ -70,8 +71,18 @@ function getGraphRedirect(link: string) {
function getInviteRedirect(link: string) {
const [,,app,uid] = link.split('/');
const invite = useInviteState.getState().invites[app][uid];
if(!invite) { return ''; }
return { search: `?join-kind=${app}&join-path=${encodeURIComponent(resourceAsPath(invite.resource))}` };
if(!invite || (app !== 'groups' && app !== 'graph')) {
return '';
}
const { ship, name } = invite.resource;
const alreadyJoined = getGroupResourceRedirect(`~${deSig(ship)}/${name}`);
if (alreadyJoined) {
return alreadyJoined;
}
return { search: createJoinParams(app, resourceAsPath(invite.resource)) };
}
function getDmRedirect(link: string) {

View File

@ -1,12 +1,12 @@
import { isChannelAdmin } from '~/logic/lib/group';
import { cite } from '~/logic/lib/util';
import { createJoinParams } from '~/views/landscape/components/Join/Join';
const makeIndexes = () => new Map([
['ships', []],
['commands', []],
['subscriptions', []],
['groups', []],
['apps', []],
['other', []]
]);
@ -56,34 +56,11 @@ const commandIndex = function (currentGroup, groups, associations) {
if (canAdd) {
commands.push(result('Channel: Create', `/~landscape${workspace}/new`, 'Groups', null));
}
commands.push(result('Groups: Join', '?join-kind=group', 'Groups', null));
commands.push(result('Groups: Join', createJoinParams('groups'), 'Groups', null));
return commands;
};
const appIndex = function (apps) {
// all apps are indexed from launch data
// indexed into 'apps'
const applications = [];
Object.keys(apps)
.filter((e) => {
return !['weather','clock'].includes(e);
})
.sort((a, b) => {
return a.localeCompare(b);
})
.map((e) => {
const obj = result(
apps[e].type?.basic?.title || apps[e].type.custom?.tile || e,
apps[e]?.type.basic?.linkedUrl || apps[e]?.type.custom?.linkedUrl || '',
apps[e]?.type?.basic?.title || apps[e].type.custom?.tile || e,
null
);
applications.push(obj);
});
return applications;
};
const otherIndex = function(config) {
const other = [];
const idx = {
@ -102,7 +79,7 @@ const otherIndex = function(config) {
return other;
};
export default function index(contacts, associations, apps, currentGroup, groups, hide): Map<string, OmniboxItem[]> {
export default function index(contacts, associations, currentGroup, groups, hide): Map<string, OmniboxItem[]> {
const indexes = makeIndexes();
indexes.set('ships', shipIndex(contacts));
// all metadata from all apps is indexed
@ -164,7 +141,6 @@ export default function index(contacts, associations, apps, currentGroup, groups
indexes.set('commands', commandIndex(currentGroup, groups, associations));
indexes.set('subscriptions', subscriptions);
indexes.set('groups', landscape);
indexes.set('apps', appIndex(apps));
indexes.set('other', otherIndex(hide));
return indexes;

View File

@ -1,5 +1,4 @@
import { Content, GraphNode, Post, TextContent } from '@urbit/api';
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import { BigIntOrderedMap, Content, GraphNode, Post, TextContent } from '@urbit/api';
import bigInt, { BigInteger } from 'big-integer';
import { buntPost } from '~/logic/lib/post';
import { unixToDa } from '~/logic/lib/util';

View File

@ -1,9 +1,4 @@
import { GraphNode } from '@urbit/api';
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import BigIntArrayOrderedMap, {
arrToString,
stringToArr
} from '@urbit/api/lib/BigIntArrayOrderedMap';
import { arrToString, stringToArr, BigIntOrderedMap, BigIntArrayOrderedMap, GraphNode } from '@urbit/api';
import bigInt, { BigInteger } from 'big-integer';
import produce from 'immer';
import _ from 'lodash';

View File

@ -1,11 +1,9 @@
import { Enc } from '@urbit/api';
import {
Enc,
Group,
GroupPolicy, GroupUpdate,
InvitePolicy, InvitePolicyDiff, OpenPolicy, OpenPolicyDiff, Tags
} from '@urbit/api/groups';
} from '@urbit/api';
import _ from 'lodash';
import { Cage } from '~/types/cage';
import { resourceAsPath } from '../lib/util';

View File

@ -1,11 +1,11 @@
import {
BigIntOrderedMap,
HarkPlace,
Timebox,
HarkStats,
harkBinToId,
makePatDa
} from '@urbit/api';
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import _ from 'lodash';
import { compose } from 'lodash/fp';
import { BaseState } from '../state/base';
@ -210,6 +210,9 @@ function more(json: any, state: HarkState): HarkState {
function added(json: any, state: HarkState): HarkState {
if('added' in json) {
const { bin } = json.added;
if(bin.place.desk !== window.desk) {
return state;
}
const binId = harkBinToId(bin);
state.unseen[binId] = json.added;
}
@ -239,6 +242,9 @@ function timebox(json: any, state: HarkState): HarkState {
const time = makePatDa(lid.archive);
const old = state.archive.get(time) || {};
notifications.forEach((note: any) => {
if(note.bin.place.desk !== window.desk) {
return;
}
const binId = harkBinToId(note.bin);
old[binId] = note;
});
@ -246,6 +252,9 @@ function timebox(json: any, state: HarkState): HarkState {
} else {
const seen = 'seen' in lid ? 'seen' : 'unseen';
notifications.forEach((note: any) => {
if(note.bin.place.desk !== window.desk) {
return;
}
const binId = harkBinToId(note.bin);
state[seen][binId] = note;
});

View File

@ -1,4 +1,4 @@
import { InviteUpdate } from '@urbit/api/invite';
import { InviteUpdate } from '@urbit/api';
import _ from 'lodash';
import { BaseState } from '../state/base';
import { InviteState as State } from '../state/invite';

View File

@ -1,4 +1,4 @@
import { MetadataUpdate, Associations, ResourceAssociations } from '@urbit/api/metadata';
import { MetadataUpdate, Associations, ResourceAssociations } from '@urbit/api';
import _ from 'lodash';
import { Cage } from '~/types/cage';
import { BaseState } from '../state/base';

View File

@ -1,4 +1,4 @@
import { SettingsUpdate } from '@urbit/api/settings';
import { SettingsUpdate } from '@urbit/api';
import _ from 'lodash';
import { SettingsState as State } from '~/logic/state/settings';
import { BaseState } from '../state/base';

View File

@ -1,12 +1,12 @@
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import { patp2dec } from 'urbit-ob';
import shallow from 'zustand/shallow';
import { Association, deSig, GraphNode, Graphs, FlatGraphs, resourceFromPath, ThreadGraphs, getGraph, getShallowChildren, setScreen } from '@urbit/api';
import {
Association, BigIntOrderedMap, deSig, GraphNode, Graphs, FlatGraphs, resourceFromPath, ThreadGraphs, getGraph, getShallowChildren, setScreen,
addDmMessage, addPost, Content, getDeepOlderThan, getFirstborn, getNewest, getNode, getOlderSiblings, getYoungerSiblings, markPending, Post, addNode, GraphNodePoke
} from '@urbit/api';
import { useCallback } from 'react';
import { createState, createSubscription, reduceStateN, pokeOptimisticallyN } from './base';
import airlock from '~/logic/api';
import { addDmMessage, addPost, Content, getDeepOlderThan, getFirstborn, getNewest, getNode, getOlderSiblings, getYoungerSiblings, markPending, Post, addNode, GraphNodePoke } from '@urbit/api/graph';
import { GraphReducer, reduceDm } from '../reducers/graph-update';
import _ from 'lodash';
import { clone } from '../lib/util';

View File

@ -1,5 +1,6 @@
import {
archive,
BigIntOrderedMap,
HarkBin,
markCountAsRead,
NotificationGraphConfig,
@ -15,7 +16,6 @@ import {
import { Poke } from '@urbit/http-api';
import { patp2dec } from 'urbit-ob';
import _ from 'lodash';
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import api from '~/logic/api';
import { useCallback, useMemo } from 'react';

View File

@ -1,4 +1,4 @@
import { Association, Associations, MetadataUpdatePreview } from '@urbit/api/metadata';
import { Association, Associations, MetadataUpdatePreview } from '@urbit/api';
import _ from 'lodash';
import { useCallback, useEffect, useState } from 'react';
import {

View File

@ -16,8 +16,7 @@ import {
import { useCallback } from 'react';
import { reduceUpdate } from '../reducers/settings-update';
import airlock from '~/logic/api';
import { Contact, getDeskSettings, Value } from '@urbit/api';
import { putEntry } from '@urbit/api/settings';
import { Contact, getDeskSettings, putEntry, Value } from '@urbit/api';
export interface ShortcutMapping {
cycleForward: string;
@ -41,6 +40,7 @@ export interface SettingsState {
hideUnreads: boolean;
hideGroups: boolean;
hideUtilities: boolean;
disableSpellcheck: boolean;
};
keyboard: ShortcutMapping;
remoteContentPolicy: RemoteContentPolicy;
@ -73,7 +73,8 @@ const useSettingsState = createState<SettingsState>(
hideAvatars: false,
hideUnreads: false,
hideGroups: false,
hideUtilities: false
hideUtilities: false,
disableSpellcheck: false
},
remoteContentPolicy: {
imageShown: true,

View File

@ -3,7 +3,7 @@ import { Meta, Story } from '@storybook/react';
import { Box } from '@tlon/indigo-react';
import { InviteItem, InviteItemProps } from '~/views/components/Invite';
import { JoinProgress } from '@urbit/api/groups';
import { JoinProgress } from '@urbit/api';
export default {
title: 'Notifications/Invite',

View File

@ -4,8 +4,7 @@ import { withDesign } from 'storybook-addon-designs';
import { Col, Row } from '@tlon/indigo-react';
import { LinkBlockItem } from '~/views/apps/links/components/LinkBlockItem';
import { createPost, GraphNode } from '@urbit/api';
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import { BigIntOrderedMap, createPost, GraphNode } from '@urbit/api';
export default {
title: 'Collections/BlockItem',

View File

@ -4,8 +4,7 @@ import { withDesign } from 'storybook-addon-designs';
import { Box } from '@tlon/indigo-react';
import { LinkDetail } from '~/views/apps/links/components/LinkDetail';
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import { GraphNode } from '@urbit/api';
import { BigIntOrderedMap, GraphNode } from '@urbit/api';
import useMetadataState from '~/logic/state/metadata';
import { makeComment } from '~/logic/lib/fixtures';

View File

@ -1,5 +1,4 @@
import { ContactUpdate, GroupUpdate, InviteUpdate, MetadataUpdate } from '@urbit/api';
import { SettingsUpdate } from '@urbit/api/settings';
import { ContactUpdate, GroupUpdate, InviteUpdate, MetadataUpdate, SettingsUpdate } from '@urbit/api';
import { ConnectionStatus } from './connection';
import { LaunchUpdate, WeatherState } from './launch-update';
import { LocalUpdate } from './local-update';

View File

@ -27,7 +27,7 @@ import './css/indigo-static.css';
import { Content } from './landscape/components/Content';
import './landscape/css/custom.css';
import { bootstrapApi } from '~/logic/api/bootstrap';
import { uxToHex } from '@urbit/api/dist';
import { uxToHex } from '@urbit/api';
function ensureValidHex(color) {
if (!color)
@ -43,7 +43,11 @@ const Root = withState(styled.div`
font-family: ${p => p.theme.fonts.sans};
height: 100%;
width: 100%;
padding: 0;
padding-left: env(safe-area-inset-left, 0px);
padding-right: env(safe-area-inset-right, 0px);
padding-top: env(safe-area-inset-top, 0px);
padding-bottom: env(safe-area-inset-bottom, 0px);
margin: 0;
${p => p.display.backgroundType === 'url' ? `
background-image: url('${p.display.background}');

View File

@ -1,5 +1,4 @@
import { Content, createPost, fetchIsAllowed, Post, removePosts, deSig } from '@urbit/api';
import { Association } from '@urbit/api/metadata';
import { Association, Content, createPost, fetchIsAllowed, Post, removePosts, deSig } from '@urbit/api';
import { BigInteger } from 'big-integer';
import React, {
ReactElement, useCallback,
@ -90,7 +89,7 @@ const ChatResource = (props: ChatResourceProps): ReactElement => {
);
const isAdmin = useMemo(
() => (group ? group.tags.role.admin.has(`~${window.ship}`) : false),
() => group ? group.tags.role.admin.has(deSig(window.ship)) : false,
[group]
);

View File

@ -1,4 +1,4 @@
import { acceptDm, cite, Content, declineDm, deSig, Post, removeDmMessage } from '@urbit/api';
import { acceptDm, cite, Content, declineDm, deSig, Post } from '@urbit/api';
import React, { useCallback, useEffect } from 'react';
import _ from 'lodash';
import bigInt from 'big-integer';
@ -77,8 +77,10 @@ export function DmResource(props: DmResourceProps) {
);
useEffect(() => {
getNewest(`~${window.ship}`, 'dm-inbox', 100, `/${patp2dec(ship)}`);
}, [ship]);
if(dm.size === 0 && !pending) {
getNewest(`~${window.ship}`, 'dm-inbox', 100, `/${patp2dec(ship)}`);
}
}, [ship, dm]);
const fetchMessages = useCallback(
async (newer: boolean) => {
@ -125,10 +127,6 @@ export function DmResource(props: DmResourceProps) {
[ship, addDmMessage]
);
const onDelete = useCallback((msg: Post) => {
airlock.poke(removeDmMessage(`~${window.ship}`, msg.index));
}, []);
const onAccept = async () => {
await airlock.poke(acceptDm(ship));
};
@ -136,6 +134,7 @@ export function DmResource(props: DmResourceProps) {
history.push('/~landscape/messages');
await airlock.poke(declineDm(ship));
};
return (
<Col width="100%" height="100%" overflow="hidden">
<Row
@ -206,7 +205,6 @@ export function DmResource(props: DmResourceProps) {
onReply={quoteReply}
fetchMessages={fetchMessages}
dismissUnread={dismissUnread}
onDelete={onDelete}
getPermalink={() => undefined}
isAdmin={false}
onSubmit={onSubmit}

View File

@ -8,6 +8,7 @@ import React, { useRef, ClipboardEvent, useEffect, useImperativeHandle } from 'r
import { Controlled as CodeEditor } from 'react-codemirror2';
import styled from 'styled-components';
import { MOBILE_BROWSER_REGEX } from '~/logic/lib/util';
import useSettingsState from '~/logic/state/settings';
import '../css/custom.css';
import { useChatStore } from './ChatPane';
@ -131,6 +132,8 @@ const ChatEditor = React.forwardRef<CodeMirrorShim, ChatEditorProps>(({ inCodeMo
useImperativeHandle(ref, () => editorRef.current);
const editor = editorRef.current;
const disableSpellcheck = useSettingsState(s => s.calm.disableSpellcheck);
const {
message,
setMessage
@ -234,6 +237,7 @@ const ChatEditor = React.forwardRef<CodeMirrorShim, ChatEditorProps>(({ inCodeMo
fontFamily={inCodeMode ? 'Source Code Pro' : 'Inter'}
fontSize={1}
lineHeight="tall"
spellCheck={!disableSpellcheck}
value={message}
rows={1}
style={{ width: '100%', background: 'transparent', color: 'currentColor' }}

View File

@ -284,6 +284,9 @@ const MessageActionItem = (props) => {
const MessageActions = ({ onReply, onDelete, msg, isAdmin, permalink }) => {
const isOwn = () => msg.author === window.ship;
const { doCopy, copyDisplay } = useCopy(permalink, 'Copy Message Link');
const showCopyMessageLink = Boolean(permalink);
const showDelete = (isAdmin || isOwn()) && onDelete;
const showDropdown = showCopyMessageLink || showDelete;
return (
<Box
@ -304,49 +307,46 @@ const MessageActions = ({ onReply, onDelete, msg, isAdmin, permalink }) => {
>
<Icon icon='Chat' size={3} />
</Box>
<Dropdown
dropWidth='250px'
width='auto'
alignY='top'
alignX='right'
flexShrink={0}
offsetY={8}
offsetX={-24}
options={
<Col
py={2}
backgroundColor='white'
color='washedGray'
border={1}
borderRadius={2}
borderColor='lightGray'
boxShadow='0px 0px 0px 3px'
>
<MessageActionItem onClick={() => onReply(msg)}>
Reply
</MessageActionItem>
{permalink ? (
<MessageActionItem onClick={doCopy}>
{copyDisplay}
{showDropdown && (
<Dropdown
dropWidth='250px'
width='auto'
alignY='top'
alignX='right'
flexShrink={0}
offsetY={8}
offsetX={-24}
options={
<Col
py={2}
backgroundColor='white'
color='washedGray'
border={1}
borderRadius={2}
borderColor='lightGray'
boxShadow='0px 0px 0px 3px'
>
<MessageActionItem onClick={() => onReply(msg)}>
Reply
</MessageActionItem>
) : null }
{(isAdmin || isOwn()) ? (
<MessageActionItem onClick={e => onDelete(msg)} color='red'>
Delete Message
</MessageActionItem>
) : null}
{false && (
<MessageActionItem onClick={e => console.log(e)}>
View Signature
</MessageActionItem>
)}
</Col>
}
>
<Box padding={1} size={'24px'} cursor='pointer'>
<Icon icon='Menu' size={3} />
</Box>
</Dropdown>
{showCopyMessageLink && (
<MessageActionItem onClick={doCopy}>
{copyDisplay}
</MessageActionItem>
)}
{showDelete && (
<MessageActionItem onClick={e => onDelete(msg)} color='red'>
Delete Message
</MessageActionItem>
)}
</Col>
}
>
<Box padding={1} size={'24px'} cursor='pointer'>
<Icon icon='Menu' size={3} />
</Box>
</Dropdown>
)}
</Row>
</Box>
);
@ -418,7 +418,7 @@ function ChatMessage(props: ChatMessageProps) {
}
const onReply = props?.onReply || emptyCallback;
const onDelete = props?.onDelete || emptyCallback;
const onDelete = props?.onDelete; // If missing hide delete action
const transcluded = props?.transcluded || 0;
const renderSigil = props.renderSigil || (Boolean(nextMsg && msg.author !== nextMsg.author) ||
!nextMsg
@ -513,111 +513,3 @@ function ChatMessage(props: ChatMessageProps) {
export default React.memo(React.forwardRef((props: Omit<ChatMessageProps, 'innerRef'>, ref: any) => (
<ChatMessage {...props} innerRef={ref} />
)));
export const MessagePlaceholder = ({
height,
index,
className = '',
style = {},
...props
}) => (
<Box
width='100%'
fontSize={2}
pl={3}
pt={4}
pr={3}
display='flex'
lineHeight='tall'
className={className}
style={{ height, ...style }}
{...props}
>
<Box
pr={3}
verticalAlign='top'
backgroundColor='white'
style={{ float: 'left' }}
>
<Text
display='block'
background='washedGray'
width='24px'
height='24px'
borderRadius='50%'
style={{
visibility: index % 5 == 0 ? 'initial' : 'hidden'
}}
></Text>
</Box>
<Box
style={{ float: 'right', flexGrow: 1 }}
color='black'
className='clamp-message'
>
<Box
className='hide-child'
paddingTop={4}
style={{ visibility: index % 5 == 0 ? 'initial' : 'hidden' }}
>
<Text
display='inline-block'
verticalAlign='middle'
fontSize={0}
color='washedGray'
cursor='default'
>
<Text maxWidth='32rem' display='block'>
<Text
backgroundColor='washedGray'
borderRadius={2}
display='block'
width='100%'
height='100%'
></Text>
</Text>
</Text>
<Text
display='inline-block'
mono
verticalAlign='middle'
fontSize={0}
color='washedGray'
>
<Text
background='washedGray'
borderRadius={2}
display='block'
height='1em'
style={{ width: `${((index % 3) + 1) * 3}em` }}
></Text>
</Text>
<Text
mono
verticalAlign='middle'
fontSize={0}
ml={2}
color='washedGray'
borderRadius={2}
display={['none', 'inline-block']}
className='child'
>
<Text
backgroundColor='washedGray'
borderRadius={2}
display='block'
width='100%'
height='100%'
></Text>
</Text>
</Box>
<Text
display='block'
backgroundColor='washedGray'
borderRadius={2}
height='1em'
style={{ width: `${(index % 5) * 20}%` }}
></Text>
</Box>
</Box>
);

View File

@ -161,6 +161,13 @@ class ChatWindow extends Component<
}
}
onTopLoaded = () => {
const { graphSize, unreadCount } = this.props;
if(graphSize >= unreadCount) {
this.props.dismissUnread();
}
};
onBottomLoaded = () => {
if(this.state.unreadIndex.eq(bigInt.zero)) {
this.calculateUnreadIndex();
@ -274,6 +281,7 @@ class ChatWindow extends Component<
origin='bottom'
style={virtScrollerStyle}
onBottomLoaded={this.onBottomLoaded}
onTopLoaded={this.onTopLoaded}
// @ts-ignore paging @liam-fitzgerald on virtualscroller props
onScroll={this.onScroll}
data={graph}

View File

@ -12,7 +12,7 @@ import ModalButton from "./components/ModalButton";
import Tiles from "./components/tiles";
import Tile from "./components/tiles/tile";
import "./css/custom.css";
import { Join, JoinRoute } from "~/views/landscape/components/Join/Join";
import { createJoinParams, Join, JoinRoute } from "~/views/landscape/components/Join/Join";
const ScrollbarLessBox = styled(Box)`
scrollbar-width: none !important;
@ -40,7 +40,7 @@ export const LaunchApp = (props: LaunchAppProps): ReactElement | null => {
</title>
</Helmet>
<Route path="/join/:ship/:name">
<JoinRoute modal />
<JoinRoute />
</Route>
<ScrollbarLessBox
height="100%"
@ -94,7 +94,7 @@ export const LaunchApp = (props: LaunchAppProps): ReactElement | null => {
border={0}
p={0}
borderRadius={2}
onClick={() => history.push({ search: "?join-kind=group" })}
onClick={() => history.push({ search: createJoinParams('groups') })}
>
<Row backgroundColor="white" gapX="2" p={2} height="100%" width="100%" alignItems="center">
<Icon icon="BootNode" />

View File

@ -22,6 +22,7 @@ import useSettingsState, {
} from "~/logic/state/settings";
import Tile from "../components/tiles/tile";
import { useQuery } from "~/logic/lib/useQuery";
import { createJoinParams } from "~/views/landscape/components/Join/Join";
const sortGroupsAlph = (a: Association, b: Association) =>
alphabeticalOrder(a.metadata.title, b.metadata.title);
@ -123,8 +124,7 @@ function PendingGroup(props: PendingGroupProps) {
const title = preview?.metadata?.title || path;
const { toQuery } = useQuery();
const onClick = () => {
const { ship, name } = resourceFromPath(path);
history.push(toQuery({ "join-kind": "groups", "join-path": path }));
history.push(toQuery(createJoinParams('groups', path, null, false)));
};
const joining = useGroupState((s) => s.pendingJoin[path]?.progress);

View File

@ -1,6 +1,5 @@
import { Box, Center, Col, LoadingSpinner, Text } from '@tlon/indigo-react';
import { deSig, Group } from '@urbit/api';
import { Association } from '@urbit/api/metadata';
import { Association, deSig, Group } from '@urbit/api';
import bigInt from 'big-integer';
import React, { useEffect } from 'react';
import { Link, Route, Switch, useLocation } from 'react-router-dom';

View File

@ -1,12 +1,11 @@
import { Col, Row, Text } from '@tlon/indigo-react';
import { Association, Graph, GraphNode, markEachAsRead } from '@urbit/api';
import { Association, BigIntOrderedMap, Graph, GraphNode, markEachAsRead } from '@urbit/api';
import React, { useCallback, useState, useMemo, useEffect } from 'react';
import _ from 'lodash';
import { useResize } from '~/logic/lib/useResize';
import { LinkBlockItem } from './LinkBlockItem';
import { LinkBlockInput } from './LinkBlockInput';
import useLocalState from '~/logic/state/local';
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import bigInt from 'big-integer';
import airlock from '~/logic/api';
import useHarkState, { selHarkGraph } from '~/logic/state/hark';

View File

@ -1,7 +1,7 @@
import { Box, Center, Col, Text } from '@tlon/indigo-react';
import React from 'react';
import useHarkState, { HarkState } from '~/logic/state/hark';
import { harkBinToId, HarkLid, Timebox } from '../../../../../npm/api/dist';
import { harkBinToId, HarkLid, Timebox } from '@urbit/api';
import { Notification } from './notification';
const unseenLid = { unseen: null };

View File

@ -3,7 +3,7 @@ import { Box, Row, Text } from '@tlon/indigo-react';
import { StatelessAsyncAction } from '~/views/components/StatelessAsyncAction';
import Author from '~/views/components/Author';
import { useHistory } from 'react-router';
import { acceptDm, declineDm } from '@urbit/api/graph';
import { acceptDm, declineDm } from '@urbit/api';
import airlock from '~/logic/api';
export function PendingDm(props: { ship: string; }) {

View File

@ -16,6 +16,7 @@ import { TranscludedNode } from './TranscludedNode';
import styled from 'styled-components';
import Author from '~/views/components/Author';
import useDocketState, { useTreaty } from '~/logic/state/docket';
import { createJoinParams } from '~/views/landscape/components/Join/Join';
function Placeholder(type) {
const lines = (type) => {
@ -118,8 +119,7 @@ function GraphPermalink(
const permalink = (() => {
const link = `/perma${getPermalinkForGraph(group, graph, index).slice(16)}`;
return (!association && !loading)
? { search: `?join-kind=group&join-path=${encodeURIComponent(group)}&redir=${encodeURIComponent(link)}` }
: link
? { search: createJoinParams('groups', group, link) } : link;
})();
const [nodeGroupHost, nodeGroupName] = association?.group.split('/').slice(-2) ?? ['Unknown', 'Unknown'];

View File

@ -46,13 +46,6 @@ export function Note(props: NoteProps & RouteComponentProps) {
props.history.push(rootUrl);
};
if (typeof note.post === 'string' || !note.post) {
return (
<Box width="100%" pt="2" textAlign="center">
<Text gray>This note has been deleted.</Text>
</Box>
);
}
const comments = getComments(note);
const [, title, , post] = getLatestRevision(note);
@ -148,4 +141,16 @@ export function Note(props: NoteProps & RouteComponentProps) {
);
}
export default Note;
export default function(props: NoteProps & RouteComponentProps) {
const { note } = props;
if (typeof note.post === 'string' || !note.post) {
return (
<Box width="100%" pt="2" textAlign="center">
<Text gray>This note has been deleted.</Text>
</Box>
);
}
return (<Note {...props} />);
}

View File

@ -1,6 +1,5 @@
import { Box, Col, Icon, Image, Row, Text } from '@tlon/indigo-react';
import { Group } from '@urbit/api';
import { GraphNode } from '@urbit/api/graph';
import { Group, GraphNode } from '@urbit/api';
import React from 'react';
import ReactMarkdown from 'react-markdown';
import { Link } from 'react-router-dom';

Some files were not shown because too many files have changed in this diff Show More