Bulding your first blockchain app with Ethereum
Introduction
Today we are going to make our first simple decentralized app using the blockchain.
The app is going to be a simple micro blog service.
Setup
mkdir dapp-demo
cd dapp-demo
npm init
npm install ethereumjs-testrpc web3 solc http-server --save
ethereumjs-testrc is for running a local dev blockchain
web3 is the ethereum js client
solc is for compiling smart contracts
http-server for running the web app in a dev env
Creating the smart contract
MyBlog.sol
pragma solidity ^0.4.11;
contract MyBlog {
bytes32 private blogName;
bytes32[] private messages;
function MyBlog(bytes32 title) {
blogName = title;
}
function addPost(bytes32 message) {
messages.push(message);
}
function getMessages() returns (bytes32[]) {
return messages;
}
function getBlogName() returns (bytes32) {
return blogName;
}
}
Read more about solidity
Compiling the smart contract and deploying the code to the blockchain
compile.js
fs = require('fs');
Web3 = require('web3');
solc = require('solc');
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
code = fs.readFileSync('MyBlog.sol').toString();
compiledCode = solc.compile(code);
abiDefinition = JSON.parse(compiledCode.contracts[':MyBlog'].interface);
console.log(abiDefinition);
MyBlogContract = web3.eth.contract(abiDefinition);
byteCode = compiledCode.contracts[':MyBlog'].bytecode;
// Get first account from the blockchain to deploy the contract
blogTitle = "Demo Blog";
MyBlogContract.new(blogTitle ,{data: byteCode, from: web3.eth.accounts[0], gas: 4700000}, function(err, myContract){
if(!err && myContract.address) {
console.log(myContract.address);
}
});
Run the test blockchain by executing ./node_modules/.bin/testrpc
Then execute ‘node compile.js’ and save the outputs.
Building the web app
index.html
<html>
<head>
<title>Decentralized Blog</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdn.rawgit.com/ethereum/web3.js/develop/dist/web3.js"></script>
<script src="app.js"></script>
</head>
<body>
<ul id="messages"></ul>
<input type="text" id="message"/>
<button id="send" onClick="addPost()">Send</button>
</body>
</html>
app.js (Use the outputs from the compile.js)
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
// Extracted from compiledCode.contracts[':MyBlog'].interface
var abi = JSON.parse('[{"constant":false,"inputs":[],"name":"getMessages","outputs":[{"name":"","type":"bytes32[]"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"getBlogName","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"message","type":"bytes32"}],"name":"addPost","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"title","type":"bytes32"}],"payable":false,"type":"constructor"}]');
BlogContract = web3.eth.contract(abi);
// Extracted from myContract.address
blog = BlogContract.at('0x69c99b6a9dacb80df84d1fed7ea1555b802f09b8');
$(document).ready(function() {
$container = $('#messages');
getPosts();
});
function getPosts() {
posts = blog.getMessages.call();
// Print them
$container.html('');
for (var i = 0; i < posts.length; i++) {
$container.append('<li>'+web3.toAscii(posts[i])+'</li>');
}
}
function addPost() {
$message = $('#message');
blog.addPost($message.val(), {from: web3.eth.accounts[0]}, function() {
alert('Success!');
$message.val('');
getPosts();
})
}
Note:
Difference between contract.getMessages() and contract.getMessages.call()
call() is for read operations, doesn’t cost gas and doesn’t write in the blockchain.
Calling a method directly, like getMessages(), is for writing in the blockchain and costs gas.
Read more about gas
Running
Run the website http-server -a localhost -p 8000 -c-1 .
Download the full code at github