Truffle-Contract中间件
— Truffle-Contract安装&使用 —
— 连接 MetaMask钱包 —
truffle-contact
truffle-contact 是一个基于web3的链接网络中智能合约的JS中间组件,利用它可以方便调用合约
官方英文文档
安装/引入
安装:npm install truffle-contract
npm install web3
引入:1
2<script type="text/javascript" src="./path/to/web3.min.js"></script>
<script type="text/javascript" src="./dist/truffle-contract.min.js"></script>
链接至合约
1 | //1.新建一个web3驱动 |
你能使用MyContract
中的以下函数来连接至链:
at()
:创建一个MyContract实例在特定的位置deployed()
:创建一个MyContract实例在合约默认的位置new()
:部署一个此智能合约的新版本到网络,获取这个新的合约实例
合约抽象类
链接至链上合约,可以查看合约返给我们的合约抽象类
1
2
3
4
5
6
7
8
9
10
11
12
13
14// 注意用.then 使用回调函数
MetaCoin.deployed().then(function(instance) {
console.log(instance);
});
// 输出
//
// Contract
// - address: "0xa9f441a487754e6b27ba044a5a8eb2eec77f6b92"
// - allEvents: ()
// - getBalance: ()
// - getBalanceInEth: ()
// - sendCoin: ()
// ...
这里会有部署合约的地址,合约的函数等等内容,可以由此来调用合约中的函数
truffle-contract API
在说明如何调用合约之前,以MyContract
为例,详细说明truffle-contract自带的其他函数
MyContract.new([arg1, arg2, …], [tx params])
作用:将合约的一个新实例部署到网络中
输入参数:这个函数接受contract需要的任何参数。最后有一个可选参数,可传递交易参数,包括发起地址,gas限制,gas价格等。
返回:返回包含一个在新的地址部署的合约 的合约抽象类 的Promise
MyContract.at(address)
作用:从链上特定的地址上创建一个新的合约实例
输入参数:一个新的地址
返回:返回一个新的合约实例
MyContract.deployed()
作用:从默认地址创建一个新的合约实例。该默认地址是提供给truffle-contract的参数,对应对应的链
输入参数:一个新的地址
返回:返回一个新的合约实例
MyContract.link(instance)
作用:连接一个合约虚拟实例的库到MyContract。库必须已经被部署,并拥有部署地址。并且可以从该合约虚拟实例中推断出名称跟部署地址
输入参数:一个已经部署的合约虚拟实例
返回:在这个交易的结果中,报告所有合约虚拟实例库的事件?
MyContract.link(name, address)
MyContract.link(object)
此处不太明白link的作用,差不多是拷贝吧,当用到时,再补充说明
MyContract.networks()
作用:查看MyContract的已经设置为代表的网络id列表
返回:网络id列表
MyContract.setProvider(provider)
作用:设置MyContract将要使用的web3驱动
输入参数:web3的provider
MyContract.setNetwork(network_id)
作用:设置MyContract当前代表网络id
输入参数:网络id
MyContract.hasNetwork(network_id)
作用:判断MyContract是否连接上这个网络
输入参数:网络id
返回:返回布尔型;是/否
MyContract.defaults([new_defaults])
作用:为从MyContract创建的所有实例设置事务默认值
输入参数:设置的默认值
返回:没有输入参数时,返回当前事务默认值1
2
3
4
5
6
7//设置新的默认值
MyContract.defaults({
from: ...,
gas: ...,
gasPrice: ...,
value: ...
})
此处设置可以省略在调用智能合约时的每次指定from,gas等
MyContract.clone(network_id)
作用:从当前MyContract克隆一个合约虚拟实例到新的网络id(别忘了,之后指定新的provider)
输入参数:network_id
返回:一个新的合约虚拟实例1
var MyOtherContract = MyContract.clone(1337);
与合约中函数的交互
其中与合约函数交互有两种形式:transaction
和 call
以下为实例合约1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35pragma solidity ^0.4.18;
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);
//控制器,创建合约时运行
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 getBalanceInEth(address addr) public view returns(uint){
return ConvertLib.convert(getBalance(addr),2);
}
//获取代币函数
function getBalance(address addr) public view returns(uint) {
return balances[addr];
}
}
transaction 交易
真实的产生了一个交易,由矿工处理
- 消耗Gas
- 改变网络状态
- 不能立即处理
- 不会有返回值(只会有交易id)
1 | var account_one = "0x1234..."; // an address |
可以注意到实际我们传入了三个参数,但是在合约的定义中是没有第三个参数的。函数允许指定事务的细节,这里指定了from地址,确保交易是account_one发起的
如果在事务中执行的函数有一个返回值,那么您将不会在这个结果中获得返回值。您必须使用一个事件(event)并在日志数组中查找结果。之后详细说明
call
不会真实产生交易
- 免费(不消耗Gas)
- 不改变网络状态
- 立即处理
- 会有返回值
1 | var account_one = "0x1234..."; // an address |
注意以太坊网络可以处理非常大的数字,这里返回是一个BigNumber类型,我们转变为数字(我们是已知这里的数字比较小,如果超出最大整型范围,转变会出错)
捕捉事件
在合约中使用event
触发事件,在 transaction 交易形式的返回内容中,会有事件结果(这也是让交易形式返回结果的方式)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26var 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) {
// result 是一个对象 有以下参数
//
// result.tx => 交易的hash, string型
// result.logs => 在交易中触发的事件的数组
// result.receipt => 交易收据对象, 包括 gas used
// 遍历 result.logs
for (var i = 0; i < result.logs.length; i++) {
var log = result.logs[i];
if (log.event == "Transfer") {
// 得到要的event
break;
}
}
}).catch(function(err) {
// 有错误
});
truffle-contract 链接Metamask web3
利用truffle-contract使MetaMask获取当前账号,连接至区块链1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47//引入truffle-contract
var contract = require('truffle-contract');
//引入合约地址
var CoinContract = require('../../contracts/Coin.json');
//获取当前窗口的web3的provider
var web3 = window.web3
if (typeof web3 !== 'undefined') {
web3 = new Web3(web3.currentProvider)
} else {
web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:7545/'))
}
const Contract = {
contract: null,
instance: null,
account: null,
init: function () {
let self = this
return new Promise(function (resolve, reject) {
// 引入合约地址
self.contract = contract(CoinContract)
self.contract.setProvider(web3.currentProvider)
// 获取metamak当前账户
web3.eth.getAccounts(function(error, accounts) {
if (error) {
console.log(error);
}
self.account = accounts[0]
})
// 链接至区块链
self.contract.deployed().then(instance => {
// 返回合约
self.instance = instance
resolve()
}).catch(err => {
reject(err)
})
})
}
}
export default Contract