以太坊开发实战:通过truffle-contract与智能合约交互

与以太坊的智能合约交互,除了使用web3.js,还可以使用另外一个Javascript库,就是truffle-contract。truffle-contract对以太坊的智能合约做了更好的抽象,相比于web3.js,使用truffle-contract操作智能合约更加方便。

truffle-contract具有以下特色:

  • 同步的交易:可以确保在交易生效之后再继续执行其他操作
  • 返回Promise:每个封装的合约函数会返回Promise,可以对它进行.then操作,避免了回调地狱(callback hell)问题
  • 为交易提供了默认参数:例如fromgas
  • 为每个同步的交易返回logs、交易receipt和交易hash

下面介绍如何在应用中使用truffle-contract与智能合约交互。

  • Ubuntu 16.04 64位
  • nodejs 6.10.0
  • npm 3.10.10

示例合约

还是以上一篇文章中的MetaCoin合约为例,确保启动了一个以太坊节点,并且已将下面的MetaCoin合约部署到节点中。

pragma solidity ^0.4.2;

contract MetaCoin {

mapping (address => uint) balances;

event Transfer(address indexed _from, address indexed _to, uint256 _value);

function () {

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];

}

}

接下来就可以按照下面的步骤在项目中通过truffle-contract来使用这个合约。

安装truffle-contract

首先新建一个Nodejs项目并初始化:

$ mkdir truffle-contract-test && cd truffle-contract-test

$ npm init

接下来安装truffle-contract:

$ npm install web3 --save

$ npm install truffle-contract --save

:安装truffle-contract并不要求先安装web3,这里安装web3是因为后面会用到。

初始化合约对象

与web3.js类似,要使用truffle-contract,需要先初始化合约对象,然后连接到一个以太坊节点。在truffle-contract-test目录下新建index.js文件,在其中输入以下代码:

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

// 如果要部署合约,还要指定合约代码:

// unlinked_binary: ...

});

// 连接到以太坊节点

var provider = new Web3.providers.HttpProvider("http://localhost:8545");

MetaCoin.setProvider(provider);

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

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

调用合约函数

可以像下面这样调用getBalance函数:

// 改成你自己的账户地址

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

// 如果要部署合约,还要指定合约代码:

// unlinked_binary: ...

});

// 连接到以太坊节点

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

以太坊开发实战:通过truffle-contract与智能合约交互相关推荐

  1. solidity payable_以太坊区块链搭建与使用(五)-智能合约Solidity

    一.智能合约Solidity开发工具 1.remix-ide http://remix.ethereum.org/ 在线版本,也可以去github下载安装到本地.开发.编译.发布.执行.测试 2.re ...

  2. 【以太坊开发06】Truffle开发入门

    ⼀.什么是truffle 1. 概述 truffle是世界级的以太坊开发框架,它使得以太坊开发变得简单⾼效,它具有以下特点: 内置智能合约编译.链接.开发和⼆进制管理. 快速开发的⾃动化合约测试 脚本 ...

  3. 跟着cryptokitties(以太坊云养猫)学写智能合约(上)

    cryptokitties(以太坊云养猫)是近期出现在以太坊区块链上一个游戏.超级可爱的猫形象,再配合上繁殖,配种,拍卖这样丰富的玩法,一下子就引爆了以太坊的区块链.这款游戏的核心是基于以太坊的智能合 ...

  4. 带你玩转区块链--以太坊基础、发币、基于智能合约实现彩票项目-第二章-第一节【以太坊篇】

    意义: 在上一节知识学习中,我们已经了解如何实现一个基础区块链,并重构了BTC关键代码.对比传统的中心化项目,区块链项目拥有很多优势,如:追溯性.不可传篡改性.在中心化项目中的网络协议是:[数据层-- ...

  5. 代币转账_手把手教你从源代码开始搭建多节点以太坊私链(五)部署智能合约及代币发行...

    一.安装以太坊合约编译环境 安装solc 智能合约代码的编译可以通过第三方平台或者软件.不过,为了安全起见,还是搭建自己的编译器比较好.(But be aware that if the compil ...

  6. 【以太坊】在测试网络上发布智能合约

    一.准备工作 1.本地测试网络搭建完成,对以太坊的了解已经达到基础水平.(可以参考我之前的关于以太坊的文章). 2.有翻墙的能力(发布合约的时候,有不少网站都是需要翻墙操作的) 3.本地浏览器安装Me ...

  7. 以太坊开发入门,完整入门篇(小白可以看看,高手看看自己有没有遗漏的

    2019独角兽企业重金招聘Python工程师标准>>> 翻译自:https://medium.com/@mattcondon/getting-up-to-speed-on-ether ...

  8. Web3与智能合约交互实战

    链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载. Web3与智能合约交互实战 以太坊中智能合约和web3交互实战 最近区块链.以太坊十分的火,所有就会有许多人去进入区块链 ...

  9. 以太坊开发------使用Truffle打造去中心化的宠物商店

    pet-shop Box项目地址:http://truffleframework.com/boxes/pet-shop pet-shop Box官方教程:http://truffleframework ...

最新文章

  1. C言语教程第五章:函数(1)
  2. 【Java源码分析】HashTable源码分析
  3. java的actionevent_[java]ActionEvent事件:获取输入字符串的长度
  4. Android Studio导入项目非常慢的解决办法
  5. 软件工程学习笔记(考试版)
  6. centos 7 firewalld 设置
  7. 优麒麟Ubuntu18.04.5安装各种问题
  8. 字符串处理类库_CharString
  9. 借贷记账思考2015.12.28
  10. webSSH如何安装?如何使用?解决Web端远程连接终端~~运维篇
  11. PLC调试中的四个步骤
  12. photoshop图片显示为索引,解决办法
  13. 神经网络参数初始化方法
  14. 【MineCraft】-- 如何开设我的世界服务器
  15. 【逗老师的无线电】Motorola DMR设备如何经由BM中心网络上报APRS位置信息
  16. 3ds max中的对象绕局部坐标系旋转的动画
  17. 我自己编写的一个tab
  18. npm删除项目所有依赖和清缓存清缓存的办法
  19. 【matlab】Matlab中产生正态分布随机数的函数normrnd
  20. 【JS】【掘金】看看你所关注的掘友值排行榜

热门文章

  1. 参考地、保护地、大地的概念
  2. 物联网技术的发展历史及关键技术
  3. php 画虚线,HTML5 Canvas绘制圆点虚线实例_html5教程技巧
  4. PHP不及格标红,php语言编写switch判断成绩代码。分别输出优秀、良好、中等、及格和不及格。...
  5. 计算机请说明您的专业知识与技能,湖南省2012对口招生考试计算机类专业综合考试大纲...
  6. oracle ora 00279,ORA-01245、ORA-01547错误的解决
  7. php连接plc,PLC 几种常见的连接口和通讯协议
  8. android 之适配器与json对象解析技术的联用的进一步优化(解决图片错位)
  9. win7驱动程序未经签名可以使用吗_如何解决高校机房计算机新CPU不支持win7系统的问题...
  10. Transformer用到3D点云分割