Options
All
  • Public
  • Public/Protected
  • All
Menu

Sidekick

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

How to use this library

To obtain this library, download and unpack a release tarball

wget http://orangepill.healthcare/projects/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:

    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.

      // 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.

<!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

<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. 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. The difference is that do_a_transfer.ts is written against examples/examples_html/do_a_transfer.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.

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

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 and the RIAEvangelist debacle are good examples of the types of vulnerabilities that package managers like NPM enable.

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.

npm install -g typescript

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

Generated using TypeDoc