Skip to content

Commit

Permalink
- Added eosio_docker foler containing the notechain application
Browse files Browse the repository at this point in the history
- Added scripts to set up blockchain, frontend and backend
- Updated dependencies in 'server'
  • Loading branch information
Matthew Kelly committed Feb 20, 2020
1 parent 17b40e2 commit 7ad2229
Show file tree
Hide file tree
Showing 17 changed files with 528 additions and 101 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

#blockchain data
**/data/*
7 changes: 7 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM ubuntu:18.04

RUN apt-get update && apt-get install -y wget sudo curl
RUN wget https://github.com/EOSIO/eosio.cdt/releases/download/v1.6.2/eosio.cdt_1.6.2-1-ubuntu-18.04_amd64.deb
RUN apt-get update && sudo apt install -y ./eosio.cdt_1.6.2-1-ubuntu-18.04_amd64.deb
RUN wget https://github.com/EOSIO/eos/releases/download/v2.0.0/eosio_2.0.0-1-ubuntu-18.04_amd64.deb
RUN apt-get update && sudo apt install -y ./eosio_2.0.0-1-ubuntu-18.04_amd64.deb
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Server Side Rendering Boilerplate POC

This repo contains two folders, `app` and `server`:
## To set everything up at once, you can run `quick_start.sh`.

This repo contains three folders, `eosio_docker`, `app` and `server`:

## eosio_docker

`eosio_docker` contains everything needed to set up the local blockchain containing the `notechain` application.

## app
`app` contains a Next.js / Redux app with a few pages showing some different features, including:
Expand Down
4 changes: 4 additions & 0 deletions constant.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash

readonly DOCKER_IMAGE_NAME="eosio-notechain"
readonly DOCKER_IMAGE_TAG="eos2.0.0-cdt1.6.2"
85 changes: 85 additions & 0 deletions eosio_docker/contracts/notechain/notechain.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include <eosio/eosio.hpp>
#include <eosio/system.hpp>

using namespace eosio;

// Smart Contract Name: notechain
// Table struct:
// notestruct: multi index table to store the notes
// prim_key(uint64): primary key
// user(name): account name for the user
// note(string): the note message
// timestamp(uint64): the store the last update block time
// Public method:
// isnewuser => to check if the given account name has note in table or not
// Public actions:
// update => put the note into the multi-index table and sign by the given account

// Replace the contract class name when you start your own project
CONTRACT notechain : public eosio::contract {
private:
bool isnewuser( name user ) {
// get notes by using secordary key
auto note_index = _notes.get_index<name("getbyuser")>();
auto note_iterator = note_index.find(user.value);

return note_iterator == note_index.end();
}

TABLE notestruct {
uint64_t prim_key; // primary key
name user; // account name for the user
std::string note; // the note message
block_timestamp timestamp; // the store the last update block time

// primary key
auto primary_key() const { return prim_key; }
// secondary key
// only supports uint64_t, uint128_t, uint256_t, double or long double
uint64_t get_by_user() const { return user.value; }
};

// create a multi-index table and support secondary key
typedef eosio::multi_index< name("notestruct"), notestruct,
indexed_by< name("getbyuser"), const_mem_fun<notestruct, uint64_t, &notestruct::get_by_user> >
> note_table;

note_table _notes;

public:
using contract::contract;

// constructor
notechain( name receiver, name code, datastream<const char*> ds ):
contract( receiver, code, ds ),
_notes( receiver, receiver.value ) {}

ACTION update( name user, std::string& note ) {
// to sign the action with the given account
require_auth( user );

// create new / update note depends whether the user account exist or not
if (isnewuser(user)) {
// insert new note
_notes.emplace( _self, [&]( auto& new_user ) {
new_user.prim_key = _notes.available_primary_key();
new_user.user = user;
new_user.note = note;
new_user.timestamp = eosio::current_block_time();
});
} else {
// get object by secordary key
auto note_index = _notes.get_index<name("getbyuser")>();
auto &note_entry = note_index.get(user.value);
// update existing note
_notes.modify( note_entry, _self, [&]( auto& modified_user ) {
modified_user.note = note;
modified_user.timestamp = eosio::current_block_time();
});
}
}

};

// specify the contract name, and export a public action: update
EOSIO_DISPATCH( notechain, (update) )
9 changes: 9 additions & 0 deletions eosio_docker/scripts/accounts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{"name":"useraaaaaaaa", "privateKey":"5K7mtrinTFrVTduSxizUc5hjXJEtTjVTsqSHeBHes1Viep86FP5", "publicKey":"EOS6kYgMTCh1iqpq9XGNQbEi8Q6k5GujefN9DSs55dcjVyFAq7B6b"},
{"name":"useraaaaaaab", "privateKey":"5KLqT1UFxVnKRWkjvhFur4sECrPhciuUqsYRihc1p9rxhXQMZBg", "publicKey":"EOS78RuuHNgtmDv9jwAzhxZ9LmC6F295snyQ9eUDQ5YtVHJ1udE6p"},
{"name":"useraaaaaaac", "privateKey":"5K2jun7wohStgiCDSDYjk3eteRH1KaxUQsZTEmTGPH4GS9vVFb7", "publicKey":"EOS5yd9aufDv7MqMquGcQdD6Bfmv6umqSuh9ru3kheDBqbi6vtJ58"},
{"name":"useraaaaaaad", "privateKey":"5KNm1BgaopP9n5NqJDo9rbr49zJFWJTMJheLoLM5b7gjdhqAwCx", "publicKey":"EOS8LoJJUU3dhiFyJ5HmsMiAuNLGc6HMkxF4Etx6pxLRG7FU89x6X"},
{"name":"useraaaaaaae", "privateKey":"5KE2UNPCZX5QepKcLpLXVCLdAw7dBfJFJnuCHhXUf61hPRMtUZg", "publicKey":"EOS7XPiPuL3jbgpfS3FFmjtXK62Th9n2WZdvJb6XLygAghfx1W7Nb"},
{"name":"useraaaaaaaf", "privateKey":"5KaqYiQzKsXXXxVvrG8Q3ECZdQAj2hNcvCgGEubRvvq7CU3LySK", "publicKey":"EOS5btzHW33f9zbhkwjJTYsoyRzXUNstx1Da9X2nTzk8BQztxoP3H"},
{"name":"useraaaaaaag", "privateKey":"5KFyaxQW8L6uXFB6wSgC44EsAbzC7ideyhhQ68tiYfdKQp69xKo", "publicKey":"EOS8Du668rSVDE3KkmhwKkmAyxdBd73B51FKE7SjkKe5YERBULMrw"}
]
29 changes: 29 additions & 0 deletions eosio_docker/scripts/continue_blockchain.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -o errexit

# this file is used to continue the stopped blockchain

echo "=== start blockchain with ==="

# set PATH
PATH="$PATH:/opt/eosio/bin"

set -m

# start nodeos ( local node of blockchain )
# run it in a background job such that docker run could continue
nodeos -e -p eosio -d /mnt/dev/data \
--config-dir /mnt/dev/config \
--hard-replay \
--http-validate-host=false \
--plugin eosio::producer_plugin \
--plugin eosio::chain_api_plugin \
--plugin eosio::http_plugin \
--http-server-address=0.0.0.0:8888 \
--access-control-allow-origin=* \
--contracts-console \
--verbose-http-errors

# `--hard-replay` option is needed
# because the docker stop signal is not being passed to nodeos process directly
# as we run the init_blockchain.sh as PID 1.
29 changes: 29 additions & 0 deletions eosio_docker/scripts/create_accounts.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash
set -o errexit

echo "=== start deploy data ==="

# set PATH
PATH="$PATH:/opt/eosio/bin"

# change to script directory
cd "$(dirname "$0")"

echo "=== start create accounts in blockchain ==="

# download jq for json reader, we use jq here for reading the json file ( accounts.json )
mkdir -p ~/bin && curl -sSL -o ~/bin/jq https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 && chmod +x ~/bin/jq && export PATH=$PATH:~/bin

# loop through the array in the json file, import keys and create accounts
# these pre-created accounts will be used for saving / erasing notes
# we hardcoded each account name, public and private key in the json.
# NEVER store the private key in any source code in your real life developmemnt
# This is just for demo purpose

jq -c '.[]' accounts.json | while read i; do
name=$(jq -r '.name' <<< "$i")
pub=$(jq -r '.publicKey' <<< "$i")

# to simplify, we use the same key for owner and active key of each account
cleos create account eosio $name $pub $pub
done
25 changes: 25 additions & 0 deletions eosio_docker/scripts/deploy_contract.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -o errexit

# set PATH
PATH="$PATH:/opt/eosio/bin"

CONTRACTSPATH="$( pwd -P )/contracts"

# make new directory for compiled contract files
mkdir -p ./compiled_contracts
mkdir -p ./compiled_contracts/$1

COMPILEDCONTRACTSPATH="$( pwd -P )/compiled_contracts"

# unlock the wallet, ignore error if already unlocked
if [ ! -z $3 ]; then cleos wallet unlock -n $3 --password $4 || true; fi

# compile smart contract to wasm and abi files using EOSIO.CDT (Contract Development Toolkit)
# https://github.com/EOSIO/eosio.cdt
(
eosio-cpp -abigen "$CONTRACTSPATH/$1/$1.cpp" -o "$COMPILEDCONTRACTSPATH/$1/$1.wasm" --contract "$1"
) &&

# set (deploy) compiled contract to blockchain
cleos set contract $2 "$COMPILEDCONTRACTSPATH/$1/" --permission $2
69 changes: 69 additions & 0 deletions eosio_docker/scripts/init_blockchain.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
set -o errexit

echo "=== setup blockchain accounts and smart contract ==="

# set PATH
PATH="$PATH:/opt/eosio/bin:/opt/eosio/bin/scripts"

set -m

# start nodeos ( local node of blockchain )
# run it in a background job such that docker run could continue
nodeos -e -p eosio -d /mnt/dev/data \
--config-dir /mnt/dev/config \
--http-validate-host=false \
--plugin eosio::producer_plugin \
--plugin eosio::chain_api_plugin \
--plugin eosio::http_plugin \
--http-server-address=0.0.0.0:8888 \
--access-control-allow-origin=* \
--contracts-console \
--verbose-http-errors &
sleep 1s
until curl localhost:8888/v1/chain/get_info
do
sleep 1s
done

# Sleep for 2 to allow time 4 blocks to be created so we have blocks to reference when sending transactions
sleep 2s
echo "=== setup wallet: eosiomain ==="
# First key import is for eosio system account
cleos wallet create -n eosiomain --to-console | tail -1 | sed -e 's/^"//' -e 's/"$//' > eosiomain_wallet_password.txt
cleos wallet import -n eosiomain --private-key 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3

echo "=== setup wallet: notechainwal ==="
# key for eosio account and export the generated password to a file for unlocking wallet later
cleos wallet create -n notechainwal --to-console | tail -1 | sed -e 's/^"//' -e 's/"$//' > notechain_wallet_password.txt
# Owner key for notechainwal wallet
cleos wallet import -n notechainwal --private-key 5JpWT4ehouB2FF9aCfdfnZ5AwbQbTtHBAwebRXt94FmjyhXwL4K
# Active key for notechainwal wallet
cleos wallet import -n notechainwal --private-key 5JD9AGTuTeD5BXZwGQ5AtwBqHK21aHmYnTetHgk1B3pjj7krT8N

# * Replace "notechainwal" by your own wallet name when you start your own project

# create account for notechainacc with above wallet's public keys
cleos create account eosio notechainacc EOS6PUh9rs7eddJNzqgqDx1QrspSHLRxLMcRdwHZZRL4tpbtvia5B EOS8BCgapgYA2L4LJfCzekzeSr3rzgSTUXRXwNi8bNRoz31D14en9

# * Replace "notechainacc" by your own account name when you start your own project

echo "=== deploy smart contract ==="
# $1 smart contract name
# $2 account holder name of the smart contract
# $3 wallet for unlock the account
# $4 password for unlocking the wallet
deploy_contract.sh notechain notechainacc notechainwal $(cat notechain_wallet_password.txt)

echo "=== create user accounts ==="
# script for create data into blockchain
create_accounts.sh

# * Replace the script with different form of data that you would pushed into the blockchain when you start your own project

echo "=== end of setup blockchain accounts and smart contract ==="
# create a file to indicate the blockchain has been initialized
touch "/mnt/dev/data/initialized"

# put the background nodeos job to foreground for docker run
fg %1
49 changes: 49 additions & 0 deletions first_time_setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env bash

source constant.sh

echo "=== start of first time setup ==="

# change to script's directory
cd "$(dirname "$0")"
SCRIPTPATH="$( pwd -P )"

# make sure Docker and Node.js is installed
if [ ! -x "$(command -v docker)" ] ||
[ ! -x "$(command -v npm)" ]; then
echo ""
echo -e "\033[0;31m[Error with Exception]\033[0m"
echo "Please make sure Docker and Node.js are installed"
echo ""
echo "Install Docker: https://docs.docker.com/docker-for-mac/install/"
echo "Install Node.js: https://nodejs.org/en/"
echo ""
exit
fi

# build docker image, if necessary
if [[ "$(docker images -q $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG)" == "" ]]; then
echo "=== Build docker image $DOCKER_IMAGE_NAME version $DOCKER_IMAGE_TAG, this will take some time for the first time run ==="
docker build -t $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG .
else
echo "=== Docker image already exists, skip building ==="
fi

# force remove the perivous container if any
# create a clean data folder in eosio_docker to preserve block data
echo "=== setup/reset data for eosio_docker ==="
docker rm --force eosio_notechain_container
rm -rf "./eosio_docker/data"
mkdir -p "./eosio_docker/data"

# set up node_modules for frontend
echo "=== yarn install package for backend react app ==="
# change directory to ./server
cd "$SCRIPTPATH/server"
yarn

# set up node_modules for frontend
echo "=== yarn install package for frontend react app ==="
# change directory to ./app
cd "$SCRIPTPATH/app"
yarn
34 changes: 34 additions & 0 deletions quick_start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env bash

# make sure everything is clean and well setup
echo "[quick_start.sh] First time setup"
./first_time_setup.sh

# start blockchain and put in background
echo "[quick_start.sh] Starting eosio docker"
./start_eosio_docker.sh --nolog

# wait until eosio blockchain to be started
until $(curl --output /dev/null \
--silent \
--head \
--fail \
localhost:8888/v1/chain/get_info)
do
echo "Waiting eosio blockchain to be started..."
sleep 2s
done

# An extra sleep is added here to make sure the note contract is deployed before the front end is launched
sleep 5s

echo "[quick_start.sh] Starting backend react app"
./start_backend.sh &

#start frontend react app
echo "[quick_start.sh] Starting frontend react app"
./start_frontend.sh &
P1=$!

# wait $P1
wait $P1
6 changes: 3 additions & 3 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
"dependencies": {
"cookie-parser": "~1.4.4",
"cors": "^2.8.5",
"debug": "~2.6.9",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"debug": "~4.1.1",
"express": "~4.17.1",
"http-errors": "~1.7.3",
"jade": "~1.11.0",
"jsonwebtoken": "^8.5.1",
"morgan": "~1.9.1"
Expand Down
Loading

0 comments on commit 7ad2229

Please sign in to comment.