纸上得来终觉浅,绝知此事要躬行。
古训不虚,且慢道来
缘起:以太坊智能合约开发第七篇:智能合约与网页交互
场景:很简单的一个输入文本,服务端给拼接后返回到前端表单
如果下使用truffle,要首先在项目目录执行 truffle unbox webpack
即可获得一个项目模板,形如:
truffle-config.js 里需要修改
取消注释,并修改网络参数,如果本地测试,可以用ganache,桌面版即可,我遇到的问题是metamask不允许用默认的5777网络ID,而是提示1337,索性我就改ganache NETWORKID为1337,端口也遇到问题(好像是有的库里写死了7545),ganache端口也改为7545好了,点save保存。
Migrate/下的2_deploy_contracts.js修改为:
//artifacts对象为truffle框架提供
//artifacts.require()方法与Node中的require()方法类似
//编译合约代码。自动调用solc编译器来编译合约代码并返回编译结果对象
//var stringsContract = artifacts.require("./strings.sol");
var HelloContract = artifacts.require("./Hello.sol");
//部署器对象deployer为truffle框架提供
module.exports = function(deployer) {
//部署string.sol合约
//deployer.deploy(stringsContract);
//将已部署的strings合约类库连接到Hello合约
//deployer.link(stringsContract, HelloContract);
//部署Hello.sol合约
deployer.deploy(HelloContract);
};
contracts/ 下的
删除,保留迁移合约的Migrateions.sol合约
新建Hello.sol合约:
//pragma关键字:版本申明。
//用来指示编译器将代码编译成特定版本,以免引起兼容性问题
//此处不支持0.4.0之前的编译器,也不支持0.5.0之后的编译器(条件为 ^)
pragma solidity ^0.5.16;
//contract关键字:合约申明
//和Java、PHP中的class类似
//此处是申明一个名为Hello的合约
contract Hello {
//public: 函数访问属性(后续文章为详细阐述)
//returns (string): 定义返回值类型为string
function say(string memory name) public returns (string memory) {
return stringAdd('你好:',name);
}
function stringAdd(string memory a, string memory b) public returns(string memory ){
bytes memory _a = bytes(a);
bytes memory _b = bytes(b);
bytes memory res = new bytes(_a.length + _b.length);
for(uint i = 0;i < _a.length;i++)
res[i] = _a[i];
for(uint j = 0;j < _b.length;j++)
res[_a.length+j] = _b[j];
return string(res);
}
}
function say(string memory name) public returns (string memory)里的memory时候来加上的,是5的新要求吧,stringAdd()是我新加的函数,为了拼接字符串(坑吧,一门语言不提供字符串拼接函数),那个public是加上去的,不加出错。
打开ganache,它提供了一条摸你的区块链节点,
在项目/目录下运行
truffle compile 来编译合约
truffle migrate 来部署合约到ganache
T:\DApp\HelloWorld>truffle compile
Compiling your contracts...
===========================
> Compiling .\contracts\Hello.sol
> Compiling .\contracts\Migrations.sol
> Compilation warnings encountered:
project:/contracts/Hello.sol:17:2: Warning: Function state mutability can be restricted to pure
function stringAdd(string memory a, string memory b) public returns(string memory ){
^ (Relevant source part starts here and spans across multiple lines).
> Artifacts written to T:\DApp\HelloWorld\build\contracts
> Compiled successfully using:
- solc: 0.5.16+commit.9c3226ce.Emscripten.clang
T:\DApp\HelloWorld>truffle migrate
Compiling your contracts...
===========================
> Compiling .\contracts\Hello.sol
> Compiling .\contracts\Migrations.sol
> Compilation warnings encountered:
project:/contracts/Hello.sol:17:2: Warning: Function state mutability can be restricted to pure
function stringAdd(string memory a, string memory b) public returns(string memory ){
^ (Relevant source part starts here and spans across multiple lines).
> Artifacts written to T:\DApp\HelloWorld\build\contracts
> Compiled successfully using:
- solc: 0.5.16+commit.9c3226ce.Emscripten.clang
Starting migrations...
======================
> Network name: 'development'
> Network id: 1337
> Block gas limit: 6721975 (0x6691b7)
1_initial_migration.js
======================
Deploying 'Migrations'
----------------------
> transaction hash: 0x05e6ce1ec4e9fa59f4e2dbb7ad85eb79b5e58651b53acc3f71bcb77934f12a65
> Blocks: 0 Seconds: 0
> contract address: 0xb001f23d72EEc02F9221D2E3c1A42883ce060F87
> block number: 5
> block timestamp: 1630729607
> account: 0x1a51cbF93B2C2989Ae775748a3A8573d805f9254
> balance: 99.9855462
> gas used: 164175 (0x2814f)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.0032835 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.0032835 ETH
2_deploy_contracts.js
=====================
Deploying 'Hello'
-----------------
> transaction hash: 0x6dc0b39042f0867955824db54525868e004fbdde374146ab76f4f1f705e506fa
> Blocks: 0 Seconds: 0
> contract address: 0x3CA101b8B7BCC5722B7a16AaEe1A7065bf2C895D
> block number: 7
> block timestamp: 1630729608
> account: 0x1a51cbF93B2C2989Ae775748a3A8573d805f9254
> balance: 99.97820334
> gas used: 324802 (0x4f4c2)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.00649604 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.00649604 ETH
Summary
=======
> Total deployments: 2
> Final cost: 0.00977954 ETH
WEB:
?app/下结构如下
app/src/结构
?其中index.html代码:
<!DOCTYPE html>
<html>
<head>
<title>Hello - Truffle</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- 可选的 Bootstrap 主题文件(一般不用引入) -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="./index.js"></script>
</head>
<style>
input {
display: block;
margin-bottom: 12px;
}
</style>
<body>
<div class="alert alert-success" role="alert" style="display:none;" id="message-box"></div>
<div class="form-group">
<input type="text" class="form-control" id="username" aria-describedby="basic-addon1">
</div>
<button type="submit" id="submit" class="btn btn-success">调用合约</button>
<button type="submit" id="cancel" class="btn btn-default">重置</button>
<script>
$(document).ready(function(){
$('#submit').on('click', function(){
var username = $('#username').val();
if(typeof username == 'undefined' || username == false){
alert('不能为空');
}else {
//调用App的say()方法
window.App.say(username, function (err, result) {
if(err){
alert(err);
}else {
$('#username').val(username);
$('#message-box').html(result);
$('#message-box').show();
}
});
}
});
$('#cancel').on('click', function(){
$('#username').val('');
$('#message-box').hide();
$('#message-box').html('');
});
});
</script>
</body>
</html>
?index.js:
//导入CSS
//import "../css/app.css";
//导入web3和truffle-contract库
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'
//导入Hello合约的ABI文件
import Hello_artifacts from '../../build/contracts/Hello.json'
//获取Hello合约对象
var HelloContract = contract(Hello_artifacts);
window.App = {
init: function() {
//设置web3连接
HelloContract.setProvider(web3.currentProvider);
},
//封装合约中的say()方法调用过程,供javascript调用
say: function(name, callback){
//instance为Hello合约部署实例
HelloContract.deployed().then(function(instance){
//调用Hello合约中的say()方法,并传入参数name
instance.say.call(name).then(function(result){
//将返回结果传入回调函数
callback(null, result);
});
}).catch(function(e){
console.log(e, null);
});
}
};
window.addEventListener('load', function() {
//设置web3连接 http://127.0.0.1:7545 为Ganache提供的节点链接
window.web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:7545"));
App.init();
});
在app/下npm run dev的时候遇到dev缺失字样,原来是package.json里没有想改内容,对照完善
{
"name": "app",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"build": "webpack",
"dev": "webpack-dev-server"
},
"devDependencies": {
"copy-webpack-plugin": "^5.0.5",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.9.0"
},
"dependencies": {
"truffle-contract": "^4.0.31",
"web3": "^1.2.4"
}
}
中间还遇到过需要在app/ 运行 npm install --save truffle-contract的事
(我一开始没用truffle生成模板,是手工拼凑项目,所有出了很多弯路)
总体顺序:
mkdir test //重新建一个项目目录test
truffle unbox webpack
truffle develop // 启动一个控制台
> compile //编译
>migrate //迁移合约 当然这两部也可以不在控制台下完成 可以用 truffle compile 和 truffle migrate 完成。
npm run dev //运行webpack服务器进行前端热重新加载(在开发控制台之外)。
|