-
Notifications
You must be signed in to change notification settings - Fork 26
3. DAppNode SDK Tutorial: Complex package with setup wizard
In this guide, we will walk you through creating the Vipnode DAppNode Package using the dappnodesdk
.
The Vipnode package is great as a learning example because it's simple but includes some extra features like the dependency on DAppNode's core packages.
- 0. The setup
- 1. Understand your package
- 2. Develop your package
- 3. Polish your package
- 4. Build and test
- 5. Publish
If you haven't already, install the dappnodesdk
package
npm install -g @dappnode/dappnodesdk
Set up and bootstrap our project. We recommend the naming convention of DAppNodePackage-${package_name}
.
mkdir DAppNodePackage-vipnode
cd DAppNodePackage-vipnode
The init
command will create a convenient basic starting point. To auto answer the init questions use the flag -y
, you can edit the resulting information latter.
dappnodesdk init -y
The resulting file structure should be similar to
DAppNodePackage-vipnode/
├── build/
│ └── Dockerfile
├── avatar-default.png
├── dappnode_package.json
└── docker-compose.yml
Before we start, we need to understand what our DApp does, what does it need, and what other P2P DApps it depends on.
The Vipnode DApp is an incentivization layer that allows full node operators to join a pool where light nodes can go to connect to full node slots, in exchange for micropayments.
So in this case, the requirements are the following:
It needs to connect to an Ethereum full node via the JSON RPC to edit the whitelist of light nodes. Aren't we lucky that DAppNode already has a full node?
The Vipnode binary accepts a --rpc
flag. We will use this to connect the DAppNode's full node available at the generalized URL my.ethchain.dnp.dappnode.eth
.
Once connected to the full node, it needs to access the node key in order to identify it.
Accessing the nodekey can be done by giving the Vipnode docker container access to the DAppNode's fullnode DAppNode Package (ETHCHAIN) volume via an external docker volume. The ethchain's volume name is dncore_ethchaindnpdappnodeeth_identity
so we must map it to our package and tell the vipnode binary where to find the nodekey.
A third requirement is that it needs a payout address to send the rewards to - that is the micropayments that light clients will send for using the light client slots of the full node.
The payout address must be editable by the user, and the user needs to be able to change it whenever he/she wants. To accomplish that, it must be declared as an ENV which is shown in the ADMIN UI where the user can customize it at any point. Then, we will feed this ENV to the vipnode binary. We will name PAYOUT_ADDRESS
for simplicity.
Note that this is an excellent field to ask the user during the setup process of the package installation, using our setup wizard. You will find more information on how to prepare this in the add a setup wizard section of this guide.
Now it's time to translate the above requirements into actual code. All DAppNode packages wrap a docker image, which is what we have to develop first.
This tutorial assumes you are comfortable with Docker and docker-compose. If not, please watch a basic tutorial or refer to the official documentation.
Taking the official Vipnode docker image as the base, we will expand it with custom options:
- A) Tell the Vipnode binary to connect to the DAppNode's fullnode at
http://my.ethchain.dnp.dappnode.eth:8545
with the option--rpc
. - B) Tell the Vipnode binary where to find the node's key in the path of the volume that we will create later in the docker-compose
/app/identity/nodekey
with the option--nodekey
. - C) Set the payout address with an environment variable that will be injected at runtime by the setting the user provides in each installation. Set the flag
--payout
to the ENV variable${PAYOUT_ADDRESS}
whose name must match the environment variable declared in the docker-compose.
FROM shazow/vipnode
ENTRYPOINT vipnode agent -vv \
--rpc=http://my.ethchain.dnp.dappnode.eth:8545 \
--payout=${PAYOUT_ADDRESS} \
--nodekey=/app/identity/nodekey
Extend the boilerplate docker-compose with these configuration options:
- B) Map the external volume of the DNP_ETHCHAIN
dncore_ethchaindnpdappnodeeth_identity
to the/app/identity
path, which matches the path provided to the vipnode binary. Since we just need to read the key we make the volume read-only with:ro
. Refer to the docker-compose documentation for the syntax used to declare the external volume. - C) Declare the environment variable
PAYOUT_ADDRESS
empty, which will be provided by the user during the installation through the setup wizard or later in the configuration tab of the package, where the Environment Variables can be changed.
version: "3.4"
services:
vipnode.dnp.dappnode.eth:
image: "vipnode.dnp.dappnode.eth:0.1.0"
build: ./build
environment:
- "PAYOUT_ADDRESS="
volumes:
- "dncore_ethchaindnpdappnodeeth_identity:/app/identity:ro"
volumes:
dncore_ethchaindnpdappnodeeth_identity:
external: true
To make sure the docker image builds without errors let's try to build before continuing
$ docker-compose build
If the build completed successfully continue to next step. Otherwise make sure there typos in the files, troubleshoot possible docker errors or reach out to us.
The package now should work, but that doesn't mean the users know how to use it! It's time to introduce features to improve the UX for your DAppNode Package users.
Next, we will add the following items:
- Manifest (mandatory): Help users understand what the package is about. It's used to identify the package and its descriptions are shown before installing
- Avatar (mandatory): An image that will define your package
- Setup wizard (optional, highly recommended if the package needs configuration): Help users configure the package. It's shown at installation time
- Getting started (optional): Help users start using the package. It's shown after a successful installation
This file declares your DAppNode package. All mandatory metadata was filled when running dappnodesdk init
. However, you are highly encouraged to fill the following fields that will show up before installing the package:
-
upstreamVersion
: What's the version of the underlying software being wrapped -
shortDescription
: 6-8 word hook description -
description
: Detailed description, allows markdown -
author
: Package author, please format as${name} <${email}> (${github URL})
{
"name": "vipnode.dnp.dappnode.eth",
"version": "0.1.0",
"upstreamVersion": "2.2.1",
"shortDescription": "Economic incentive for running Ethereum full nodes",
"description": "[Vipnode](https://vipnode.org)'s goal is to allow the Ethereum network to remain decentralized by creating a financial marketplace for more people to run full nodes and serve native light clients. Check this [medium article](https://medium.com/vipnode/an-economic-incentive-for-running-ethereum-full-nodes-ecc0c9ebe22) to understand the motivation behind this project and this [2.0 release article](https://medium.com/vipnode/vipnode-2-0-released-9af1d65b4552) for a tutorial on how to use Vipnode.",
"type": "service",
"author": "DAppNode Association <[email protected]> (https://github.com/dappnode)",
"categories": ["Economic incentive"],
"links": {
"homepage": "https://github.com/dappnode/DAppNodePackage-vipnode"
},
"repository": {
"type": "git",
"url": "https://github.com/dappnode/DAppNodePackage-vipnode.git"
},
"bugs": {
"url": "https://github.com/dappnode/DAppNodePackage-vipnode/issues"
},
"license": "GPL-3.0"
}
Add an avatar to be shown in the Admin UI. To do so, just add this avatar (link TODO) avatar-vipnode.png
to the root of the project. The dappnodesdk
will automatically find it and add it to the release. Refer to the docs (link TODO) for the avatar requirements.
This step is optional, but we highly recommend preparing the setup wizard as it can highly improve the usability of your package!
The wizard helps users configure the package. You can declare the different configuration variables that the user must or should set. You can also add a description and validation logic to them. This component is built on top of https://github.com/rjsf-team/react-jsonschema-form and requires three distinct files:
-
setup.schema.json
: Declares parameters to be shown, metadata and validation options. -
setup-ui.json
(optional): Adds custom options affecting the display of the form fields. -
setup-target.json
: Tells the DAppNode installer what configuration parameter is each field referring too.
Declare which parameters should be shown in the setup wizard form, their name, description and validation options. For all description
fields you can use markdown which will be rendered by https://github.com/rexxars/react-markdown.
{
"description": "This setup wizard will help you start. In case of problems: https://github.com/dappnode/DAppNodePackage-vipnode#installing-and-setting-up-vipnode",
"type": "object",
"required": ["payoutAddress"],
"properties": {
"payoutAddress": {
"type": "string",
"title": "Payout address",
"description": "Define an Ethereum mainnet address to get rewards to",
"pattern": "^0x[a-fA-F0-9]{40}$"
}
}
}
Add custom options affecting the display of setup.schema.json
's fields. See https://react-jsonschema-form.readthedocs.io for more details.
{
"payoutAddress": {
"ui:help": "Don't use your main address",
"errorMessages": {
"pattern": "Must be a valid address (0x1fd16a...)"
}
}
}
Tell the DAppNode installer what configuration parameter is each field referring too.
{
"payoutAddress": {
"type": "environment",
"name": "PAYOUT_ADDRESS"
}
}
This step is optional
Once the user has installed the package, they might need some help to start using it. This file will be shown right after a successful installation, when the user enters the installed package, and is dismissable.
You can use internal DAppNode links if applicable, or guide the users to video tutorials you might have, external websites, etc. The contents of this file will be rendered as markdown by https://github.com/rexxars/react-markdown.
You should see your enode
\```
[host] 2019/04/09 08:45:33 Connected to local node: enode://974f7b125a2a3756ddb917f9ae...
\```
on the pool status website [Status](https://vipnode.org/status)
Now your package is ready for being tested locally in your DAppNode!
First, let's make sure the file directory is right. Your Vipnode DAppNode package directory should look like this:
DAppNodePackage-vipnode.dnp.dappnode.eth/
├── build/
│ └── Dockerfile
├── avatar-vipnode.png
├── dappnode_package.json
├── docker-compose.yml
├── getting-started.md
├── setup-target.json
├── setup-ui.json
└── setup.schema.json
The dappnodesdk
build command will prepare the necessary files, build the docker image and upload the package directory to IPFS. The resulting IPFS hash will allow you to install and run the package without needing to create the APM Repo (more on that latter). This will allow you to test the package in any DAppNode before publishing the package. Make sure that you are connected to your DAppNode's VPN or Wi-Fi hotspot and run:
$ dappnodesdk build
The process can take several minutes depending on your internet connection and should end with an output similar to this
DNP (DAppNode Package) built and uploaded
Manifest hash : /ipfs/QmfDSDeK9fiWpB7tEAiFKzuXvcvJr7yPiYr2jZmto6ZPRa
Install link : http://my.dappnode/#/installer/%2Fipfs%2FQmfDSDeK9fiWpB7tEAiFKzuXvcvJr7yPiYr2jZmto6ZPRa
You can open the install link in your browser and install the package in your DAppNode.
Once you have successfully tested the package using its IPFS hash, it's time to publish it.
But what does it mean to publish a DAppNode package? In DAppNode we use the Aragon Package Manager (APM) smart contract. To publish a DAppNode package means sending a transaction to the registry contract and link a Semver version to the IPFS hash of the manifest of the package.
Now, let's publish our DAppNode package! The publish command does the build of the image and shows a transaction data to be able to publish the package. The first time it will create the repository. Otherwise, it will update it.
To be able to update a repository you must be the authorized dev. The authorized dev Ethereum account is assigned when first deploying the APM repo of a package. When you deploy the APM repo of your package, the dappnodesdk
will ask you to provide the authorized dev address.
The script increases the current version of the repository based on the specified type (patch, minor, major), unless a version hasn't yet been published
$ dappnodesdk publish < patch | minor | major >
for more information about versioning check semver
Please take into account that the package version is not the internal version of the package you want to upload. We use the Aragon package manager, and it only lets starting with version 1 and increments one by one. Valid initial versions are 0.0.1
, 0.1.0
or 1.0.0
.