-
Notifications
You must be signed in to change notification settings - Fork 26
1. Start here: DAppNode SDK
This tutorial will show you how to turn the Status-go server into a DAppNode package (DNP)
If you don’t have it installed yet, you need to install Node.js in your laptop.
Last stable version of Node.js (or 8.12.0) works just fine.
You will also need docker and docker-compose.
Repo: DAppNode SDK
Tip: If you are using npm 5.2 or higher, we recommend using npx to run packages globally.
npx @dappnode/dappnodesdk
or
sudo npm install -g @dappnode/dappnodesdk
or
npm install --save-dev @dappnode/dappnodesdk
- Introduction to SDK
DAppNodeSDK is a tool to make as simple as possible the creation of new dappnode packages. It helps to initialize and publish an Aragon Package Manager Repo in the ethereum mainnet.
We have deployed a public APM (Aragon Package Manager) registry in which anyone can create their own APM repository: public.dappnode.eth
- Manifest
- Command line
$ dappnodesdk --help
Usage: dappnodesdk <command> [options]
Commands:
add_avatar Upload .png avatar and add it to the manifest
build Build a new version (only generates the ipfs hash)
gen_compose Generate the docker-compose.yml from the manifest
gen_manifest Generate the manifest from the docker-compose.yml
increase [type] Increases the version defined in the manifest
init Initialize a new DAppNodePackage (DNP) repository
next [type] Compute the next release version from local
publish [type] Publish a new version of the package in an Aragon Package
Manager Repository
Options:
--directory, --dir Change the base directory [string] [default: "./"]
--silent Silence output to terminal [boolean]
--verbose, --debug Show more output to terminal [boolean]
-h, --help Show help [boolean]
-v, --version Show version number [boolean]
- Workflow
Creating a DNP involves dockerizing your decentralized application and using the existing provided services instead of other centralized providers.
Note this step is completely specific to your DApp.
A DNP project folder must contain these files:
.
├── build/
| ├── Dockerfile
| └── src
├── docker-compose.yml
├── dappnode_package.json
├── your-dnp-avatar.png
- A JSON manifest
dappnode_package.json
where the DNP's information and metadata are specified.
{
"name": "your-dnp.public.dappnode.eth",
"version": "0.0.1",
"description": "Your amazing DNP",
"avatar": "/ipfs/QmQbwD61LSo9BGN6qfxPzEJQtuB1J9bvHXPcByWjMU3YyF",
"image": {
"path": "your-dnp.public.dappnode.eth_0.0.1.tar.xz",
"hash": "/ipfs/QmNi5ys4NgnyGPrbmTBt65tpEdNJcyu7KhA8ofXhkTu2Rk",
"size": 15174122,
... # docker-compose rules
},
... # metadata
}
- A bare-bones docker-compose.yml to build the docker image.
version: '3.4'
services:
your-dnp.public.dappnode.eth:
image: 'your-dnp.public.dappnode.eth:0.0.1'
build: ./build
- A build folder with the DNP's source code.
- An avatar to be shown in the UI.
- Simple DNP depending on Core DNPs DAppNodePackage-vipnode
- Blockchain Node DAppNodePackage-goerli-geth
- GoLang application DAppNodePackage-swarm
- NodeJS application DNP_ETHFORWARD
- Self-deployed P2P application DAppNodePackage-matrix
This example is chosen merely because it's simplicity and dependency on DAppNode's core DNPs. You can review the other DNP examples which contain other types of applications.
The first step is to understand what your DApp needs and depends on. Let's do this for the Vipnode DApp, an incentivization layer to connect fullnodes and lightnodes in exchange for micropayments based on successful connections duration.
- It needs to connect to an Ethereum node via the JSON RPC to edit the whitelist of light nodes.
- It needs to access the nodekey of the node to identify it.
- It needs a payout address to send the profits to.
Note that Vipnode is a process that must be running permanently and with uninterrupted connection to the node. This is why Vipnode must be a DNP and cannot be a DWeb.
Now it's time to translate the above two requirements:
- The Vipnode binary accepts a
--rpc
flag. We will use this to connect the DAppNode's full node available at the generalized urlmy.ethchain.dnp.dappnode.eth
.
# Dockerfile's ENTRYPOINT
vipnode (...) --rpc=http://my.ethchain.dnp.dappnode.eth:8545
- Accessing the nodekey can be done by giving the Vipnode docker container access to the ethchain's volume via an external docker volume. The ethchain's volume name is
dncore_ethchaindnpdappnodeeth_data
so we must declare the external docker volume mapping in the manifest, and tell the binary where to find the nodekey
# dappnode_package.json
{
...
"image": {
...
"external_vol": [ "dncore_ethchaindnpdappnodeeth_data:/app/.ethchain:ro" ]
},
}
# Dockerfile's ENTRYPOINT
vipnode (...) --nodekey=/app/.ethchain/network/key
- The payout address must be editable on the fly by the user. To allow so, it must be declared as an ENV and then it will be shown in the ADMIN UI where the user can customize it at any point. To declare an ENV, add it in the manifest's field
image.environment
in array form and it will have an empty value as default. Then, consume the declared env in the Dockerfile's ENTRYPOINT.
# dappnode_package.json
{
...
"image": {
...
"environment": [ "PAYOUT_ADDRESS=" ]
},
}
# Dockerfile's ENTRYPOINT
vipnode (...) --payout=${PAYOUT_ADDRESS}
Admin UI view
![]()
With these lines, the DAppNode integration is completed. The rest of the code is inherited from the default Vipnode build and other necessary metadata.
- Dockerfile: The rest of the file sets up a build environment, downloads the Vipnode source code, builds it and then copies the resulting binary to a new stage to reduce the image size.
### Build stage
FROM golang:alpine3.9 AS build-env
ENV VERSION v2.0
# Install build deps
RUN apk update && apk --no-cache add git gcc build-base
# Get the source code
RUN git clone -b ${VERSION} https://github.com/vipnode/vipnode.git
WORKDIR /go/vipnode
RUN go get -d -v
RUN go mod download
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o vipnode
### Final stage
FROM alpine:3.9
RUN apk update && apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=build-env /go/vipnode/vipnode /usr/bin/
ENTRYPOINT vipnode host --rpc=http://my.ethchain.dnp.dappnode.eth:8545 -vv --payout=${PAYOUT_ADDRESS} --nodekey=/app/.ethchain/network/key
- Manifest (dappnode_package.json): The rest of the file adds useful metadata for the user such as describing the DNP and useful links.
{
"name": "vipnode.dnp.dappnode.eth",
"version": "0.0.1",
"description": "https://vipnode.org - Economic incentive for running Ethereum full nodes. The 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.",
"avatar": "/ipfs/Qmen3srZXEHncMM2RPsgVKkPbkJPTMN9SNFVEAQQY4a7Nf",
"type": "service",
"image": {
"path": "vipnode.dnp.dappnode.eth_0.0.1.tar.xz",
"hash": "/ipfs/QmfGTuPBxs641TBxf1tGkv6B5MxXDdMQan67iwpVykFAHe",
"size": 7844641,
"restart": "always",
"environment": [
"PAYOUT_ADDRESS="
],
"external_vol": [
"dncore_ethchaindnpdappnodeeth_data:/app/.ethchain:ro"
]
},
"author": "DAppNode Association <[email protected]> (https://github.com/dappnode)",
"license": "GPL-3.0",
"homepage": {
"homepage": "https://github.com/dappnode/DAppNodePackage-vipnode"
},
"repository": {
"type": "git",
"url": "git+https://github.com/dappnode/DAppNodePackage-vipnode.git"
},
"bugs": {
"url": "https://github.com/dappnode/DAppNodePackage-vipnode/issues"
},
"dependencies": {}
}
Once you have tackled all the issues try building the package. This command only generates the IPFS Hash to be able to install it without needing to create the APM Repo. It will allow you to test the package in any DAppNode before publishing the package.
$ dappnodesdk build
Once you have successfully tested the package using its IPFS hash, it's time to publish it.
In DAppNode we favour the use of Aragon Package Manager (APM) smart contract. To publish a DNP means sending transaction to the a registry contract and link a semver version to the IPFS hash of the manifest of the 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 of it.
To be able to update a repository you must be the authorized dev.
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 | mayor >
for more information about versioning check semver
Please take in account that the package version is not the internal version of the package you want to upload. We use Aragon package manager, and it only lets starting with version 1 and increment one by one. Valid initial versions are 1.0.0, 0.1.0 or 0.0.1
You must sign-in in your Docker on Mac account, see issue reference ( docker-compose can't handle when docker-credential-osxkeychain is gone · Issue #6517 · docker/compose)
- Open Docker menu
- Click "Sign in / Create Docker ID". The Docker app will store the appropriate credentials in your Mac's keychain