start documenting jex:

This commit is contained in:
2023-05-09 16:16:43 -06:00
parent d6a8fa87dd
commit d36fcf826d
2 changed files with 76 additions and 25 deletions
View File
+76 -25
View File
@@ -13,21 +13,21 @@ extension and a wallet. Sidekick implements this from the perspective of a page
script (the "Æpp"). script (the "Æpp").
Jex is my homemade alternative to NPM. It is currently super confusing and Jex is my homemade alternative to NPM. It is currently super confusing and
unusable, but I maintain it is significantly better than NPM. borderline unusable, but it is significantly superior to NPM.
The motivation was [Aegora.jp](https://aegora.jp/), which is a basic e-commerce The motivation was [Aegora.jp](https://aegora.jp/), which is a basic e-commerce
site where items are priced in Aeternity cryptocurrency. site where items are priced in Aeternity.
We (Craig and Peter) started working on Aegora around January of 2022, and We (Craig and Peter) started working on Aegora around January of 2022, and
launched on December 8, 2022. launched on December 8, 2022.
Our first task was quite simple: discover if the user has a wallet installed. Our first task was to discover if the user has a wallet installed. If so, make
If so, make the page background green; if not, make it red. the page background green; if not, make it red.
This seemingly simple task was absurdly difficult with the Aeternity JavaScript This seemingly simple task was (is) absurdly difficult with the Aeternity
SDK, at least in its state as of early 2022. The SDK has been improved JavaScript SDK, at least in its state as of early 2022. The SDK has been
significantly since that time, but it is still nowhere near production quality. improved significantly since that time, but it is still nowhere near production
To this day, I would have no idea how to do that task. quality. To this day, I would have no idea how to accomplish that task.
Here is how to do it with Sidekick: Here is how to do it with Sidekick:
@@ -36,18 +36,36 @@ Here is how to do it with Sidekick:
let maybe_wallet = await sk.detect(sk.TIMEOUT_DEF_DETECT_MS, // timeout let maybe_wallet = await sk.detect(sk.TIMEOUT_DEF_DETECT_MS, // timeout
"failed to detect wallet", // error if timeout "failed to detect wallet", // error if timeout
logger); // logger logger); // logger
// returns a 'Safe' type
// if the call "worked", it will be
// {ok: true, result: <what the wallet sent back>}
// if not, it will be
// {ok: false, error: <either timeout, or some error originating from the wallet>}
// so, we can branch on maybe_wallet.ok to see if the wallet is there or not
if (maybe_wallet.ok)
document.body.style.background = 'green';
else
document.body.style.background = 'red';
``` ```
You have to pass in a logger to each call. You probably want `sk.cl()` which This is the basic pattern in sidekick:
is the console logger. Sidekick exports a few other loggers, as well as the - there is a sequence of steps to talk to the wallet (`detect`, `connect`,
`sk.Logger` interface if you want to write a custom one. For instance, maybe `address`, and then either `msg_sign` or `tx_sign_noprop`).
you want to log the page script/wallet conversation on your own server, so if - each step returns this `Safe` type
something goes wrong, you hear about it. You can write your own logger which - your code ends up being
`POST`s the logs back to your own server, and just pass it in as an argument. - do step N
- if step N worked, proceed to step N+1
- otherwise, display an error message
Anyway, back in Februaryish of 2022, I ended up going to work trying to figure Everything in sidekick works pretty much exactly the way you would expect.
out how the SDK was communicating with Superhero. It turns out there's an There's no crazy wizardry, or situations where you touch thing A and it changes
event bus available to both the document and extension context, and posting things B, C, and D behind your back. Sidekick doesn't try to outsmart you or
guess what you are trying to do.
So, backstory: back in Februaryish of 2022, I ended up going to work trying to
figure out how the SDK was communicating with Superhero. It turns out there's
an event bus available to both the document and extension context, and posting
messages in said event bus is how the two communicate. messages in said event bus is how the two communicate.
Sidekick started at this time as just a scratch project to figure out what the Sidekick started at this time as just a scratch project to figure out what the
@@ -61,18 +79,28 @@ perfectly, was easy to use, and was entirely self-contained (i.e. no external
dependencies, could be wrapped up in a tarball and dropped on the server). And dependencies, could be wrapped up in a tarball and dropped on the server). And
maybe we should just use that. So we did. maybe we should just use that. So we did.
By the way, the tooling to do "just wrap it up in a tarball and drop it on a The tooling to do "just wrap it up in a tarball and drop it on a server" is
server" is Jex. Jex.
## Annotated example: Aegora log-in code ## Annotated example: Aegora log-in code
Background: we don't use passwords to do login at Aegora (we don't store *any* I mentioned that the entire pattern of sidekick is:
private information about our users). Instead, we have your wallet
cryptographically sign a random message, and then verify the signature. - do step N
- branch on whether or not it worked
- if so proceed
- if not error
Let us see a real-world example
Here is the page script for the Aegora log in page, annotated. Here is the page script for the Aegora log in page, annotated.
You can follow along reading <https://aegora.jp/r/115/sign_mess-2.js>. You can follow along reading <https://aegora.jp/r/115/sign_mess-2.js>.
We don't use passwords to do login at Aegora (we don't store *any* private
information about our users). Instead, we have your wallet cryptographically
sign a random message, and then verify the signature.
The first thing we do is import sidekick The first thing we do is import sidekick
```js ```js
@@ -147,14 +175,14 @@ type Safe<ok_t, err_t>
``` ```
This allows you to use an `if` statement to ask the simple question "did it This allows you to use an `if` statement to ask the simple question "did it
work or not"? The pattern here is: work or not"? Again, the pattern here is:
1. Perform a step 1. Perform a step
2. Use an `if` statement to tell if it worked or not. (The user rejecting a request from the page counts as "not working"). 2. Use an `if` statement to tell if it worked or not. (The user rejecting a request from your script counts as "not working").
3. If it worked, proceed to the next step 3. If it worked, proceed to the next step
4. If it didn't, show an error message 4. If it didn't, show an error message
You might want to re-read the `detect` function, and then let's continue with `connect`: You might want to re-read the `detect` function above, and then let's continue with `connect`:
```js ```js
@@ -272,3 +300,26 @@ async function sign_mess(pk, logger)
} }
} }
``` ```
And, that's it.
## Jex
Using strange code from NPM is an unacceptable risk in a high-security context
(i.e. handling people's money). This risk is not hypothetical. There are
countless examples of NPM dependencies being used as an attack vector.
However, we do run into the same basic problems that something NPM-like solves:
1. We want to share code across multiple projects.
For instance, sidekick's test suite obviously depends on sidekick.
2. Automating builds
3. Making distribution tarballs.
Jex solves these problems, but in a much saner way than NPM.
Jex was originally a Python script, which has since evolved into an escript. It
will eventually become a full-blown Erlang application. The "inspiration" is
Craig's Erlang package manager, zx.