Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DApp Launcher, Seed High Level API (HLAPI) & Seed Module #4

Merged
merged 21 commits into from
Aug 26, 2018

Conversation

CarsonRoscoe
Copy link
Contributor

Overview

The following development changes were based upon the design article DApp Launcher. This pull request includes functional, unstyled UI's for the launcher, the Seed module and the Relay module. It also includes dynamically loading modules, a High Level API (HLAPI) implementation for Seed DApps, and functional implementations of the Seed & Relay modules with their UI's.

To reiterate, this pull request was not focused around creating styled UI's, but instead about creating simple UI's which are functional and genuinely communicate with the Seed ecosystem.

Terminology Note: A "Module" is similar to a "Smart Contract" in Ethereum, while a "DApp" is an application which uses Modules.


DApp Launcher

The DApp launcher is created using NodeJS and Electron. It dynamically loads modules, pairs them with the virtual machine, can launch the dynamically loaded UI's for their modules, and offers a high level API for these DApps.

Due to the nature of Electron, all communication between the Launcher window, DApps and Seed (through the API) must be done though interprocess communication (IPC) between the individual pages and the Main process.


Dynamic Module Loading

Modules & their accompanying DApp are loaded dynamically by the Main process. The Launcher UI is then informed and updated to respect these loaded DApps. The Main process does not know anything about the underlying modules, only where to find the downloaded modules and how to load them.

DApp Requirements

There are four primary requirements a DApp must describe to the launcher in order for the launcher to effectively load the DApp.

DApps must:

  1. Be able to describe to the launcher how they wish to be displayed in the launcher

  2. Describe where to find their Modules source code

  3. Describe where to find their UI's source code

  4. State their Modules expected checksum for validation purposes

When being loaded dynamically, the Module Loader will read a module.json file which will explain these for the launcher.

For the purpose of example, the current module.json file for the Seed DApp contains the following JSON object.

{ "name" : "Seed", "dappSource" : "index.html", "moduleSource" : "seed.js", "moduleChecksum" : "fd37" }

Implementation

All modules are stored in the /modules folder in the base directory of the client. Each sub folder of the /modules folder represents a separate DApp that the launcher can launch. Inside each sub folder is a module.json file, which contains a JSON object that describes the above DApp requirements to the launcher.

When the launcher opens, it will read each subfolder's module.json file and dynamically create each tile & associated module. In order to add modules to the launcher, one must simply be downloaded and places in the /modules folder.

The above logic is express in code in the moduleLoader.js file, under the exported function "loadModules".

LoadedImage.png


High Level API (HLAPI)

DApps which choose to be hosted inside the launcher will have the luxury of accessing a High Level API for Seed. This High Level API is referred to as the SeedHLAPI. This API wraps all logic needed regarding how Seed works under the hood, and lets users create transactions, read from modules or subscribe for updates in a couple simple function calls.

This approach differs from the current Seed API, which is now being referred to as the Seed Low level API (SeedLLAPI). The Low Level API (LLAPI) exposes the underlying exports needed to communicate directly with Seed's subsystems, while the High Level API (HLAPI) wraps the logic, removing a developers need from understanding how to appropriately communicate with the Seed subsystems.

Electron Constraints

Electron brings its own set of constraints we must adhere to when building the HLAPI. The primary constraints we must respect is how Electron and the underlying Chromium system its built on communicate across processes.

Each process has its own set of memory, with each window being a separate process. The base process is known as "Main", which creates each individual window. Each window has its own process, which is known as a Renderer. Renderer's and Main communicate with one-other through Electron's IPC channels. These IPC channels cannot have JavaScript references sent through it, so all data or objects that are sent over IPC must be serializable.

Since we cannot send references, the processes cannot communicate with the same Seed API instances directly. Instead, Main must be the process that holds the Seed LLAPI instance used by the Seed HLAPI, and the Renderers must request Main do the processing. These requests must be made through IPC.

DApp Requirements

DApps must be able to make HLAPI requests, wait for a response from a separate process, and continue their work once the execution of the HLAPI has completed. Therefore, the DApps require that the HLAPI is asynchronous, despite the LLAPI being synchronous.

With regards to what DApps must be able to do, DApps must be able to:

