通过web3.js与以太坊智能合约交互
web3.js是以太坊提供的一个NodeJs库,封装了一些和以太坊交互的常用对象、函数。主要包括版本、账号、交易、合约等信息的获取和调用。本文主要介绍通过web3.js调用及执行智能合约
准备工作:
安装node,npm,这里就不介绍了
本文中使用的私有链是Ganache,它是可视化私有链,前身就是大名鼎鼎的testRPC。更重要的是只有在产生交易时它才会挖矿,很适合用来测试智能合约。
1、新建项目
由于web3.js 1.x 和 0.x版本api不同,尽管web3.js的1.0 release还没出来,这里仍然选用1.0 beta版本演示,方便后续学习
> mkdir demo && cd demo > npm init > npm install [email protected] --save > npm install solc --save
2、创建合约
在项目下新建MetaCoin.sol,把以下内容复制到文件中。该合约内容是使用truffle初始化项目(truffle unbox metacoin
)后生成的。
pragma solidity ^0.4.24; contract MetaCoin { mapping(address => uint) balances; event Transfer(address indexed _from, address indexed _to, uint256 _value); constructor() public { balances[tx.origin] = 10000; } function sendCoin(address receiver, uint amount) public returns (bool sufficient) { if (balances[msg.sender] < amount) return false; balances[msg.sender] -= amount; balances[receiver] += amount; emit Transfer(msg.sender, receiver, amount); return true; } function getBalance(address addr) public view returns (uint) { return balances[addr]; } }
3、编译合约
web3.js 1.0版本移除了compile方法,所以web3.eth.compile.solidity(source)
已经不能用了。如果需要编译合约有两种方式
- 使用
solc
- 在网页上编译 https://remix.ethereum.org
本文使用solc直接在项目中编译合约,方便查看编译后的结果
const fs = require('fs'); const Web3 = require("web3"); const solc = require('solc'); const data = fs.readFileSync('./MetaCoin.sol'); // console.log(data.toString()) const web3 = new Web3(); // Ganache默认端口7545 web3.setProvider(new Web3.providers.HttpProvider("http://localhost:7545")); // 1 是优化器参数 const output = solc.compile(data.toString(), 1); // console.log(output) const bytecode = output.contracts[':MetaCoin'].bytecode; const abi = output.contracts[':MetaCoin'].interface;
4、部署合约
// 第一个参数:合约的abi对象 new web3.eth.Contract(JSON.parse(abi), { // 必填,合约发起者 from: '0x75441ac9a1d2DaAA5638beae207546c8D14a7f6d', // 合约bytecode,也可也在deploy中传入 data: bytecode, // 即gas limit,该交易最大可使用的Gas gas: 4712388, gasPrice: '1000000' }).deploy().send().then((instance) => { // console.log(instance) // 合约地址 // console.log(`Address: ${instance.options.address}`); //执行合约,只是查询状态,不需要挖矿,所以调用call方法 instance.methods.getBalance('0x75441ac9a1d2DaAA5638beae207546c8D14a7f6d').call({ //非必填,该合约方法的调用者 from: '0x6cc022FAE89414146b2A2646ca5143e23dA5b7e7' }, function (error, result) { console.log('error:' + error) console.log('result:' + result) }) })
其中要注意的是:web3.js 1.0版本和0.x版本获取账号的方法不一样,如下web3.eth.accounts[0]
web3.js 0.x版本中的方法web3.eth.getAccounts().then(function (value) { console.log(value[0]) })
web3.js 1.0版本中的方法
5、调用已经部署过的合约,执行合约方法
// 相对于部署合约,多了第二个参数,即合约地址 const metaCoinContract = new web3.eth.Contract(JSON.parse(abi), '0x83A87C3DC9CD2146e29D8aCFb7470Bc86d8bFf28', { // 非必填,合约的bytecode data: bytecode, // 非必填,合约的创建者 from: '0x906210387ADC119767900692fA5E59417C809642', //Gas limit gas: 4712388, gasPrice: '1000000' }); // 调用合约中的sendCoin方法 metaCoinContract.methods.sendCoin('0x84d939AD8034c3ce2A7D4D100b939d4523b9E46E', 100).send({ //非必填,该合约方法的调用者 from: '0x75441ac9a1d2DaAA5638beae207546c8D14a7f6d' }).on('transactionHash', function (hash) { console.log(hash) }).on('receipt', function (receipt) { console.log(receipt) }).on('confirmation', function (confirmationNumber, receipt) { console.log(confirmationNumber) }).on('error', console.error) // 调用合约中的getBalance方法 metaCoinContract.methods.getBalance('0x75441ac9a1d2DaAA5638beae207546c8D14a7f6d').call({ //非必填,该合约方法的调用者 from: '0x6cc022FAE89414146b2A2646ca5143e23dA5b7e7' }, function (error, result) { console.log('error:' + error) console.log('result:' + result) })
欢迎订阅「K叔区块链」 - 专注于区块链技术学习
博客地址:http://www.jouypub.com
简书主页:https://www.jianshu.com/u/756c9c8ae984
segmentfault主页:https://segmentfault.com/blog/jouypub
腾讯云主页:https://cloud.tencent.com/developer/column/72548