The UI-即上图左下角metamask-ui部分,即其图形化界面

The MetaMask UI is essentially just a website that can be configured by passing it the API and state subscriptions from above. Anyone could make a UI that consumes these, effectively reskinning MetaMask.

MetaMask UI本质上只是一个网站,可以通过从上面传递API和状态订阅来配置它。任何人都可以创建一个使用这些的UI,有效地重新设计MetaMask

You can see this in action in our file ui/index.js. There you can see an argument being passed in named accountManager, which is essentially a MetaMask controller (forgive its really outdated parameter name!). With access to that object, the UI is able to initialize a whole React/Redux app that relies on this API for its account/blockchain-related/persistent states.

你可以从文件ui/index.js中看见它的实现。在这里,您可以看到一个参数在accountManager中传递,accountManager本质上是一个MetaMask控制器(该参数名称已经过时!)通过对该对象的访问,UI能够初始化整个依赖于该API实现其帐户/区块链相关/持久状态的React/Redux应用程序。

metamask-extension/ui/index.js

const render = require('react-dom').render
const h = require('react-hyperscript')
const Root = require('./app/root')
const actions = require('./app/actions')
const configureStore = require('./app/store')
const txHelper = require('./lib/tx-helper')
const { fetchLocale } = require('./i18n-helper')
const log = require('loglevel') module.exports = launchMetamaskUi log.setLevel(global.METAMASK_DEBUG ? 'debug' : 'warn') function launchMetamaskUi (opts, cb) {
var accountManager = opts.accountManager//accountManager就是一个metamask控制器,所以metamask-controller.js中的函数其都能调用,UI一般就调用getApi ()和getState()两个函数
actions._setBackgroundConnection(accountManager)//设置后台的连接信息
// check if we are unlocked first
accountManager.getState(function (err, metamaskState) {//返回一个javascript对象,表示当前的MetaMask状态
if (err) return cb(err)
startApp(metamaskState, accountManager, opts)
.then((store) => {
cb(null, store)
})
})
}

//打开APP
async function startApp (metamaskState, accountManager, opts) {
// parse opts
if (!metamaskState.featureFlags) metamaskState.featureFlags = {} const currentLocaleMessages = metamaskState.currentLocale
? await fetchLocale(metamaskState.currentLocale)//得到`./_locales/${metamaskState.currentLocale}/messages.json`文件,因为选择的语言不同
: {}
const enLocaleMessages = await fetchLocale('en')//这个选择的是英语 const store = configureStore({//配置metamask环境信息,如中间件等 // metamaskState represents the cross-tab state
metamask: metamaskState, // appState represents the current tab's popup state
appState: {}, localeMessages: {
current: currentLocaleMessages,
en: enLocaleMessages,
}, // Which blockchain we are using:
networkVersion: opts.networkVersion,
}) // if unconfirmed txs, start on txConf page
//得到时间由小到大排序的所有信息
const unapprovedTxsAll = txHelper(metamaskState.unapprovedTxs, metamaskState.unapprovedMsgs, metamaskState.unapprovedPersonalMsgs, metamaskState.unapprovedTypedMessages, metamaskState.network)
const numberOfUnapprivedTx = unapprovedTxsAll.length
if (numberOfUnapprivedTx > 0) {
store.dispatch(actions.showConfTxPage({
id: unapprovedTxsAll[numberOfUnapprivedTx - 1].id,//配置actions中showConfTxPage的值,tx里的详细信息可以看本博客metamask源码学习-background.js,其的代码注释中有写,如id...
}))
} accountManager.on('update', function (metamaskState) {//如果metamaskState由更新时触发
store.dispatch(actions.updateMetamaskState(metamaskState))
}) // global metamask api - used by tooling
global.metamask = {
updateCurrentLocale: (code) => {
store.dispatch(actions.updateCurrentLocale(code))
},
setProviderType: (type) => {
store.dispatch(actions.setProviderType(type))
},
} // start app,使用react框架来启动该metamask app
render(
h(Root, {
// inject initial state
store: store,//这里的内容就是上面进行相应设置后的状态信息,这个store有的详细内容的解释看本博客metamask源码学习-background.js,其的代码注释中有写本博客metamask源码学习-background.js,其的代码注释中有写
} ), opts.container) return store }

