创建前端应用
1- 创建主入口代码
打开src/js/index.js文件,加入以下代码:
importReactfrom'react'
importReactDOMfrom'react-dom'
importWeb3from'web3'
import'./../css/index.css'
classAppextendsReact.Component{
constructor(props){
super(props)
this.state = {
lastWinner:0,
timer:0
}
}
voteNumber(number){
console.log(number)
}
render(){
return(
Bet for your best number and win huge amounts of Ether
Timer:
{this.state.timer}
Last winner:
{this.state.lastWinner}
Vote for the next number
{this.voteNumber(1)}}>1
{this.voteNumber(2)}}>2
{this.voteNumber(3)}}>3
{this.voteNumber(4)}}>4
{this.voteNumber(5)}}>5
{this.voteNumber(6)}}>6
{this.voteNumber(7)}}>7
{this.voteNumber(8)}}>8
{this.voteNumber(9)}}>9
{this.voteNumber(10)}}>10
)
}
}
ReactDOM.render(
,
document.querySelector('#root')
)
2- 创建CSS文件
打开src/css/index.css文件,加入以下代码:
body{
font-family:'open sans';
margin:0;
}
ul{
list-style-type: none;
padding-left:0;
display: flex;
}
li{
padding:40px;
border:2pxsolidrgb(30, 134, 255);
margin-right:5px;
border-radius:10px;
cursor: pointer;
}
li:hover{
background-color:rgb(30, 134, 255);
color: white;
}
li:active{
opacity:0.7;
}
* {
color:#444444;
}
.main-container{
padding:20px;
}
.block{
display: flex;
align-items: center;
}
.number-selected{
background-color:rgb(30, 134, 255);
color: white;
}
.bet-input{
padding:15px;
border-radius:10px;
border:1pxsolid lightgrey;
font-size:15pt;
margin:010px;
}
3- 用webpack打包应用并运行
在命令行中,使用命令:webpack或者npm run build编译打包。
以上命令在package.json文件中配置,查看scripts,如下:
"scripts": {
"build":"webpack --log-level=debug",//npmrun build等同于webpack命令
"start":"webpack-dev-server --port 3030 --inline --content-base ./build"
},
然后运行:npm start启动web服务,默认情况下npm init时会生成8080端口的web服务,如果冲突,可以改为其他端口。如本例改为了3030本地端口。
接着在浏览器中打开: http://127.0.0.1:3030,可以看到如下网页:
4- 连接智能合约与javascript前端
在Remix中部署合约,找到ABI文件,并复制。
在index.js中添加如下代码:
if(typeofweb3 !="undefined") {
//启动Metamask
console.log("Using web3 detected from external source like Metamask")
this.web3 =newWeb3(web3.currentProvider)
}else{
//启用本地以太坊网络或者Truffle的Ganache
this.web3 =newWeb3(newWeb3.providers.HttpProvider("http://localhost:8545"))
}
constcontractAddress ="0xB2bE09289F9f7103964f57aAF04119fcB79d2149"//本案例部署的合约帐号,可换
constabi = 合约的ABI数组,一个非常长的数组
constMyContract = web3.eth.contract(abi)
this.state.ContractInstance = MyContract.at(contractAddress)
执行合约中函数的基本方法,以合约中的bet函数为例:
yourContractInstance.bet(7, {// 7为函数参数,即下注的数字
gas:300000,// Gas
from: web3.eth.accounts[0],// 用户帐号,accounts是数组,取第一个元素
value: web3.toWei(0.1,'ether')// 发送金额,单位wei
}, (err, result) => {...})
如果调用不需要Gas的方法或者变量,使用如下代码:
yourContractInstance.maxAmountOfBets((err, result)=>{
if(result !=null) {...}
})
在index.js继续添加以下代码:
componentDidMount() {
this.updateState()
this.setupListeners()
setInterval(this.updateState.bind(this),10e3)
}
updateState() {
this.state.ContractInstance.minimumBet((err, result) =>{
if(result !=null) {
this.setState({
minimumBet:parseFloat(web3.fromWei(result,'ether'))
})
}
})
this.state.ContractInstance.totalBet((err, result) =>{
if(result !=null) {
this.setState({
totalBet:parseFloat(web3.fromWei(result,'ether'))
})
}
})
this.state.ContractInstance.numberOfBets((err, result) =>{
if(result !=null) {
this.setState({
numberOfBets:parseInt(result)
})
}
})
this.state.ContractInstance.maxAmountOfBets((err, result) =>{
if(result !=null) {
this.setState({
maxAmountOfBets:parseInt(result)
})
}
})
}
// 设置监听器
setupListeners() {
letliNodes =this.refs.numbers.querySelectorAll('li')
liNodes.forEach(number=>{
number.addEventListener('click', event => {
event.target.className ='number-selected'
this.voteNumber(parseInt(event.target.innerHTML), done => {
// Remove the other number selected
for(leti =0; i < liNodes.length; i++) {
liNodes[i].className =''
}
})
})
})
}
// 下注
voteNumber(number, cb) {
letbet =this.refs['ether-bet'].value
if(!bet) bet =0.1//默认下注为0.1ETH
if(parseFloat(bet)
alert('You must bet more than the minimum')
cb()
}else{
this.state.ContractInstance.bet(number, {
gas:300000,
from: web3.eth.accounts[0],
value: web3.toWei(bet,'ether')
}, (err, result) => {
cb()
})
}
}
至此,主要的程序已经完成,webpack打包编译,运行npm start,然后在浏览器中打开:http://127.0.0.1:3030可以试玩。
四、使用IPFS部署应用
在本章,我们将看到IPFS的强大,她可以方便的部署一个去中心化的应用。
启动IPFS网络后,运行以下命令:
ipfsadd-r dist/
ipfs name publish 上面生成的Hash值
之后就可以直接用:http://网关/ipfs/网站Hash 进行访问。
即可在IPFS网络上访问并运行该分布式应用。