Files
Vanillae/sidekick/scratch/old-readme.md
T

491 lines
17 KiB
Markdown

# Sidekick
Sidekick is a simple JavaScript library for talking to an Aeternity
browser wallet extension such as Superhero from the document context
of a webpage.
| **Thing** | **URL** |
| --- | --- |
| Bug Tracker | https://gitlab.com/DoctorAjayKumar/sidekick/-/issues |
| Documentation | http://orangepill.healthcare/projects/sidekick/current/docs |
| Examples | https://gitlab.com/DoctorAjayKumar/sidekick/-/tree/master/examples |
| Git repository | https://gitlab.com/DoctorAjayKumar/sidekick |
| Homepage | http://orangepill.healthcare/projects/sidekick |
| License | ./LICENSE.txt |
| Maintainer | Dr. Ajay Kumar PHD <DoctorAjayKumar@protonmail.com> |
| Releases | http://orangepill.healthcare/projects/sidekick/releases |
> One of the most important things for designing a computer, which I
> think most designers don't do, is you study the problem you want to
> solve. And then use what you learn from studying the problem you
> want to solve to put in the mechanisms needed to solve it in the
> computer you're building. No more, no less.
— Gerald Jay Sussman
### What sidekick is NOT
Sidekick is **not** ideal if you operate in the Node/NPM ecosystem. If you are
working in the Node/NPM ecosystem, you probably want the [Aeternity JavaScript
SDK](https://github.com/aeternity/aepp-sdk-js/). Every single
Aeternity-related thing you could ever possibly want to do is possible to
accomplish with the SDK.
All that Sidekick knows how to do is talk to a browser wallet extension. In an
application, there is a great deal of necessary functionality (e.g. forming
transactions for the wallet to sign) which sidekick assumes your server-side
code has already handled.
In all software there is a tradeoff between simplicity and number of features.
Sidekick is very simple: 2300 lines of TypeScript, including comments, with no
dependencies. Therefore Sidekick intentionally only has a very limited set of
features.
# How to use this library
To obtain this library, download and unpack a release tarball
wget http://zxq9.com/projects/vanillae/sidekick/releases/sidekick_dist_X-Y-Z.tar.gz
tar xzvf sidekick_dist_X-Y-Z.tar.gz
You *should* be able to get all of the functionality you need just
from the exposed functions in the `sidekick` module. (If this is not
the case, please report this as a bug.)
You probably want to read the documentation of:
sidekick.js : top-level function calls
awcp/awcp.js : explains the return types of top-level sidekick
functions, explains what sidekick actually does
for you, and explains how all the various
modules fit together
skylight.js : main data structure in sidekick
helpers.js : what it sounds like
There are examples explained in this document. Their source can be
found in full in the GitLab repository, link above. The examples
exhibit how to interact with the standard release tarball using
TypeScript.
## General flow of Sidekick usage
1. Import the sidekick.js file:
```typescript
import * as sk from '/path/to/sidekick_dist_X-Y-Z/dist_js/sidekick.js'
```
2. Create a `Skylight`. This is the main data structure of Sidekick.
There are two ways to do this
1. `start_dwim() : Promise<Skylight>`
This is probably the one you want. It starts up the Skylight
and does the handshake with the wallet (will pop up the
little window for your user). The effect of this is to
populate all the variables like the user's public key.
Note that this is an async function. It doesn't return until
the handshake is complete.
```typescript
// Needs to be wrapped in an async function in order to use
// await keyword
async function main() : Promise<void> {
let my_skylight = await sk.start_dwim();
...
}
main();
```
2. `start : Skylight`
This is the vanilla option. All it does is create the
Skylight object.
Beware that this does start up a message queue that passively
listens for messages from the wallet.
3. Pass the skylight in to various functions along with additional
calldata generated by your server-side backend code.
## Example 1: Hello World
The effect of this example is to print "hello world" to the JS
console (Ctrl+Shift+C in most browsers). This example is included for
debugging/mental-quicksand-escape purposes.
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello world: Sidekick</title>
</head>
<body>
<h1>Sidekick Example: Hello World</h1>
<h4>Check the console</h4>
<script type="module">
import * as sk from '../sidekick_dist/dist_js/sidekick.js';
sk.hello();
</script>
</body>
</html>
```
The important lines are
```html
<script type="module">
import * as sk from '../sidekick_dist/dist_js/sidekick.js';
sk.hello();
</script>
```
This shows
- you need to use `type="module"` in order for imports to work
- how to do an import
- how to call functions from an imported module
## Example 2: get the user to sign a transaction
Anything you will want the user to do (e.g. sign smart contracts) is
contained in "get the user to sign a transaction". This example
illustrates the basic things you need to do in order to accomplish
that.
Sidekick does not provide functionality for forming the transaction
string you want the user to sign. Your backend should be doing that.
The example here uses a shim library called `parasite`, which you can find in
the GitLab repository in the `examples` directory. Parasite is just a rewrite
layer in front of the `testnet.aeternity.io` JSON interface. It is not suitable
for usage in production.
This is adapted from
[`examples/examples_src_ts/do_a_transfer.ts`][dat_ts]. The
difference is that `do_a_transfer.ts` is written against
[`examples/examples_html/do_a_transfer.html`][dat_html]. It contains
a lot of unnecessary detail, like doing things in response to buttons
being clicked, and filling in DOM textboxes with the results of things.
The full example has logic that resembles a register machine, rather
than a functional program. This example is closer to a functional
program.
[dat_html]: https://gitlab.com/DoctorAjayKumar/sidekick/-/blob/master/examples/examples_html/do_a_transfer.html
[dat_ts]: https://gitlab.com/DoctorAjayKumar/sidekick/-/blob/master/examples/examples_src_ts/do_a_transfer.ts
```typescript
import * as ae_node from './parasite/ae_node.js';
import * as sk from '../sidekick_dist/dist_js/sidekick.js';
async function
main()
: Promise<void>
{
//---------------------------------------------------------------
// STEP 1: MAKE A SKYLIGHT
//---------------------------------------------------------------
let skl : sk.Skylight =
await sk.start_dwim(sk.TIMEOUT_DEF_DETECT,
sk.TIMEOUT_DEF_CONNECT,
sk.TIMEOUT_DEF_ADDRESS);
//---------------------------------------------------------------
// STEP 2: GET THE USER'S ADDRESS
//---------------------------------------------------------------
let user_addr : string =
await sk.address(skl, sk.TIMEOUT_DEF_ADDRESS);
// faster/non-async:
//
// let user_addr = skl.waellet_address
//
// the non-commented code
//
// - will crash if the wallet isn't connected
// - will query the wallet for the address if the wallet *is*
// connected but the skl.waellet_address field *is not*
// populated
// - will crash if that times out after the second argument
// number of milliseconds
//
// if you know with 100% certainty that the address field will be
// populated (which we do here, because we used connect_dwim),
// then it's safe to just grab the field from the skylight
//
// The problem is that if the address field isn't populated, the
// commented code defaults to `undefined`, rather than crashing
// with an error message and callstack trace
//---------------------------------------------------------------
// STEP 3: FORM THE TRANSACTION
//
// This will be different for your application, because you're
// not using parasite (right?)
//
// You need to figure out how to make something like `tx_obj` on
// your own.
//
// `tx_obj` is just `{tx: "some_base58_garbage"}`.
//---------------------------------------------------------------
let target_addr : string =
'ak_dvNHMgVvdSgDchLsmcUpuFTbMBGfG3E5V9KZnNjLYPyEhcqnL';
// amount is in aettos
let amount : number = 1;
let endpoint : string = ae_node.URL_TESTNET;
let spendtx = {'recipient_id' : target_addr,
'amount' : amount,
'fee' : ae_node.MIN_FEE,
'sender_id' : user_addr,
'payload' : ""};
let tx_obj = await ae_node.PostSpend(endpoint, spendtx);
//---------------------------------------------------------------
// STEP 4: HAVE THE USER SIGN THE TRANSACTION
//
// There are two options:
//
// 1. `tx_sign_no_propagate` simply has the wallet sign the
// transaction, and return the signed transaction back to you
//
// 2. `tx_sign_yes_propagate` has the wallet sign the transaction
// and also propagates it into the network. It returns a more
// elaborate data structure, which is documented in somewhere
// the AWCP module documentation.
//---------------------------------------------------------------
let result =
await sk.tx_sign_no_propagate(skl,
tx_obj,
sk.NETWORK_ID_TESTNET,
sk.TIMEOUT_DEF_SIGN);
console.log(result);
}
main();
```
# Known pitfalls
- See notes in sidekick module about potential state crossups if your
document logic is multi-threaded.
- Has only been tested against Firefox-on-Linux
- Have not worked out good user idioms for handling errors
# How the release is structured and why
The idea of the release is that it contains exactly what is needed in
order to drop Sidekick into your project and start using it. No more,
no less.
A release has the following structure:
```
sidekick_dist_X-Y-Z/
dist_js/............tsc-generated human-readable JS tree
foo.js..............the actual code that is run
foo.d.ts............included so that your TypeScript code can
typecheck against sidekick
foo.js.map..........debug symbols that map foo.js to
locations in the TypeScript source
src_ts/.............included so that the browser's debugger works
foo.ts
README.txt
LICENSE.txt
```
We use semantic versioning: `X.Y.Z`
- A change in `X` means an API-breaking change
- A change in `Y` means an non-breaking API change
- A change in `Z` means no change to the API
There is no documentation included in the release. There is
autogenerated API documentation linked above, which is generated from
this file and the sources that are included in the release.
## What each file does
```
src_ts/.....................TypeScript source for sidekick library
awcp/.......................Aepp-Waellet Communication Protocol
awcp.ts.....................Protocol definition
msgq.ts.....................Block-on-raseev implementation
msgr.ts.....................Protocol implementation
helpers.ts..................what it sounds like
sidekick.ts.................top-level module
skylight.ts.................primary data structure
```
## Where is the NPM package or the webpack bundle?
There isn't one.
### Why?
Sidekick is a library that deals with cryptocurrency. The security
model is based on transparency and trust. A user must be able to
inspect code that is running on his hardware handling his money.
We don't support NPM because of the security issues that NPM
introduces. Briefly, the code can change at any time under the
developer's nose without the developer knowing. The [leftpad
debacle][lpad] and the [RIAEvangelist debacle][ria] are good examples
of the types of vulnerabilities that package managers like NPM
enable.
[lpad]: https://archive.ph/Qsh7j
[ria]: https://archive.ph/OF5I9
We don't use something like webpack because that introduces an opaque
rewrite using an untrusted tool. Webpack could plausibly alter the
runtime behavior of the program, and we would have no way to detect
that. Even if we trusted webpack, how do we obtain webpack? NPM.
So.
It is debatable whether or not we should trust the TypeScript
compiler (TSC). On the whole, TSC probably makes Sidekick more
secure, simply by virtue of increasing overall code quality and
eliminating the largest categories of potential bugs. Moreover, the
output that TSC produces is human-readable, and has a very
straightforward mapping to the original source code. A human can
easily read the TSC-generated JavaScript tree, even without the aid
of the source map, and have a high degree of faith that the code is
trustworthy and that TSC is behaving as promised.
# How to obtain the source tree
The source tree is included in your release. You can clone the
git repository with
```
git clone https://gitlab.com/DoctorAjayKumar/sidekick.git
```
# Repo file tree (non-exhaustive)
```
examples/...................Examples
contract-examples/..........Example Sophia smart contracts
examples_html/..............Low-budget example interfaces
do_a_transfer.html......Send money to an arbitrary address
hello.html..............Hello world
ide.html................Play around with smart contracts
examples_src_ts/............TypeScript source for each example
parasite/...................JavaScript shim that does what
your backend code ordinarily
would do
ae_compiler.ts..............Talk to a remote Sophia
compiler JSON HTTP interface
ae_node.ts..................Talk to a node (for forming
transactions, querying chain,
etc)
net.ts......................Network helper functions
do_a_transfer.ts........Send money to an arbitrary address
ide.ts..................Play around with smart contracts
tsconfig.json...............Examples-specific tsc configuration
src_ts/.....................TypeScript source for sidekick library
awcp/.......................Aepp-Waellet Communication Protocol
awcp.ts.....................Protocol definition
msgq.ts.....................Block-on-raseev implementation
msgr.ts.....................Protocol implementation
helpers.ts..................what it sounds like
sidekick.ts.................top-level module
skylight.ts.................primary data structure
LICENSE.txt.................MIT License
Makefile....................Makefile
make........................Equivalent to `make build`
make build..................Run tsc
make clean..................rm -r dist_js sidekick_dist docs \
examples/examples_dist_js
make dist...................Build a release tarball directory
make jsdoc..................Build the HTML documentation
make build_examples.........cd examples && tsc
make serve_examples.........cd examples && python3 -m \
http.server 8001
README.txt..................This file
STYLE_GUIDE.md..............Explains why the code looks so weird
TODO.md.....................what it sounds like
tsconfig.json...............Configuration file for tsc
```
# How to build a release
You will need the TypeScript compiler installed. See prereqs section.
make dist
## Prereqs for building source files
If you want to edit and rebuild the source files, you need TypeScript
installed, and you should update npm.
npm install -g typescript
npm install -g npm
## Protip: avoid using `sudo npm install -g`
If you want to avoid using sudo
```
mkdir ~/.npm-packages
npm config set prefix "${HOME}/.npm-packages"
```
Edit `~/.bashrc` or `~/.zshrc` with
```
NPM_PACKAGES="${HOME}/.npm-packages"
export PATH=$NPM_PACKAGES/bin:$PATH
```
Source: https://github.com/sindresorhus/guides/blob/main/npm-global-without-sudo.md
# How to build and view documentation
```
make build_docs
make serve_docs
```