处探DApp总结
关键点:DAPP关键是web3和智能合约交互
不足:
1.使用以太坊网络,交易确认慢,消耗账户以太币
2.需要搭建web服务器
3.不易修改,测试,调试,发布应用。
为了解决这些问题我们采取了学习:
1⃣️使用本地节点Ganache
2⃣️web3.js的原理和使用
3⃣️使用开发框架truffle
Web服务器搭建
最主流的使用:Nginx/Apache
或者用集成的方法:
如在mac下可以下载MAMP
1.MAMP:集成了Mac+Apache+Mysql+Php
2.或者应用Python启动一个f服务器节点
python -m SimpleHTTPServur会返回一个8000端口
在浏览器中输入http://127.0.0.1:8000/ 即可启动
3.利用npm先安装好npm lite-server启动npm run dev即可
)
Geth:go-ethereum以太坊节点官方的go语言实现版本
Mac下:使用brew 安装 brew是Mac下的包安装工具
在geth下创建私有链之前有写过博客。
在Geth下使用API服务:1.HTTP RPC22.Web Socket 3.IPC默认开启
这节课讲
开启多个节点。
本地测试注意点:
1.每个节点都有不同的datadir
2.每个节点要运行在不同
多节点建立连接。admin.addPeer
把webservice部署到自己的服务器上。不要放本地,以后到服务器上去调用。
需要注意的
1.使用web3对象:如果使用本地节点,可以使用同步接口,否则大部分接口仅能使用异步接口,传递一个回调函数作为最后一个参数,回调函数使用error-first风格。
例:异步接口
web3.eth.getBlock(58,function(error,result){
if(!error){
console.log(JSON.stringify(result));
}
else{
console.log(error);
}
});
主要还是得自己去看api文档
主要需要用到的4个常用api接口
1.检查环境
** (观察matemask是否安装**)
id=env显示当前环境。net显示当前网络
2.发送交易
检查钱包是否解锁
解锁之后就可以发送交易。否则不可以发送交易。
实现一个具体的转账的Demo。效果图如下
具体实现代码如下:结合ganache使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>转账Demo</title>
<link rel="stylesheet" type="text/css" href="main.css">
<!--分割线-->
</head>
<!--html-->
<body>
<!--这里是展示智能合约2传来的数据-->
<div class="container">
<h1>转账 Demo</h1>
<h2 id="env"></h2>
<h2 id="account"></h2>
<label>源账户:</label>
<input type="text" id="fromAccount" value="">
<label>*目标账户:</label>
<input type="text" id="toAccount" value="">
<label>*转账金额(ether):</label>
<input type="text" id="amount" value="0.1">
<label>*Gas limit(gas):</label>
<input type="text" id=gaslimit value="21000">
<label>*Gas 价格(Gwei):</label>
<input type="text" id="gasprice" value="5">
<button onclick="sendTransaction()">发送:</button>
<div id="transactionResponse"></div>
</div>
<!--js代码-->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
</script>
<script>
// Our future code here..
//查看web3是否安装metamask
window.addEventListener('load',function(){
if(typeof web3!='undefined'){
web3=new Web3(web3.currentProvider);
if(web3.currentProvider.isMetaMast==true){
$("#env").html("MetaMask可用");
console.log("MetaMask可用");
}else{
$("#env").html("非MetaMask可用");
console.log("非MetaMask可用");
}
}else{
$("#env").html("No web3? 需要安装 Metamask!");
}
});
//查看钱包是否解锁
web3.eth.getAccounts(function(err,accounts){
if(accounts.length==0){
$("#account").html("请检查钱包是否解锁");
console.log("请检查钱包是否解锁");
}else{
$("#account").html("钱包已经解锁");
console.log("钱包已经解锁");
}
});
//发送转账
function sendTransaction(){
var fromAccount=$('#fromAccount').val();
var toAccount=$('#toAccount').val();
var amount=$('#amount').val();
var gas=$('#gaslimit').val();
var gasprice=$('#gasprice').val();
//判断输入的信息合法有效
if(web3.isAddress(fromAccount) && web3.isAddress(toAccount) && amount != null
&& amount.length>0 && gas!=null && gas.length>0 && gasprice!=null && gasprice.length>0
){
//Example2 :使用默认账户
// web3.eth.defaultAccount=fromAccount;
var message={from:fromAccount,to:toAccount,value:web3.toWei(amount,'ether')};
console.log(message);
web3.eth.sendTransaction(message,(err,res)=>{
var output=""
if(!err){
output+=res;
}else{
output="error";
}
document.getElementById('transactionResponse').innerHTML="Transaction response= " +output +"
";
});
}
}
</script>
</body>
</html>
略修改了一下视频代码:1.让当前登陆账户展示。2.fromAccount为当前登陆账户,转账时fromAccount为当前登陆账户,无需在输入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>转账Demo</title>
<link rel="stylesheet" type="text/css" href="main.css">
<!--分割线-->
</head>
<!--html-->
<body>
<!--这里是展示智能合约2传来的数据-->
<div class="container">
<h1>转账 Demo</h1>
<h3 id="env"></h3>
<h3 id="account"></h3>
<label>当前账户:</label>
<h3 id="fromAccount" ></h3>
<label>*目标账户地址:</label>
<input type="text" id="toAccount" value="">
<label>*转账金额(ether):</label>
<input type="text" id="amount" value="0.1">
<label>*Gas limit(gas):</label>
<input type="text" id=gaslimit value="21000">
<label>*Gas 价格(Gwei):</label>
<input type="text" id="gasprice" value="5">
<button onclick="sendTransaction()">发送:</button>
<div id="transactionResponse"></div>
</div>
<!--js代码-->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
</script>
<script>
// Our future code here..
//查看web3是否安装metamask
window.addEventListener('load',function(){
if(typeof web3!='undefined'){
web3=new Web3(web3.currentProvider);
if(web3.currentProvider.isMetaMast==true){
$("#env").html("MetaMask可用");
console.log("MetaMask可用");
}else{
$("#env").html("非MetaMask可用");
console.log("非MetaMask可用");
}
}else{
$("#env").html("No web3? 需要安装 Metamask!");
}
});
//查看钱包是否解锁
web3.eth.getAccounts(function(err,accounts){
if(accounts.length==0){
$("#account").html("请检查钱包是否解锁");
console.log("请检查钱包是否解锁");
}else{
$("#account").html("钱包已经解锁");
console.log("钱包已经解锁");
}
});
//查看当前账户及余额
var accounts=web3.eth.accounts;
web3.eth.getAccounts(function callback1(error,result){
console.log("result[0]"+result[0]);
$("#fromAccount").html(result[0]);
// web3.eth.getBalance(result[0],function callback2(err2,value){
// test=web3.fromWei(value, 'ether');
// console.log("value="+test);
// });
});
//发送转账
function sendTransaction(){
fromAccount=web3.eth.defaultAccount;
var toAccount=$('#toAccount').val();
var amount=$('#amount').val();
var gas=$('#gaslimit').val();
var gasprice=$('#gasprice').val();
//判断输入的信息合法有效
if(web3.isAddress(fromAccount) && web3.isAddress(toAccount) && amount != null
&& amount.length>0 && gas!=null && gas.length>0 && gasprice!=null && gasprice.length>0
){
//Example2 :使用默认账户
var message={from:fromAccount,to:toAccount,value:web3.toWei(amount,'ether')};
console.log(message);
web3.eth.sendTransaction(message,(err,res)=>{
var output=""
if(!err){
output+=res;
}else{
output="error";
}
document.getElementById('transactionResponse').innerHTML="Transaction response= " +output +"
";
});
}
}
</script>
</body>
</html>
3.合约部署,加载合约
合约相关的主要调用代码就是这个
主要示例代码:
之后可以通过info.functionname去调用合约的函数。这个我们再做第一个Dapp 的Demo就了解过这个。
如果调用的是只返回值view类型的function我们可以用.call。如果需要传值进去就用sendTransaction。
具体来说。我们第一个Demo展示名字年龄:info.getInfo.call(function(error,result){})
如果是传入名字年龄则用info.setInfo.sendTransaction(KaTeX parse error: Expected 'EOF', got '#' at position 3: ("#̲"name).val(),("#"age).val(),{gas:220000}
,function(error,result) 可以自己设置需要的gas费,需要注意的是我们有一个要求最低大于210000
但是这里需要我们手动再代码那填写合约代码。我们也可以设置自动编译**(第二十课。字节码在哪看?暂时没找到,回头再搞)**
这节课主要是讲如何监听合约事件,个人认为非常重要且有帮助。事件是合约和外部交流的一个接口,因为在调用合约的时候都是异步执行的。这意味着,我们在调用一个函数时是没办法拿到结果的。如果我们想要拿到结果就得用到事件日志。
具体代码展示:
合约代码如下
pragma solidity ^0.4.26;
contract InfoContract {
string Name;
uint age;
string content;
event Instructor(
string name,
uint age
);
function setInfo(string _Name, uint _age) public {
Name = _Name;
age = _age;
emit Instructor(_Name, _age);
}
function getInfo() public view returns (string,uint) {
return (Name,age);
}
}
针对这个合约的Instructor事件我们拿到监听的结果的方法。
1.var infoContract = web3.eth.contract(abi)abi为函数的abi码
2. var info= infoContract.at(合约地址)
3. 调用监听事件
var infoEvent=info.Instructor();
infoEvent.watch(function(error,result){
if(!error){
$("#loader").hide();
$("#info").html(result.args.name+'('+result.args.age+')years old');
}else{
$("#loader").hide();
$("#info").html('Error'+error);
}
});
需要特别注意的是1.监听用watch 2.取值不是直接用result。而是result.args.监听对象名称。
1.web3.js有两个版本1.0和2.0.我们默认的是2.0版本。1.0还是测试版本
2.web3.js调用大部分是异步的,我们需要通过回调拿到结果
3.如果我们用了metamask。metamask要用站点的方式访问,也就是要用服务器。方法有好几种,前面有提到。目前我是用node,npm run dev启动。
4.多看文档