Introduction to Fitbit dapp
A-Lin
About Me
Profile
- JAVA 5 years
- Javascript 3 years
- conference speaker
- JSDC.tw 2016
- Testing Day 2018
- Modern Web 2016, 2018
- coding coach
- alincode@gmail.com
for this example, we don't use large front-end framework
Lightweight Module
-
nanohtml
-
morphdom
-
csjs-inject
-
budo
-
browserify
nanohtml (bel)
HTML template strings for the Browser with support for Server Side Rendering in Node.
// insert DOM element
const html = require('nanohtml');
const element = html`<div>Hello!</div>`;
document.body.appendChild(element);
// bind event
function hi(event) { alert('Hello'); }
var button = bel`<button class="primary" onclick=${hi}>click me</button>`
morphdom
Fast and lightweight DOM diffing/patching (no virtual DOM needed)
const html = require('nanohtml');
const morphdom = require('morphdom');
const element = html`<div>hello</div>`;
const newElement = html`<div>Hi</div>`;
// update DOM element
morphdom(element, newElement)
csjs-inject
A CSJS wrapper module that works exactly like CSJS, but adds auto-injection of styles into the DOM.
const csjs = require('csjs-inject');
const css = csjs `
.input {
margin: 10px;
width: 500px;
font-size: 20px;
}
`
const inputAccount
= html `<input class=${css.input} type="text" placeholder="input your account"/>`;
budo
// install module
npm install budo -g
// live reload mode
budo src/01.js:bundle.js --live --open --dir ./static
a dev server for rapid prototyping --open:set port number --live:switch dev live mode --dir: set public directory
browserify
Browserify lets you require('modules') in the browser by bundling up all of your dependencies.
// install module
npm install browserify -g
// package module
browserify src/01.js > static/01.js
const Web3 = require('web3');
const html = require('nanohtml');
const csjs = require('csjs-inject');
const morphdom = require('morphdom');
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js"/>
if you don't use require symptom
Fitbit DApp
Player
Funder
Owner
role
guest
View
-
player of amount
-
how many players
-
funder of amount
-
how many funders
-
funder list
-
goal step
-
during
-
isSign
-
isOwner
Action
-
bet
-
fund
player
View
-
isSign
-
begin step
-
current step
Action
-
fund
funder
special logical
- first time
- insert a new row
- second time
- update amount
fund
owner
View
-
endAt
-
state
Action
step1:contest done
step2:award
Start to build DApp
All Step
step1: import module step2: initial web3.js instance step3: connect with smart contract step4: CSS inject step5: DOM element step6: listening smart contract event step7: implement DOM Event step8: preload data step9: render
Step1 : import module
const Web3 = require('web3');
const html = require('nanohtml');
const csjs = require('csjs-inject');
const morphdom = require('morphdom');
Step2: initial web3.js instance
if (typeof web3 !== 'undefined') {
web3 = new Web3(web3.currentProvider);
} else {
alert('initial failed');
}
Step3: connect with smart contract
const ABI = require('./abi.json');
const DEFAULT_ADDRESS = '0x0c972a74a9806f249968720035ebda65b653360c';
const myContract = new web3.eth.Contract(ABI, DEFAULT_ADDRESS);
Step4 : CSS inject
const css = csjs `
.box {
margin: 10px;
}
.input {
margin-top: 10px;
margin-right: 10px;
width: 500px;
font-size: 20px;
}
.button {
margin-top: 10px;
margin-right: 10px;
font-size: 20px;
width: 180px;
background-color: #4CAF50;
color: white;
}
img {
border: 1px solid #ddd;
border-radius: 4px;
padding: 5px;
width: 150px;
}
`
Step5: DOM element
const fundAmountElement = bel `<input class=${css.input} type="text"/>`;
const fundNameElement = bel `<input class=${css.input} type="text"/>`;
const fundAreaElement = bel `
<div class="${css.box6}">
I want to sponsor this contest with ${fundAmountElement} ETH!<br>
Name you want to be added to our sponsorship board. ${fundNameElement}<br>
<button class=${css.shortButton} onclick=${fund}> Fund </button> (min 0.5 ETH)
</div>
`
Step6 : listening smart contract event
// Generate filter options
const options = {
// filter: {
// _from: process.env.WALLET_FROM,
// _to: process.env.WALLET_TO,
// _value: process.env.AMOUNT
// },
fromBlock: 'latest'
}
myContract.events.NewFundLog(options, async (error, event) => {
if (error) {
console.log(error)
return
}
const ether = web3.utils.fromWei(event.returnValues.amount, "ether");
const name = event.returnValues.name;
location.reload();
// const newElement = html`<div class="${css.result}">.......</div>`
// morphdom(resultElement, newElement);
return
})
Step7 : implement DOM Event
function fund(event) {
let account = web3.eth.defaultAccount;
// send contract
myContract.methods.fund(inputName.value).send({
from: account,
value: web3.utils.toWei(inputAmount.value, "ether")
}, (err, data) => {
if (err) return console.error(err);
console.log('>>> fund ok.');
});
}
function fund(string _name) public minimizeContribute onlyOnTime payable {
if(funders[msg.sender].amount != 0) {
funders[msg.sender].amount += msg.value;
funders[msg.sender].name = _name;
} else {
funders[msg.sender] = Funder(msg.sender, msg.value, now, _name);
funderIndexs.push(msg.sender);
}
fundersOfAmount += msg.value;
}
smart contract
DApp
Step8 :
Preload Data
function start() {
console.log('=== start ===');
step1({});
}
function step1(result) {
// call contract
myContract.methods.getFunders().call((err, data) => {
if (err) return console.error(err);
result.funders = data;
step2(result);
})
}
function step2(result) {
step3(result)
}
function lastStep(result) {
render(result)
}
function getFunders() public view returns (string[], uint[]) {
string[] memory names = new string[](funderIndexs.length);
uint[] memory amounts = new uint[](funderIndexs.length);
for (uint i = 0; i < funderIndexs.length; i++) {
Funder storage funder = funders[funderIndexs[i]];
names[i] = funder.name;
amounts[i] = funder.amount;
}
return (names, amounts);
}
smart contract
DApp
Step9 : Render
function lastStep(result) {
console.log('>>> last step');
render(result)
}
function render(result) {
console.log('>>> result:', result);
document.body.appendChild(html `
<div class=${css.box} id="app">
// skip...
Name: ${inputName}<br>
Amount: ${inputAmount}<br>
// skip...
</div>
`)
}
if (typeof web3 !== 'undefined') start();
prepare to deploy
browserify src/index.js > bundle.js
<!doctype html>
<html>
<head><meta charset="utf-8"></head>
<body>
<script src="bundle.js"></script>
</body>
</html>
package module
index.html
directory
* src
- abi.json
- index.js
- index.html
- bundle.js
good job, we finish.
Introduction_to_fitbit_dapp
By alincode
Introduction_to_fitbit_dapp
by alincode
- 1,320