MetaMask/metamask-inpage-provider
https://github.com/MetaMask/metamask-inpage-provider
Used to initialize the inpage ethereum provider injected by MetaMask.
Installation
npm install metamask-inpage-provider -S
metamask-inpage-provider/createErrorMiddleware.js
处理JSON-RPC调用是出现的错误,并将错误记录到日志中
loglevel是JavaScript的最小轻量级日志记录,它没有控制台的缺点,替代了console.log()并且对于基于级别的日志和过滤是十分友好的,本博客loglevel-metamask
const log = require('loglevel')
/**
* JSON-RPC error object
*
* @typedef {Object} RpcError
* @property {number} code - Indicates the error type that occurred
* @property {Object} [data] - Contains additional information about the error
* @property {string} [message] - Short description of the error
*/
/**
* Middleware configuration object
*
* @typedef {Object} MiddlewareConfig
* @property {boolean} [override] - Use RPC_ERRORS message in place of provider message
*/
/**
* Map of standard and non-standard RPC error codes to messages
*/
const RPC_ERRORS = {
1: 'An unauthorized action was attempted.',
2: 'A disallowed action was attempted.',
3: 'An execution error occurred.',
[-32600]: 'The JSON sent is not a valid Request object.',
[-32601]: 'The method does not exist / is not available.',
[-32602]: 'Invalid method parameter(s).',
[-32603]: 'Internal JSON-RPC error.',
[-32700]: 'Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.',
internal: 'Internal server error.',
unknown: 'Unknown JSON-RPC error.',
}
/**
* Modifies a JSON-RPC error object in-place to add a human-readable message,
* optionally overriding any provider-supplied message
*
* @param {RpcError} error - JSON-RPC error object
* @param {boolean} override - Use RPC_ERRORS message in place of provider message
*/
function sanitizeRPCError (error, override) {
if (error.message && !override) { return error }
const message = error.code > -31099 && error.code < -32100 ? RPC_ERRORS.internal : RPC_ERRORS[error.code]//判断错误类型并获得错误message
error.message = message || RPC_ERRORS.unknown
}
/**
* json-rpc-engine middleware that both logs standard and non-standard error
* messages and ends middleware stack traversal if an error is encountered
*
* @param {MiddlewareConfig} [config={override:true}] - Middleware configuration
* @returns {Function} json-rpc-engine middleware function
*/
function createErrorMiddleware ({ override = true } = {}) {
return (req, res, next) => {
next(done => {
const { error } = res
if (!error) { return done() }
sanitizeRPCError(error)
log.error(`MetaMask - RPC Error: ${error.message}`, error)
done()
})
}
}
module.exports = createErrorMiddleware
metamask-inpage-provider/index.js
这个库的作用有设置浏览器本地信息存储publicConfig流、构建RpcProvider双向传送json rpc及其结果流,以及对从浏览器中得到的json rpc进行处理,send/sendsync的处理是不同的,然后将他们根据得到的特殊id存储到数组中,等待传送到区块链进行处理
const pump = require('pump')//看本博客pump模块的学习-metamask
const RpcEngine = require('json-rpc-engine')//看本博客MetaMask/json-rpc-engine
const createErrorMiddleware = require('./createErrorMiddleware')//检查json rpc产生的错误
const createIdRemapMiddleware = require('json-rpc-engine/src/idRemapMiddleware')创建一个独特的id来标识json rpc,不然它的id很多都是相同的1,2等,看本博客MetaMask/json-rpc-engine
const createJsonRpcStream = require('json-rpc-middleware-stream')//看本博客的MetaMask/json-rpc-middleware-stream
const LocalStorageStore = require('obs-store')//看本博客MetaMask/obs-store
const asStream = require('obs-store/lib/asStream')//看本博客MetaMask/obs-store
const ObjectMultiplex = require('obj-multiplex')//看博客kumavis/obj-multiplex
const util = require('util')
const SafeEventEmitter = require('safe-event-emitter')//看博客MetaMask/safe-event-emitter
module.exports = MetamaskInpageProvider
util.inherits(MetamaskInpageProvider, SafeEventEmitter)
function MetamaskInpageProvider (connectionStream) {
const self = this
// super constructor
SafeEventEmitter.call(self)
// setup connectionStream multiplexing
const mux = self.mux = new ObjectMultiplex()
pump(
connectionStream,
mux,
connectionStream,
logStreamDisconnectWarning.bind(this, 'MetaMask')
)
// subscribe to metamask public config (one-way)
self.publicConfigStore = new LocalStorageStore({ storageKey: 'MetaMask-Config' })//定义了一个在浏览器中storageKey为'MetaMask-Config'的本地存储,用于存储一些区块链的账户信息,网络信息
pump(//进行浏览器本地信息存储
mux.createStream('publicConfig'),//创建name为publicConfig的子流
asStream(self.publicConfigStore),
logStreamDisconnectWarning.bind(this, 'MetaMask PublicConfigStore')//logStreamDisconnectWarning函数下面有定义,'MetaMask PublicConfigStore'为error说明,
)
// ignore phishing warning message (handled elsewhere)
mux.ignoreStream('phishing')//这里不对name为phishing的流进行处理
// connect to async provider
const jsonRpcConnection = createJsonRpcStream()//
pump(//构建provider,接受浏览器传来的json rpc,并响应
jsonRpcConnection.stream,
mux.createStream('provider'),
jsonRpcConnection.stream,
logStreamDisconnectWarning.bind(this, 'MetaMask RpcProvider')
)
// handle sendAsync requests via dapp-side rpc engine
const rpcEngine = new RpcEngine() 看了本博客MetaMask/json-rpc-engine后,可以知道这是push进将要对接受到的json rpc调用的处理
rpcEngine.push(createIdRemapMiddleware())//获得个unique id拿来使用
rpcEngine.push(createErrorMiddleware()) //进行错误的处理
rpcEngine.push(jsonRpcConnection.middleware) //将json rpc 请求写入createJsonRpcStream双工流中
self.rpcEngine = rpcEngine
// forward json rpc notifications
jsonRpcConnection.events.on('notification', function(payload) {//设置json-rpc-middleware-stream流相应的'notification'事件
self.emit('data', null, payload) //触发data事件
})
// Work around for https://github.com/metamask/metamask-extension/issues/5459
// drizzle accidently breaking the `this` reference
self.send = self.send.bind(self)
self.sendAsync = self.sendAsync.bind(self)
}
// Web3 1.0 provider uses `send` with a callback for async queries
MetamaskInpageProvider.prototype.send = function (payload, callback) {//web3调用send()
const self = this
if (callback) {//如果是异步带回调的,就调用sendAsync
self.sendAsync(payload, callback)
} else {//否则就调用_sendSync
return self._sendSync(payload)
}
}
// handle sendAsync requests via asyncProvider
// also remap ids inbound and outbound
MetamaskInpageProvider.prototype.sendAsync = function (payload, cb) {
const self = this
if (payload.method === 'eth_signTypedData') {
console.warn('MetaMask: This experimental version of eth_signTypedData will be deprecated in the next release in favor of the standard as defined in EIP-712. See https://git.io/fNzPl for more information on the new standard.')
}
self.rpcEngine.handle(payload, cb)//该json rpc就会被处理
}
MetamaskInpageProvider.prototype._sendSync = function (payload) {
const self = this
let selectedAddress
let result = null
switch (payload.method) {
case 'eth_accounts':
// read from localStorage
selectedAddress = self.publicConfigStore.getState().selectedAddress //从本地存储中获得账户信息
result = selectedAddress ? [selectedAddress] : []
break
case 'eth_coinbase':
// read from localStorage
selectedAddress = self.publicConfigStore.getState().selectedAddress//从本地存储中获得账户信息
result = selectedAddress || null
break
case 'eth_uninstallFilter':
self.sendAsync(payload, noop) //设置回调为{}再调用sendAsync
result = true
break
case 'net_version':
const networkVersion = self.publicConfigStore.getState().networkVersion//从本地存储中获得网络信息
result = networkVersion || null
break
// throw not-supported Error
default:
var link = 'https://github.com/MetaMask/faq/blob/master/DEVELOPERS.md#dizzy-all-async---think-of-metamask-as-a-light-client'
var message = `The MetaMask Web3 object does not support synchronous methods like ${payload.method} without a callback parameter. See ${link} for details.`
throw new Error(message)
}
// return the result
return {
id: payload.id,
jsonrpc: payload.jsonrpc,
result: result,
}
}
MetamaskInpageProvider.prototype.isConnected = function () {
return true
}
MetamaskInpageProvider.prototype.isMetaMask = true
// util
function logStreamDisconnectWarning (remoteLabel, err) {
let warningMsg = `MetamaskInpageProvider - lost connection to ${remoteLabel}`
if (err) warningMsg += '\n' + err.stack
console.warn(warningMsg)
const listeners = this.listenerCount('error')
if (listeners > ) {
this.emit('error', warningMsg)
}
}
function noop () {}
Usage
MetamaskInpageProvider的使用:
// Create a stream to a remote provider:
var metamaskStream = new LocalMessageDuplexStream({
name: 'inpage',
target: 'contentscript',
}) // compose the inpage provider
var inpageProvider = new MetamaskInpageProvider(metamaskStream)
MetaMask/metamask-inpage-provider的更多相关文章
- metamask源码学习-inpage.js
The most confusing part about porting MetaMask to a new platform is the way we provide the Web3 API ...
- Guide to Porting MetaMask to a New Environment
https://github.com/MetaMask/metamask-extension/blob/develop/docs/porting_to_new_environment.md MetaM ...
- MetaMask/zero-client
https://github.com/MetaMask/zero-client MetaMask ZeroClient and backing iframe service architecture ...
- mascara-2(MetaMask/mascara本地实现)-连接线上钱包
https://github.com/MetaMask/mascara (beta) Add MetaMask to your dapp even if the user doesn't have t ...
- MetaMask/metamask-extension-provider
用来探测你的浏览器中有没有安装metamask插件 https://github.com/MetaMask/metamask-extension-provider MetaMask Extension ...
- 青山不遮,毕竟东流,集成Web3.0身份钱包MetaMask以太坊一键登录(Tornado6+Vue.js3)
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_213 上世纪九十年代,海湾战争的时候,一位美军军官担心他们的五角大楼会被敌人的一枚导弹干掉,从而导致在全球的美军基地处于瘫痪状态. ...
- metamask源码学习-ui/index.js
The UI-即上图左下角metamask-ui部分,即其图形化界面 The MetaMask UI is essentially just a website that can be configu ...
- 通过METAMASK调试和发布智能合约指南(转载)
2017-12-07 芯链团队 小明微思考 原文地址:https://mp.weixin.qq.com/s?__biz=MzA4Mzk2MzUzNg==&mid=2651223347& ...
- 如何在自己设计的页面中调用metamask-1
启发: https://github.com/MetaMask/metamask-extension/issues/714 https://github.com/MetaMask/metamask-e ...
随机推荐
- [转]group by 后使用 rollup 子句总结
group by 后使用 rollup 子句总结 一.如何理解group by 后带 rollup 子句所产生的效果 group by 后带 rollup 子句的功能可以理解为:先按一定的规则产生多种 ...
- C#时间格式转换为时间戳互转
/// <summary> /// 将 DateTime时间格式转换为Unix时间戳格式 /// </summary> /// <param name="tim ...
- MySQL学习(五) UNION与UNION ALL
UNION用于把来自许多SELECT语句的结果组合到一个结果集合中,也叫联合查询. SELECT ... UNION [ALL | DISTINCT] SELECT ... [UNION [ALL | ...
- 关于Ajax的get与post浅分析,同步请求与异步请求,跨域请求;
Ajax局部异步刷新全称ASynchronous JavaScript And XML.使用Javascript代码获取服务器的数据,Ajax当中有两个请求方法,一个是get方法,一个是post请求方 ...
- JS闭包和引用
简介 Javascript 中一个最重要的特性就是闭包的使用.因为闭包的使用,当前作用域总可以访问外部的作用域.因为Javascript 没有块级作用域,只有函数作用域,所以闭包的使用与函数是紧密相关 ...
- 03--css形状--css揭秘
形状 一 自适应的椭圆 1.难题 1> 圆 你可能注意到过, 给任何正方形元素设置一个足够大的border-radius, 就可以把它变成一个圆形.所用到的CSS 代码如下所示: #bd { w ...
- VUE 实现复制内容到剪贴板功能
注: 依赖第三方插件 clipboard 一.安装插件 npm install vue-clipboard2 --save 二.全局注入(main.js) import VueClipboard fr ...
- php+smarty轻松开发微社区/微论坛
今天我们就来分析微社区的基本功能构成吧.首先,每个论坛最主要的是会员在对应的版块下发帖,或者在感兴趣的主题帖下跟帖盖楼.其次,会员能时时看到帖子或版块的基本信息.所以主要大块是: 前台:会员的注册登录 ...
- Java并发编程(二)同步
在多线程的应用中,两个或者两个以上的线程需要共享对同一个数据的存取.如果两个线程存取相同的对象,并且每一个线程都调用了修改该对象的方法,这种情况通常成为竞争条件. 竞争条件最容易理解的例子就是:比如 ...
- Mongodb的入门(8)mongodb事物分析
老生常谈:<在前面博客中也介绍过> mongodb官网:https://docs.mongodb.com/manual/introduction/ mongodb:官网上是这样定义的Mon ...