metamask-extension/app/scripts/metamask-controller.js

//=============================================================================
// EXPOSED TO THE UI SUBSYSTEM
//============================================================================= /**
* The metamask-state of the various controllers是得到多种控制器的状态, made available to the UI
*
* @returns {Object} status
*/
getState () {
const wallet = this.configManager.getWallet()
const vault = this.keyringController.store.getState().vault
const isInitialized = (!!wallet || !!vault)//就是只要两者wallet和vault中有一个有值,那么就说明初始化过了 return {
...{ isInitialized },
...this.memStore.getFlatState(),
...this.configManager.getConfig(),
...{
lostAccounts: this.configManager.getLostAccounts(),
seedWords: this.configManager.getSeedWords(),
forgottenPassword: this.configManager.getPasswordForgotten(),
},
}
}
 !!()。

比如:a默认是undefined,!a是true,!!a则是false,所以b的值是false,而不再是undefined。这样写可以方便后续判断使用。

所以,!!(a)的作用是将a强制转换为布尔型(boolean)。

metamask-extension/ui/i18n-helper.js

async function fetchLocale (localeName) {//得到`./_locales/${metamaskState.currentLocale}/messages.json`文件
try {
const response = await fetch(`./_locales/${localeName}/messages.json`)
return await response.json()
} catch (error) {
log.error(`failed to fetch ${localeName} locale because of ${error}`)
return {}
}
}

metamask-extension/ui/app/util.js

function valuesFor (obj) {//通过keys()得到obj对象中的键值,因为这里面的键值并不是简单的1,2;然后再根据获得的键值去得到obj中对应的值,并再组合起来成新的obj对象,即map()
if (!obj) return []
return Object.keys(obj)
.map(function (key) { return obj[key] })
}

举例:

var obj = {'a':'123','b':'345'};
console.log(Object.keys(obj)); //['a','b']

metamask-extension/ui/lib/tx-helper.js

const valuesFor = require('../app/util').valuesFor
const log = require('loglevel') module.exports = function (unapprovedTxs, unapprovedMsgs, personalMsgs, typedMessages, network) {
log.debug('tx-helper called with params:')
log.debug({ unapprovedTxs, unapprovedMsgs, personalMsgs, typedMessages, network })

//就是network不为0时,那么就得到unapprovedTxs中满足metamaskNetworkId === network条件的所有没被赞同的Txs;如果为0,则得到所有没被赞同的Txs
const txValues = network ? valuesFor(unapprovedTxs).filter(txMeta => txMeta.metamaskNetworkId === network) : valuesFor(unapprovedTxs)
log.debug(`tx helper found ${txValues.length} unapproved txs`) const msgValues = valuesFor(unapprovedMsgs)//得到没有签名的信息
log.debug(`tx helper found ${msgValues.length} unsigned messages`)
let allValues = txValues.concat(msgValues) const personalValues = valuesFor(personalMsgs)//得到没有签名的个人信息
log.debug(`tx helper found ${personalValues.length} unsigned personal messages`)
allValues = allValues.concat(personalValues) const typedValues = valuesFor(typedMessages)//得到没有签名的typed信息
log.debug(`tx helper found ${typedValues.length} unsigned typed messages`)
allValues = allValues.concat(typedValues)
//并全部串联起来放在allValues中
allValues = allValues.sort((a, b) => {//一个个去对比,按照每个信息的时间由小到大去排序,如果想要有大到小,就写成a.time < b.time
return a.time > b.time
}) return allValues
}

