truffle-contract调用合约

truffle-contract与合约交互

truffle-contract也是个用来与以太坊智能合约交互的JavaScript库,相对于web3.js来说更加方便一点。
文章转自:
http://dophin459.coding.me/posts/79b3ba3d/
https://blog.csdn.net/DDFFR/article/details/73772690

truffle-contract具有以下特色:
  • 同步的交易:可以确保在交易生效之后再继续执行其他操作
  • 返回Promise:每个封装的合约函数会返回Promise,可以对它进行.then操作,避免了回调地狱(callback hell)问题
  • 为交易提供了默认参数:例如from或gas
  • 为每个同步的交易返回logs、交易receipt和交易hash
使用truffle-contract需要安装
  • web3
  • truffle-contract
truffle-contract调用合约

1、调用合约之前,先部署一个简单合约,可参考下面简单的demo。

pragma solidity ^0.4.16;
contract MetaCoin {
	mapping (address => uint) balances;
	event Transfer(address indexed _from, address indexed _to, uint256 _value);
	function MetaCoin() {
		balances[tx.origin] = 10000;
	}
	function sendCoin(address receiver, uint amount) returns(bool sufficient) {
		if (balances[msg.sender] < amount) return false;
		balances[msg.sender] -= amount;
		balances[receiver] += amount;
		Transfer(msg.sender, receiver, amount);
		return true;
	}
	function getBalance(address addr) returns(uint) {
		return balances[addr];
	}
}

2、把合约部署到以太坊网络上得到合约地址和交易地址(暂时用不到),可参考

Contract mined! 
address: 0x75c35c980c0d37ef46df04d31a140b65503c0eed 
transactionHash: 0x66a19b078e5b4b80ba082e0e1d17ceff42a597e4e4e8e60d2ada9f7b5cd09143
初始化合约对象

与web3.js类似,要使用truffle-contract,需要先初始化合约对象,然后连接到一个以太坊节点。在自己的工程新建一个js文件,输入以下代码

