这篇博客是 通过小游戏学习Ethereum DApps编程系列。
- 通过小游戏学习Ethereum DApps编程(8)← 你在这里
- 通过小游戏学习Ethereum DApps编程(7)
- 通过小游戏学习Ethereum DApps编程(6)
- 通过小游戏学习Ethereum DApps编程(5)
- 通过小游戏学习Ethereum DApps编程(4)
- 通过小游戏学习Ethereum DApps编程(3)
- 通过小游戏学习Ethereum DApps编程(2)
- 通过小游戏学习Ethereum DApps编程(1)
在第五章里面我们了解了ERC20 tokens,ERC721标准,以及crypto-collectible。这些知识可以让我们和其他玩家交易自己的创造的角色。
在最后一章节我们将了解怎么把智能合约发不到ETH网络上。我们会了解一些关于Web3.js库的知识点。
如何从MetaMask获取用户的账号
MetaMask是一款可以用于Chrome和Firefox的插件,实现了Web3的接口,用于管理用户的private key。
MetaMask上可以同时管理多个账号。
获取当前活跃的账号:
var userAccount = web3.eth.accounts[0]
如果我们的游戏的主页上,有一个显示目前账号拥有的角色的功能的话,在用户切换账号的时候,我们需要重新获取新账号的信息,然后更新显示的结果。
我们可以通过一个timer来做check。
var accountInterval = setInterval(function() {
// Check if account has changed
if (web3.eth.accounts[0] !== userAccount) {
userAccount = web3.eth.accounts[0];
// Call some function to update the UI with the new account
updateInterface();
}
}, 100);
send
我们可以使用send功能来进行我们角色的交换。
- send需要我们的账户地址用于智能合约msg.sender的调用
- send需要消费gas
- 在我们提出send请求之后,根据我们设定的gas,最终被Blockchain执行并且写入到Block里面,可能有延迟。
复习:Web3和solidity之间的调用
在solidity里面,我们可以有这样一个功能:
function createRandomZombie(string _name) public {
require(ownerZombieCount[msg.sender] == 0);
uint randDna = _generateRandomDna(_name);
randDna = randDna - randDna % 100;
_createZombie(_name, randDna);
}
我们可以从Web3这样调用
function createRandomZombie(name) {
// This is going to take a while, so update the UI to let the user know
// the transaction has been sent
$("#txStatus").text("Creating new zombie on the blockchain. This may take a while...");
// Send the tx to our contract:
return cryptoZombies.methods.createRandomZombie(name)
.send({ from: userAccount })
.on("receipt", function(receipt) {
$("#txStatus").text("Successfully created " + name + "!");
// Transaction was accepted into the blockchain, let's redraw the UI
getZombiesByOwner(userAccount).then(displayZombies);
})
.on("error", function(error) {
// Do something to alert the user their transaction has failed
$("#txStatus").text(error);
});
}
发送send到Web3服务提供方
在我们发送send请求到Web3服务方(比如:MetaMask插件),我们可以通过监听来得到结果
- receipt 表示我们的请求得到了处理,并且完成了Blockchain的写入。
- error 表示执行没有顺利完成,或许是因为我们没有设定足够的gas等。
在执行send的时候,我们可以设定一个固定值为gas,当我们没有特别指定一个gas值的时候,MetaMask可以让用户来选择。
send({ from: userAccount, gas: 3000000 })
Wei
Wei是表述gas的单位,10^18个wei等于一个ether。
// This will convert 1 ETH to Wei
web3js.utils.toWei("1");
cryptoZombies.methods.levelUp(zombieId)
.send({ from: userAccount, value: web3js.utils.toWei("0.001", "ether") })
从Web3监听Solidity的event
还记得我们如何在solidity里面定义event的么?
event NewZombie(uint zombieId, string name, uint dna);
我可以这样在Web3上监听时间的触发:
cryptoZombies.events.NewZombie()
.on("data", function(event) {
let zombie = event.returnValues;
// We can access this event's 3 return values on the `event.returnValues` object:
console.log("A new zombie was born!", zombie.zombieId, zombie.name, zombie.dna);
}).on("error", console.error);
indexed
在上面的监听event的处理的时候,我们会接收到所以的触发,我们需要过滤信息只在该用户的活跃账户的时候显示提示。
这时候,我们用indexed就可以解决。
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
// Use `filter` to only fire this code when `_to` equals `userAccount`
cryptoZombies.events.Transfer({ filter: { _to: userAccount } })
.on("data", function(event) {
let data = event.returnValues;
// The current user just received a zombie!
// Do something here to update the UI to show it
}).on("error", console.error);
events和indexed在需要监听和过滤信息的时候非常方便。
我们甚至可以监听过去的event
cryptoZombies.getPastEvents("NewZombie", { fromBlock: 0, toBlock: "latest" })
.then(function(events) {
// `events` is an array of `event` objects that we can iterate, like we did above
// This code will get us a list of every zombie that was ever created
});
Because you can use this method to query the event logs since the beginning of time, this presents an interesting use case: Using events as a cheaper form of storage.
在Eth网络上,存储信息是需要花费gas的,如果我们只需要显示信息,我们可以利用event的可追溯功能,来廉价的实现。
学习完毕图片来源
图片来自原作者官方网站
网友评论