metamask源码学习-ui/index.js的更多相关文章

  1. metamask源码学习-inpage.js

    The most confusing part about porting MetaMask to a new platform is the way we provide the Web3 API ...

  2. metamask源码学习导论

    ()MetaMask Browser Extension https://github.com/MetaMask/metamask-extension 这就是整个metamask的源码所在之处,好好看 ...

  3. metamask源码学习-controller-transaction

    ()metamask-extension/app/scripts/controllers/transactions Transaction Controller is an aggregate of ...

  4. metamask源码学习-background.js

    这个就是浏览器后台所进行操作的地方了,它就是页面也区块链进行交互的中间部分. metamask-background描述了为web扩展单例的文件app/scripts/background.js.该上 ...

  5. metamask源码学习-contentscript.js

    When a new site is visited, the WebExtension creates a new ContentScript in that page's context, whi ...

  6. metamask源码学习-metamask-controller.js

    The MetaMask Controller——The central metamask controller. Aggregates other controllers and exports a ...

  7. metamask源码学习-controllers-network

    https://github.com/MetaMask/metamask-extension/tree/master/app/scripts/controllers/network metamask- ...

  8. chrome源码学习之:js与底层c++的通信

    以查询历史记录为例: 1.在上层history.js中通过chrome.send()来向底层发送事件请求和相关参数,其中'queryHistory'为信号名称,[this.searchText_, t ...

  9. vue 源码学习----build/config.js

    1. process 这个process是什么?为何都没有引入就可以使用了呢? process 对象是一个 global (全局变量),提供有关信息,控制当前 Node.js 进程.作为一个对象,它对 ...

随机推荐

  1. 【手记】解决excel无法设置单元格颜色且界面怪异+桌面图标文字老有色块等问题

    注:问题是在XP上遇到的,不知道是否适用其它系统 问题现象 excel 2010成这样了: 关键是设置不了单元格颜色,无论是文字颜色还是背景色都设置不了,设了没变化.同时会发现桌面图标的文字总有底色: ...

  2. 跨站请求伪造CSRF(Cross-site request forgery)

    CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站 ...

  3. 复盘价值1000万的腾讯云硬盘固件"BUG"

    摘要: 除了吃瓜,还是得吸取教训啊同学们! 这次,我从纯技术角度分析腾讯云与前沿数控的磁盘数据丢失事件,不站队. 硬盘门 这里说的硬盘门不是10年前陈老师的那一次,而聊的是最近"腾讯云&qu ...

  4. Android系统常用URI

    android系统常用URI android系统管理联系人的URI如下: ContactsContract.Contacts.CONTENT_URI 管理联系人的Uri ContactsContrac ...

  5. JS中实现跨域的方法总结

    今天早上在地铁看了点基础知识的考察题,看到了一个JS跨域的问题,仔细想了想自己脑子里竟然只剩下jsonp跨域和用nginx反向代理进行跨域,想着还有别的几种方法,就是想不起来,这个人呢,一上岁数这个脑 ...

  6. 将Windows下的InfluxDB、Grafana做成Windows服务

    从网上下载的Windows下的InfluxDB.Grafana,都是控制台程序,打开窗口后,很容易被别人给关掉,因此考虑做成Windows服务,nssm正是解决该问题的利器. 1.下载nssm htt ...

  7. OneAlert 携手 BearyChat(倍洽)快速构建 IT 运维 on-call 机制

    OneAlert 是北京蓝海讯通科技股份有限公司旗下产品,中国第⼀个 SaaS 模式的免费的云告警平台,集成国内外主流监控/⽀撑系统,实现⼀个平台上集中处理所有 IT 事件,提升 IT 可靠性.并且能 ...

  8. 为Hexo Next主题添加分享及打赏功能

    博客地址:往事亦如风的博客 要想先看打赏和分享功能效果,请移步我的博客 打赏功能 因为next主题自带打赏功能,所以我们只需要在next的主题配置文件中找到如下代码,image文件夹是我在blog/s ...

  9. Python类继承,方法重写及私有方法

    # -*- coding: utf-8 -*- """ Created on Mon Nov 12 15:05:20 2018 @author: zhen "& ...

  10. maven(七),本地仓库

    运行机制: 在pom.xml文件中添加依赖jar包时,首先会从本地仓库查找,如果本地仓库不存在,就从中央仓库下载到本地仓库,中央仓库是maven默认的远程仓库 仓库坐标 eclipse默认会在wind ...