通过web3.js与以太坊智能合约交互

JouyPub

  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 web3@1.0.0-beta.36 --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直接在项目中编译合约,方便查看编译后的结果

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
阅读 4.2k

jouypub.com
聊聊区块链,大数据,后端开发,前端开发

聊聊区块链、大数据、应用开发

522 声望
159 粉丝
0 条评论

聊聊区块链、大数据、应用开发

522 声望
159 粉丝
宣传栏