# Client side modules

## Introduction

A deterministic module is a client side module for hybrixd. It is used to handle client seeds, keys addresses and signing. As we do not want a client to share their keys all these actions should be performed client side. The node should never touch this data. To facilitate this the node supplies a 'client code blob' : compressed javascript code that can be executed on the client side.

## Types

Most client side modules will be asset modules. For example the client module `bitcoinjslib` to handle bitcoin key and address generation and transaction signing. Other custom client side modules can also be provided. For example to provide connectivity to (decentralized) exchanges.

## Source Files

The source files for deterministic modules with name `$MY_ASSET_NAME` are grouped in the module folder:

    $HYBRIXD/deterministic/modules/$MY_ASSET_NAME/

You will need to create the following file(s):

`deterministic.js`
  The entry file see below for the deterministic.js template
[Optional]: `precompile.sh`
  A script to standardize and automate changes to third party libraries.
[Optional]:`compile.sh`
  a script to compile the above into a single LZMA file

The artifact (compilation result) is build in the `$HYBRIXD/deterministic/dist/$MY_ASSET_NAME/` folder. It will consist of a LZMA compressed code blob file named `deterministic.js.lzma`

For examples see the existing modules: gitlab.

## Grocery List

To implement a deterministic module you will need the following

Node Side Module
  A qrtz module added to the `$HYBRIXD/node/recipes` folder. This should provide a connection to the asset API's (for example: the block explorers) Handling queries for balance, unspents and pushing transactions.
A javascript library for the asset.
  A library provided by the developers of the crypto currency. This can be a npm module or a (minified) web js library. Search online for "$MY_ASSET_NAME javascript library" this will very likely guide you to a github/gitlab repository or npm module which you can download.

## Library Dependencies

To install npm modules: please use supplied npm to ensure version compatibility:

`cd $HYBRIXD/deterministic/modules/$YOUR_ASSET` `npm i $MY_ASSETS_NPM_MODULE`

Each asset module will have its own `package.json` and `node_modules` folder. Only dev dependencies(webpack, eslint) are stored in `$HYBRIXD/deterministic/node_modules`

To use them include the npm module in your `deterministic.js`:

    const myAssetLib = require("$MY_ASSETS_NPM_MODULE")

To include a js library file place the file in the module folder:

`$HYBRIXD/deterministic/modules/$MY_ASSET_NAME/$MY_ASSET_LIBRARY/$SOME_FILE.js`

To then include the js library in your `deterministic.js`:

`const myAssetLib = require("$MY_ASSET_LIBRARY/$SOME_FILE")`

## deterministic.js Template

`deterministic.js` must provide the functions: `keys`, `importKeys`, `address` and `transaction`.

    const wrapperlib = require("$MY_ASSET_LIBRARY/$SOME_FILE")

    const wrapper = {
      keys : function(data) {
        return wrapperLib.someFunctionToCreateKeysFromSeed(data.seed);
      },

       // generate a unique wallet address from a given public key
      address : function(data) {
        return wrapperLib.someFunctionToGenerateAddressFromKeys(data.keys);
      },

      // create and sign a transaction for the given keys, amount, addresses and fees
      transaction : function(data,callback) {
        // contruct a transaction object
        var tx = {
          amount: data.amount
          fee:data.fee
          targetaddress: data.target
          sourceaddress: data.source
          fee: data.fee
        };
        return wrapperLib.someFunctionToSignTransaction(tx,data.keys);
        // If the function is asynchronious then use
        // wrapperLib.someAsyncFunctionToSignTransaction(tx,data.keys,callback);
      }
    }

    // export the wrapper
    window.deterministic = wrapper;

The `keys` function expects a data parameter containing the seed property and returns an keys object with a key.

    keys : function({seed: ..}){
      return  {privateKey:...}; // or {privateKey: ..., publicKey: ...} or { WIF: wif }
    }

The `address` function expects a data parameter containing the seed, the keys, and the mode. (The mode is used to distinguish between assets using the same deterministic module. For example bitcoinjslib.bitcoin and bitcoinjslib.omni) It returns a string containing the address

    address : function({seed: .. , keys: ..., mode: ...}){
     return "ABC123";
    }

The `transaction` function expects a data parameter of the following format:

    {
      keys:
      symbol:,
      source: ,
      target: ,
      account:,
      fee:,
      factor:,
      contract:,
      unspent:,
      target:,
      amount:,
      message: [optional]
    }

and an optional callback parameter in case the transaction generation is asynchronious. The function will return the stringified signed transaction.

## Result

A possible module folder could look like this:

    node_modules/
    deterministic.js
    package.json
    package-lock.json
    precompile.sh

## Compilation

All deterministic modules (which source files are modified more recent than the corresponding LZMA) are compiled by executing:

`$HYBRIXD/deterministic/npm run build`

### Pipeline

The following steps are performed to create the client code blob:

[Optional] Precompile
  automatic modification are made to third party libraries.
Compile
  The compile script is run
Degloballify
  All global/undeclared variables 'x' are declared as 'window.x'
Webpack
  create a package that can be used by browsers
Compress
  compress the result using lmza

### Precompile

The precompile step is only executed if there's a precompile.sh present in the module folder. This can and should be used to make modification to third party libraries (which is sometimes required). We do not want to make these modification in the libraries statically because then our changes will be lost if we update the libraries. By adding the code in precompile.sh the changes will be reapplied after code updates.

### Compile override

To override the compile script place a compile.sh script of your own making in the module folder.

## Testing

Use `$HYBRIXD/hybrix-lib/test/test --symbol $YOUR_ASSET_NAME` to test your implementation for nodejs or browse to:

`file://$HYBRIXD/hybrix-lib/test/test.html?symbol=$YOUR_ASSET_NAME`

to test your implementation for web.

If you encounter issues you can do a partial testing (without webpack) by running:

`$HYBRIXD/deterministic/test/test --symbol $YOUR_ASSET_NAME`