Based on https://www.ethereum.org/greeter
npm install web3@0.20.0 solc
mkdir contracts && touch contracts/greeter.sol
// contracts/GreetingsFactory.sol
pragma solidity ^0.4.17;
contract GreetingsFactory {
string greeting;
address greeter;
function GreetingsFactory() public {
setGreetings('Hey there!');
}
function getGreetings() public view returns (string _greeting, address _greeter) {
return(greeting, greeter);
}
function setGreetings(string _greeting) public {
greeter = msg.sender;
greeting = _greeting;
}
}
Install and open Ganache
in a node console:
> Web3 = require('web3')
> web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')) // connect to the Ganache node
> solc = require('solc')
> sourceCode = fs.readFileSync('./contracts/GreetingsFactory.sol').toString() // get string of from the contract
> compiledCode = solc.compile(sourceCode); // compile it
> contractABI = JSON.parse(compiledCode.contracts[':GreetingsFactory'].interface); // interface of the contract
> byteCode = compiledCode.contracts[':GreetingsFactory'].bytecode // store byteCode
> greetingsContract = web3.eth.contract(contractABI); // get contract Factory from web3
> greetingsDelpoyed = greetingsContract.new({data: byteCode, from: web3.eth.accounts[0], gas: 4700000}); // deploy contract on the ganache node
> greetingsInstance = greetingsContract.at(greetingsDelpoyed.address); // get instance
> greetingsInstance.getGreetings();
['Hey there!', '0x627306090abaB3A6e1400e9345bC60c78a8BEf57']
> greetingsInstance.setGreetings('Hello world', { from: web3.eth.accounts[1] });
> greetingsInstance.getGreetings();
['Hello world', '0xf17f52151EbEF6C7334FAD080c5704D77216b732']
install truffle globally
npm install -g truffle
Init a truffle project with the webpack box
This will delete this README file so please save it before
truffle unbox webpack
Remove all the contract in the contracts/
folder except the Migration.sol
and the GreeingsFactory.sol that we've just created and change the second migration in the migrations/
folder as follow:
// migrations/2_deploy_contracts.js
var GreetingsFactory = artifacts.require("./GreetingsFactory.sol");
module.exports = function(deployer) {
deployer.deploy(GreetingsFactory);
};
Change the html, the css and the javascript in the app/
folder.
<!-- app/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Greetings - My First Smart Contract</title>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<script src="./app.js"></script>
</head>
<body>
<div class="account-info">
<h3>Your account</h3>
<!-- hard coded example to remove when javascript is done -->
<p id="account">0x627306090abaB3A6e1400e9345bC60c78a8BEf57</p>
<p id="accountBalance">10 ETH</p>
</div>
<h1>Greetings</h1>
<div>
<!-- hard coded example to remove when javascript is done -->
<span class="speech-bubble" id="greeting">
Hello World
</span>
</div>
<p class="greeter-head">🙋</p>
<!-- hard coded example to remove when javascript is done -->
<p id="greeter">0x627306090abaB3A6e1400e9345bC60c78a8BEf57</p>
</body>
</html>
/* app/stylesheets/app.css */
body {
display: flex;
justify-content: center;
align-content: center;
flex-direction: column;
height: 100vh;
text-align: center;
font-family: "Open Sans", sans-serif;
color: #0f4137;
background-color: #e7f5f2;
}
h1 {
margin: 70px;
}
.speech-bubble {
color: #f9c7cf;
padding: 25px 20px;
position: relative;
background: #12776f;
border-radius: .4em;
margin-bottom: 20px;
max-width: 300px;
}
.speech-bubble:after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
width: 0;
height: 0;
border: 13px solid transparent;
border-top-color: #12776f;
border-bottom: 0;
border-left: 0;
margin-left: -6.5px;
margin-bottom: -13px;
}
.greeter-head {
font-size: 80px;
margin-top: 50px;
margin-bottom: 10px;
}
// app/javascripts/app.css
// Import the page's CSS. Webpack will know what to do with it.
import "../stylesheets/app.css";
// Import libraries we need.
import Web3 from 'web3';
import TruffleContract from 'truffle-contract'
// Import our contract artifacts (ABI) and turn them into usable abstractions.
import greetings_artifacts from '../../build/contracts/GreetingsFactory.json'
const App = {
contracts: {},
web3Provider: null,
account: 0x0,
init: function() {
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
App.web3Provider = web3.currentProvider;
window.web3 = new Web3(web3.currentProvider);
} else {
// fallback - use your fallback strategy (for us it's Ganache)
App.web3Provider = new Web3.providers.HttpProvider("http://localhost:7545")
}
window.web3 = new Web3(App.web3Provider);
App.displayAccountInfo();
App.initContract();
},
displayAccountInfo: function() {
const account = document.getElementById('account');
const accountBalance = document.getElementById('accountBalance');
// get the account of reference, by default the first one
web3.eth.getCoinbase((err, coinbase) => {
App.account = coinbase;
account.innerText = App.account;
web3.eth.getBalance(App.account, (err, balance) => {
accountBalance.innerText = `${web3.fromWei(balance, 'ether').toNumber()} ETH`;
})
})
},
initContract: function() {
// GreeingsFactory is our usable abstraction, which we'll use through the code below.
App.contracts.GreeingsFactory = TruffleContract(greetings_artifacts);
App.contracts.GreeingsFactory.setProvider(App.web3Provider);
// get greetings from the contract
App.reloadGreetings();
},
reloadGreetings: function() {
App.contracts.GreeingsFactory.deployed()
.then((instance) => instance.getGreetings())
.then(([greeting, greeter]) => {
// get greeting and put it on the HTML
const greetingEl = document.getElementById('greeting');
const greeterEl = document.getElementById('greeter');
greetingEl.innerText = greeting
if (greeter === App.account) {
greeterEl.innerText = 'You';
} else {
greeterEl.innerText = greeter;
}
})
}
};
window.addEventListener('load', function() {
App.init();
});
Run the migration. (be sure ganache is running!)
truffle migrate --compile-all --reset --network development
Run the app. You should see 'Hey there!' on http://localhost:8080
If you have the MetaMask extension, don't forget to disable it before!
npm run dev
Run the truffle console on a new terminal window.
truffle console --network development
And set a new greeting from it
> GreetingsFactory.deployed().then((instance) => { greetingsInstance = instance }) // get the instance with the truffle way
> greetingsInstance.getGreetings();
['Hey there!', '0x627306090abaB3A6e1400e9345bC60c78a8BEf57']
> greetingsInstance.setGreetings('Hello world', { from: web3.eth.accounts[1] });
> greetingsInstance.getGreetings();
['Hello world', '0xf17f52151EbEF6C7334FAD080c5704D77216b732']
Got back to http://localhost:8080, You should see 'Hello world'. Congrats you've just finished your first DAPP. 🚀
The solution is on the branch
solution
of this repo.