Truffle之合约交互帮你解决了麻烦,使得编写合约交互程序轻便简单

合约交互

介绍

如果你自己编写原生以太坊网络请求去实现合约交互, 那么,很快你会意识编写这样的请求是繁重与不便的,同样,你会发现管理你创建请求的每个状态是很复杂的.幸运的是, Truffle帮你解决了这些麻烦,使得编写合约交互程序轻便简单.

读写数据

在太坊网络中,数据写入网络与数据读出网络是有区别的, 这种区别在你编写程序时,影响较大,写数据操作叫作transaction ,然而读取数据叫做call. Transactions处理方式很不同,特征如下.

TRANSACTIONS交易

交易本质上会改变网络的状态.交易可以像发送Ether到另一个账户一样简单,也可以像执行合约函数或添加新合约到网络节点中一样复杂.交易的本质定义是它写入(或者改变)数据.交易需要花费Ether以运行, 俗称"gas", 而且执行交易也需要时间.当你通过交易执行合约函数时, 你不可以接受到函数的返回值,因为交易并不会马上执行完. 一般来说, 通过交易执行的函数不返回值; 而是返回一个交易号. 所以总的来说, 交易特性如下:

燃料消耗(Ether)修改网络状态非即时执行完成无返回值(而是返回交易编号).

CALLS调用

另一方面, Calls是非常不同的. Calls可以执行网络上的代码, 不会有数据被永久修改. Calls是免费运行的,本质特性是读取数据. 如果你通过call执行一个合约函数,会立马得到返回值,总的来说,calls特性如下:

Are free (do not cost gas)免费无燃料费Do not change the state of the network不修改网络状态Are processed immediately立即执行Will expose a return value (hooray!)有返回值

如何选择transaction还是call取决于你是想读数据,还是写数据.

抽象介绍

合约抽象是Javascript式合约交互的根本,简单的说,合约抽象是一种代码封装,使得合约交互更加简单,这样你不用太关注底层的引擎和传动装置.Truffle通过 truffle-contract 组件实现自有的合约抽象,就像下面描述的合约抽象.

为了感谢合约抽象的有益作用, 不管怎样, 首先我们需要一份合约来进行讲义。我们用可用的MetaCoin合约来向您讲述,Truffle Boxes 命令行如truffle unbox metacoin.

pragma solidity ^0.4.2;


 

import"./ConvertLib.sol";


 

// This is just a simple example of a coin-like contract.


// It is not standards compatible and cannot be expected to talk to other


// coin/token contracts. If you want to create a standards-compliant


// token, see: https://github.com/ConsenSys/Tokens. Cheers!


 

contract MetaCoin {


mapping (address => uint) balances;


 

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


 

functionMetaCoin(){


balances[tx.origin]=10000;


}


 

functionsendCoin(address receiver, uint amount)returns(bool sufficient){


if(balances[msg.sender]< amount)returnfalse;


balances[msg.sender]-= amount;


balances[receiver]+= amount;


Transfer(msg.sender, receiver, amount);


returntrue;


}


 

functiongetBalanceInEth(address addr)returns(uint){


return ConvertLib.convert(getBalance(addr),2);


}


 

functiongetBalance(address addr)returns(uint){


return balances[addr];


}


}


 

除了构造函数,这份合约有三个方法(sendCoin, getBalanceInEth, 和getBalance). 所有的这三个方法即可以被当作transaction执行,也可以被当作call执行。

现在我们来看看Truffle为我们提供的,俗称MetaCoin的Javascript对象,在Truffle console中可有效执行

// Print the deployed version of MetaCoin.


// Note that getting the deployed version requires a promise, hence the .then.


MetaCoin.deployed().then(function(instance){


console.log(instance);


});


 

// outputs:


//


// Contract


// - address: "0xa9f441a487754e6b27ba044a5a8eb2eec77f6b92"


// - allEvents: ()


// - getBalance: ()


// - getBalanceInEth: ()


// - sendCoin: ()


// ...


请注意,抽象化包括了合约内完全相同的函数.同样包括了一个指向已部署的MetaCoin合约的地址.

执行合约函数

通过abstraction你可以在以太坊网络上很容易地执行合约函数.

发起一笔交易TRANSACTIONS

在MetaCoin有三个可以执行的函数. 如果分析其中的一个函数, 会发现只有sendCoin方法会修改网络数据. sendCoin的目的是从一个账户发送Meta coins到另一个账户,而这些操作将会被持久化.

当调用sendCoin, 我们把它当成交易执行. 在下面的例子中, 我们从一个账户发送10 个Meta coin到另一个账户, 作为网络持久化的一种方式:

var account_one ="0x1234...";// an address


var account_two ="0xabcd...";// another address


 

var meta;


MetaCoin.deployed().then(function(instance){


meta = instance;


return meta.sendCoin(account_two,10,{from: account_one});


}).then(function(result){


// If this callback is called, the transaction was successfully processed.


alert("Transaction successful!")


}).catch(function(e){


// There was an error! Handle it.


})


以上代码有一些有趣的地方:

我们可以直接调用抽象的sendCoin函数. 这将默认导致,函数是以交易的方式而不是调用的方式被执行.当交易成功,回调函数直到交易被执行完才被处理.这样会轻松一些,也意味着你不必亲自检查交易的状态.传递一个对象参数作为第三个参数到函数sendCoin. 请注意,在Solidity contract合约中的sendCoin 函数并没有第三个参数.上面看到的是一个可以被传递到函数的最后一个参数的特别对象,这个参数可以让你编码交易的具体描述. 这里我们设置from 地址,确保交易从account_one发起.

发起一个调用CALL

继续MetaCoin这个例子, 注意函数getBalance对于网络数据读取是一个经常性操作. 不会引起数据修改, 仅仅是返回指定该地址上的MetaCoin 余额. 我们接下来试一下:

var account_one ="0x1234...";// an address


 

var meta;


MetaCoin.deployed().then(function(instance){


meta = instance;


return meta.getBalance.call(account_one,{from: account_one});


}).then(function(balance){


// If this callback is called, the call was successfully executed.


// Note that this returns immediately without any waiting.


// Let's print the return value.


console.log(balance.toNumber());


}).catch(function(e){


// There was an error! Handle it.


})


这里有意思的是:

我们必须执行.call() 显示调用,以便以太坊网络明确知道我们并不打算引起任何修改性操作.当执行成功时,我们接受到一个返回值,而不是一个交易的编号.以太坊网络可以处理极大的数字,所以我们用BigNumber来处理这个数字 文章导读: 如果你自己编写原生以太坊网络请求去实现合约交互, 那么,很快你会意识编写这样的请求是繁重与不便的,同样, 你会发现管理你创建请求的每个状态是很复杂的.幸运的是, Truffle帮你解决了这些麻烦,使得编写合约交互程序轻便简单

本文由 区块链技术网 作者:答案 发表,其版权均为 区块链技术网 所有,文章内容系作者个人观点,不代表 区块链技术网 对观点赞同或支持。如需转载,请注明文章来源。

发表评论