//引用web3
var Web3 = require("web3");
//引用truffle-contract
var contract = require("truffle-contract");
// 合约ABI 合约ABI在你的编译JSON文件里面有的
var contract_abi = [{"constant":false,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"addmath","outputs":[{"name":"c","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"}];
// 通过ABI初始化合约对象
var MetaCoin = contract({
    abi: contract_abi
});
// 连接到以太坊节点
var provider = new Web3.providers.HttpProvider("http://localhost:8545");
MetaCoin.setProvider(provider);

接下来,可以使用MetaCoin的以下三个函数:

  • at(contract_address):通过指定的合约地址获取MetaCoin合约实例
  • deployed():通过默认的合约地址获取MetaCoin合约实例
  • new():部署新的合约,并且获取新部署的合约实例

因为我们的合约已经部署好了,这里就用at的方式获取合约的实例,来调用合约啦,其他两种待研究。参考代码
调用合约函数

// 账户地址
var account_one = "0x68b73956d704007514e9257813bdc58cdf3c969a";
// 合约地址
var contract_address = "0xb2cdd356e58280906ce53e1665697b50f88aac56";
MetaCoin.at(contract_address).then(function(instance){
    return instance.getBalance.call(account_one);
}).then(function(balance){
    console.log(balance.toNumber());
}).catch(function(err){
    console.log(err);
});

首先通过MetaCoin.at()获取合约实例,在.then链式调用中,回调函数会在参数中获取到合约实例instance,接下来就可以在回调函数中使用合约实例来调用getBalance函数,再继续通过.then链式调用,通过回调函数获得getBalance的返回值balance。

再来看看调用sendCoin函数的情况:

// 账户地址
var account_one = "0x68b73956d704007514e9257813bdc58cdf3c969a";
var account_two = "0x9c3c1a2f5ef913fac44f0348a78f68d835f3f26e";
// 合约地址
var contract_address = "0xb2cdd356e58280906ce53e1665697b50f88aac56";
MetaCoin.at(contract_address).then(function(instance){
    // 调用sendCoin会向区块链发送一笔交易
    return instance.sendCoin(account_two, 100, {from:account_one});
}).then(function(result){
    // 这个回调函数在交易生效之后才会被执行
    // result对象包含以下三个字段:
    // result.tx      => 交易hash,是一个string
    // result.receipt => 交易执行结果,是一个对象
    // result.logs    => 交易产生的事件集合,是一个对象数组
    console.log(result);
}).catch(function(err){
    console.log(err);
});

这里,调用sendCoin会向区块链发送一笔交易,在交易生效之后,才会执行回调函数,回调函数的参数中包含了交易hash、交易执行结果以及交易产生的事件。
捕获事件
可以通过result.logs获取交易触发的事件:

// 账户地址
var account_one = "0x68b73956d704007514e9257813bdc58cdf3c969a";
var account_two = "0x9c3c1a2f5ef913fac44f0348a78f68d835f3f26e";
// 合约地址
var contract_address = "0xb2cdd356e58280906ce53e1665697b50f88aac56";
MetaCoin.at(contract_address).then(function(instance){
    // 调用sendCoin会向区块链发送一笔交易
    return instance.sendCoin(account_two, 100, {from:account_one});
}).then(function(result){
    // 这个回调函数在交易生效之后才会被执行
    // result.logs是一个数组,数组的每个元素是一个事件对象
    // 通过查询result.logs可以获得感兴趣的事件
    for (var i = 0; i < result.logs.length; i++) {
        var log = result.logs[i];
        if (log.event == "Transfer") {
            console.log("from:", log.args._from);
            console.log("to:", log.args._to);
            console.log("amount:", log.args._value.toNumber());
            break;
        }
    }
}).catch(function(err){
    console.log(err);
});
// 输出:
from: 0x68b73956d704007514e9257813bdc58cdf3c969a
to: 0x9c3c1a2f5ef913fac44f0348a78f68d835f3f26e
amount: 100

sendCoin执行完后会触发一个Transfer事件,在回调函数中,通过查询result.logs可以获取到这个事件,进而可以得到事件的参数值。

一个完整的例子

下面是一个完整的例子:

var Web3 = require("web3");
var contract = require("truffle-contract");
// 合约ABI
var contract_abi = [{ "constant": false, "inputs": [{ "name": "receiver", "type": "address" }, { "name": "amount", "type": "uint256" }], "name": "sendCoin", "outputs": [{ "name": "sufficient", "type": "bool" }], "payable": false, "type": "function" }, { "constant": false, "inputs": [{ "name": "addr", "type": "address" }], "name": "getBalance", "outputs": [{ "name": "", "type": "uint256" }], "payable": false, "type": "function" }, { "inputs": [], "payable": false, "type": "constructor" }, { "anonymous": false, "inputs": [{ "indexed": true, "name": "_from", "type": "address" }, { "indexed": true, "name": "_to", "type": "address" }, { "indexed": false, "name": "_value", "type": "uint256" }], "name": "Transfer", "type": "event" }];
// 通过ABI初始化合约对象
var MetaCoin = contract({
    abi: contract_abi
});
// 连接到以太坊节点
var provider = new Web3.providers.HttpProvider("http://localhost:8545");
MetaCoin.setProvider(provider);
// 账户地址
var account_one = "0x68b73956d704007514e9257813bdc58cdf3c969a";
var account_two = "0x9c3c1a2f5ef913fac44f0348a78f68d835f3f26e";
// 合约地址
var contract_address = "0xb2cdd356e58280906ce53e1665697b50f88aac56";
var coin;
MetaCoin.at(contract_address).then(function(instance){
    coin = instance;
    // 首先查看账户二的余额
    return coin.getBalance.call(account_two);
}).then(function(balance_of_account_two){
    console.log("Balance of account two is", balance_of_account_two.toNumber());
    // 从账户一向账户二转100个币
    return coin.sendCoin(account_two, 100, {from:account_one});
}).then(function(result){
    console.log("Sent 100 coin from account one to account two.");
    // 再次查看账户二的余额
    return coin.getBalance.call(account_two);
}).then(function(balance_of_account_two){
    console.log("Balance of account two is", balance_of_account_two.toNumber());
}).catch(function(err){
    console.log("Error:", err.message);
});
// 输出
Balance of account two is 3400
Sent 100 coin from account one to account two.
Balance of account two is 3500
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值