如何在自己设计的页面中调用metamask-1
启发:
https://github.com/MetaMask/metamask-extension/issues/714
https://github.com/MetaMask/metamask-extension/issues/3383
()
下面是cryptokitties这个游戏使用metamask的方法:
如果你没有添加metamask并且打开它,你是进不去这个游戏的,你点击开始游戏,它会一直卡在这里
然后当你打开了metamask之后,这时候无论你连接的是什么网络,这时候应该是探测到了window.web3.currentProvider !== 'undefined'了,然后你就可以进行下一步注册了
上面那样子就注册好了,这个时候你就能够进行登录了
然后点击登录后你就能够看见下面的页面弹出:
就是你想要进入这个页面你需要进行签名
当我的钱包logout了以后,页面也会一起logout:
然后点击开始又会出现下面的页面,这时候用户也没有登录到上面的账户:
当然你也可以在网页上进行一些不需要登录也能执行的操作,但是当要进行一些操作时,你就可以看见,显示的是你还没有登录,就是钱包下线的同时,网页账户也会跟着下线
然后当你在metamask上登录后,网站状态就会变成:
然后在过程中,点击我的主页的时候,有显示一个错误,就是我进入到了错误的网络:
在我的主页上能看见下面的信息:
可以看见复制地址处的address的确是metamask处现在的账号
然后这就是网页与metamask之间的关系,但是怎么实现呢,要接着学习了
()
Developing for MetaMask
https://github.com/MetaMask/faq/blob/master/detecting_metamask.md
Detecting MetaMask
Metamask/Mist currently inject their interface into page as global web3
object.
window.addEventListener('load', function() {
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
// Use the browser's ethereum provider
var provider = web3.currentProvider
} else {
console.log('No web3? You should consider trying MetaMask!')
}
})
The provider
object is a low-level object with just one supported method: provider.sendAsync(options, callback)
.
The options
object has several useful fields: method
(the method name), from
(the sender address), params
(an array of parameters to send to that method).
These methods all correspond directly to the options in the RPC provider spec.
这个网页就是教你怎么使用metamask来进行开发的,从这个文档我好像明白了什么,就是其实metamask是提供整个web3接口的,就是我们直接在网页上进行对metamask的web3进行调用即可,它给的web3接口的详细信息在https://github.com/ethereum/wiki/wiki/JSON-RPC上有写
To see if the injected provider is from MetaMask, you can check web3.currentProvider.isMetaMask
.
Installing Web3.js
Because default web3
API is not very user friendly, most developers will import a convenience library like Web3.js or EthJS using the bundler of their choice.
就是说一般默认的那个web3可能使用得并不是很方便,所以其实我们是能够自己下载Web3.js的库来进行调用的;或者使用 EthJS ,就是一个轻量级的eth的使用方法:
Installing EthJS
npm install --save ethjs
Using a Convenience Library
Once you've detected an Ethereum browser, and imported a convenience library, you can initialize that library using the detected web3.currentProvider
object. For web3 with browserify, this might look like this:
var Web3 = require('web3')
var localWeb3 = new Web3(web3.currentProvider)
Initializing an EthJS instance looks similar:
const Eth = require('ethjs');
const eth = new Eth(web3.currentProvider);
当然我还是选择第一个,但是如果想学习第二个,可以看https://github.com/ethjs/ethjs,有空看看
()
想要使用第一种方法web3.js library的话,就看下面的网址的内容
但是吧,如果你的浏览器本身就已经安装了metamask,那你就可以直接在网页上使用web3了,而不用还要跟下面这样链接
当然,如果你只是想在网页上调用web3,与metamask无关,那么就继续往下看,不然就跳过这一部分
Ethereum JavaScript API
https://github.com/ethereum/web3.js
这就是JavaScript API 的接口
网址上的调用方法就是加上这一句话:
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js"></script>
As a Browser module
CDN
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js"></script>
到这个网址上看https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/,长成下面这样:
![](https://img2018.cnblogs.com/blog/1446032/201809/1446032-20180919164708519-875062835.png)
上面的是0.20版本的,当然也有1.0版本的,https://www.jsdelivr.com/package/gh/ethereum/web3.js?version=1.0.0-beta.22&path=dist
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js@1.0.0-beta.36/dist/web3.min.js"></script>
所以就是调用这些js包后,就可以更之前一样调用web3啦
但是调用了1.0版本的包,得出来的结果还是0.20版本
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js@1.0.0-beta.36/dist/web3.min.js"></script>
<script type="text/javascript">
console.log(web3.version);
然后浏览器返回结果是
MetaMask: web3 will be deprecated in the near future in favor of the ethereumProvider
https://github.com/MetaMask/faq/blob/master/detecting_metamask.md#web3-deprecation inpage.js:1:2023
{…}
api: "0.20.3"
但是后面一想,这个是单纯地使用web3的方法,我这里是要和metamask连在一起,所以就不能用web3.min.js了,或许有什么方法可以改变metamask的web3的版本,但是我们现在先把0.20 的版本学会吧
注意:
有个web3需要注意的地方:
一开始声明的方法有所改变 ,就是从
web3 = require('web3');
变成了
var Web3 = require('web3');
var web3 = new Web3();
()
接着看:https://github.com/MetaMask/faq/blob/master/DEVELOPERS.md
MetaMask Compatibility Guide
接的是0.20版本的web3.js:https://github.com/ethereum/wiki/wiki/JavaScript-API
然后使用metamask的情况就是,在html的JavaScript中:
<script type="text/javascript">
console.log(web3.version);
window.addEventListener('load', function() {
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
console.log(web3);
// Use the browser's ethereum provider
var provider = web3.currentProvider
console.log(provider);
} else {
console.log('No web3? You should consider trying MetaMask!')
}
}
结果是返回:
MetaMask: web3 will be deprecated in the near future in favor of the ethereumProvider
https://github.com/MetaMask/faq/blob/master/detecting_metamask.md#web3-deprecation inpage.js:1:2023
{…}
api: "0.20.3"
...
<prototype>: Object { … }
createAndBuyToken:381:5
Proxy
<target>: {…}
_extend: function e()
_requestManager: Object { provider: {…}, polls: {}, timeout: null }
bzz: Object { _requestManager: {…}, blockNetworkRead: e()
, syncEnabled: e()
, … }
currentProvider: Object { mux: {…}, publicConfigStore: {…}, rpcEngine: {…} }
...
那如果我的metamask不是登录状态,那又应该是怎样呢:
如果不是登录状况,检测的方法是查看其的web3.eth.coinbase,详细内容看本博客的如何在自己设计的页面中调用metamask-2
All Async - Think of MetaMask as a light client
The user does not have the full blockchain on their machine, so data lookups can be a little slow. For this reason, we are unable to support most synchronous methods. The exceptions to this are,就是在metamask的web3中的调用基本上都是异步的,下面的几个除外:
eth_accounts
(web3.eth.accounts
)eth_coinbase
(web3.eth.coinbase
)eth_uninstallFilter
(web3.eth.uninstallFilter
)web3.eth.reset
(uninstalls all filters).net_version
(web3.version.network
).
Usually, to make a method call asynchronous, add a callback as the last argument to a synchronous method. See the Ethereum wiki on "using callbacks"
Using synchronous calls is both a technical limitation and a user experience issue. They block the user's interface. So using them is a bad practice, anyway. Think of this API restriction as a gift to your users.
举个异步例子:
Network check
When a user interacts with a dapp via MetaMask, they may be on the mainnet or testnet. As a best practice, your dapp should inspect the current network via the net_version
json rpc call. Then, the dapp can use the correct deployed contract addresses for the network, or show which network is expected in a message.
For example:
查看你的metamask连接的网络是什么,即其的networkId是多少,即chainId是多少来得到信息:
web3.version.getNetwork((err, netId) => { switch (netId) { case "1": console.log('This is mainnet') break case "2": console.log('This is the deprecated Morden test network.') break case "3": console.log('This is the ropsten test network.') break case "4": console.log('This is the Rinkeby test network.') break case "42": console.log('This is the Kovan test network.') break default: console.log('This is an unknown network.') } })
Account management and transaction signing is managed externally to the dapp
Many Dapps have a built-in identity management solution as a fallback. When an Ethereum Browser environment has been detected, the user interface should reflect that the accounts are being managed externally.
var accounts = web3.eth.accounts; console.log(accounts); // ["0x407d73d8a49eeb85d32cf465507dd71d507100c1"]
在这里得到的账户的信息都是钱包里的账户
Also see the Ethereum wiki on "accounts"
🙋 Account List Reflects User Preference
When a user selects an account in MetaMask, that account silently becomes the web3.eth.accounts[0]
in your JS context, the only member of the web3.eth.accounts
array.
当你在metamask选择了使用其中一个账户后,他就被指定为web3.eth.accounts[0]或
web3.eth.defaultAccount
For your convenience, consider the web3.eth.defaultAccount
variable a dapp-provided variable. However, it should not be used as a data source of user intention.
👂 Listening for Selected Account Changes 监听账户的变化
Since these variables reflect user intention, but do not (currently) have events representing their values changing, we somewhat reluctantly recommend using an interval to check for account changes.
For example, if your application only cares about the web3.eth.accounts[0]
value, you might add some code like this somewhere in your application:
var account = web3.eth.accounts[0]; var accountInterval = setInterval(function() { if (web3.eth.accounts[0] !== account) { account = web3.eth.accounts[0]; updateInterface(); } }, 100);
上面的那个是JavaScript版本的web3js调用的API,当然还有其他版本的,如java的、PHP的
之前写JavaScript的写习惯了,还是用这个
Other implementations
- Python Web3.py
- Haskell hs-web3
- Java web3j
- Scala web3j-scala
- Purescript purescript-web3
- PHP web3.php
- PHP ethereum-php
然后后面进行了一次简单的调用
window.addEventListener('load', function() {
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
var provider = web3.currentProvider;
console.log(web3.eth.accounts[0]);
} else {
console.log('No web3? You should consider trying MetaMask!')
}
})
结果是:
{…}
BuyToken: function ()
CreateAndBuyToken: function ()
RevocateSell: function ()
SellToken: function ()
Send: function ()
_eth: Object { _requestManager: {…}, getBalance: e()
, getStorageAt: e()
, … }
abi: Array(24) [ {…}, {…}, {…}, … ]
address: "0x4eb2bb88ac610f989d07..."
...
withdrawl: function ()
<prototype>: Object { … }
createAndBuyToken:433:13
0x3455f15cc11f2e77c055...
但是可以看见,返回的账户的值是你的钱包metamask里面的第一个账号的值,说明你成功连接上了metamask