API Description
Switch Accounts DApps may request an accounts witch, as users may have more than one account they wish to use.
Get Account DApps may want to know which account is currently logged in.
Create Transaction DApps must be able to create transactions when a user chooses to execute a function in their module.
Get Transactions DApps may want to fetch a transaction from storage by the transactions hash in order to read it.
Call "Getters" DApps may want to call any modules getters, even other modules.
Read DApps may want to read raw data from the ledger regarding a module.
Subscribe DApps must be able to subscribe to function callbacks and data changes in order to live update appropriately.
Unsubscribe DApps must be able to unsubscribe to avoid memory leaks and unwanted callback invocations.
Create Modules DApps must be able to create modules, as well as add them to the Seed system.
Get Modules DApps may want to fetch a module to read their data directly.

Implementation

The implementation of the HLAPI is split into two fronts. The first is how the Main Process implements the API in order to communicate with the Seed LLAPI. The second portion is how the DApp's Renderers make the asynchronous API requests to the Main Process.

This implementation added the requirement of asynchronous IPC communication. In order to meet this requirement, the npm module "PromiseIPC" was added to the Electron clients dependencies.

Main Process

For the implementation of the Main process portion, the code can be found at the bottom of main.js.

The Main process instantiates a PromiseIPC instance to listen for requests by the Renderers. Each API call a Renderer can make has its own listener inside main.js. These calls arrive asynchronously, where the file then works on the request, wrapping any logic needed to perform these actions. These listeners communicate with the Seed LLAPI directly through the index.js file in the seedSrc external folder.

Most API implementations are simple, simply accessing the LLAPI's appropriate export and speaking directly with whichever subsystem is needed. Some calls require a little more work, such as switching accounts.

Renderer Process

For the implementation of the Renderer processes portion, the code can be found in the seedHLAPI.js folder, which DApps can require.

In seedHLAPI.js exists a class known as SeedHLAPI. This class takes a instantiated Renderer's PromiseIPC object upon creation to communicate with Main on the Renderer's behalf. This class is very simple, as the logic heavy side is done by the Main process. The SeedHLAPI class simply wraps the communication logic, making it easier for DApps to communicate without needing to know what channels the Main process is listening for.


Seed Module

The Seed DApp is the first module & DApp available in the launcher. This DApp hosts the Seed cryptocurrency and acts as a wallet for users.

Wireframe Design

The theme will be a simple white background with a light green tint. Upon opening, a users public address will be visible in plain text, as well as a QR code display of that address. The users' balance will also be available, live updating while sending or receiving funds.

The various actions a user can do, such as transfer currency, are listed as buttons below the information heavy header.

At the bottom of the DApp will be the recent transaction history.

SeedWireframe.png

Current State

This pull request did not focus on styling or design yet, instead it focused on making every Seed module function implemented in a functional manner.

In the Seed DApp, the users public key and account balance are displayed on the screen. These values update dynamically, so if a user is given Seed or if accounts change, these values will automatically update to match.

CurrentState.png

There is a drop-down menu which correlates to the different functions in the Seed module. Seed was designed after the Ethereum ERC20 standard for tokens, and therefore there are four primary functions that users can invoke. "Transfer", "TransferFrom", "Approve" and "Burn". On top of that, there is also a "Constructor" option, which can be invoked upon the creation of the module to give it the initial starting values.

When a user changes between these five options in the drop-down menu, the input form live updates to match. These inputs are the same inputs that the functions expect as parameters into Seed. Users can invoke the function after filling in inputs, which creates a transaction and adds it to the entanglement.

Video of forms changing based on selected function


Relay Module

The Relay module is created for development only. This module and DApp allows the simply creation of empty transactions which simply validates some transactions in the entanglement. The Relay DApp will randomize one of one hundred possible users, simulating multiple users pushing the system forward.

The UI is simply a single button which says "Relay".


Honourable Mentions

Unit Test Migration

Previously, the unit tests setup the entanglement and constructed the launch of Seed. Now, that must be done through the UI.

In order to run the unit tests, you must:

  1. Switch to using "Account Cryptography - Public Key Encryption, hashing, base58 encoding & unit tests #1" through the menu system

  2. Open the Seed DApp in the launcher

  3. "Construct" the Seed module, keeping the initial amount in circulation at "1000" SEED

  4. Click the "Unit Tests" button on the main UI.

In the terminal, the unit tests will be run in the main process, showing up in your NodeJS terminal (NOT in the Launcher or Seed windows debug logs)

Video of Seed module unit test being run

…cription hookup for UI to load when balance changes
@CarsonRoscoe CarsonRoscoe merged commit 7e15a0b into Cajarty:master Aug 26, 2018
@CarsonRoscoe CarsonRoscoe mentioned this pull request Sep 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant