MetaMask/provider-engine-2-代码
package.json
"main": "index.js",
"scripts": {
"test": "node test/index.js",
"prepublish": "npm run build && npm run bundle",
"build": "babel zero.js index.js -d dist/es5 && babel subproviders -d dist/es5/subproviders && babel util -d dist/es5/util",
"bundle": "mkdir -p ./dist && npm run bundle-engine && npm run bundle-zero",
"bundle-zero": "browserify -s ZeroClientProvider -e zero.js -t [ babelify --presets [ es2015 ] ] > dist/ZeroClientProvider.js",
"bundle-engine": "browserify -s ProviderEngine -e index.js -t [ babelify --presets [ es2015 ] ] > dist/ProviderEngine.js"
},
从script可以看出来,运行该项目,首先要prepublish
npm run prepublish
作用就是将根目录下的index.js\zero.js\subproviders和util文件夹中的所有文件都使用babel转成es5的版本,存放在dist文件夹中。然后分别使用browserify将index.js\zero.js转成es5版本的dist/ProviderEngine.js\dist/ZeroClientProvider.js
browserify命令行参数意思:
–transform, -t: 对上层文件进行转换
–entry, -e: 应用程序的入口
–standalone -s: 生成一个UMB的绑定的接口,提供给其他模块使用。
返回:
> web3-provider-engine@14.1. prepublish /Users/wanghui/provider-engine-master
> npm run build && npm run bundle > web3-provider-engine@14.1. build /Users/wanghui/provider-engine-master
> babel zero.js index.js -d dist/es5 && babel subproviders -d dist/es5/subproviders && babel util -d dist/es5/util zero.js -> dist/es5/zero.js
index.js -> dist/es5/index.js
subproviders/cache.js -> dist/es5/subproviders/cache.js
subproviders/default-fixture.js -> dist/es5/subproviders/default-fixture.js
subproviders/etherscan.js -> dist/es5/subproviders/etherscan.js
subproviders/fetch.js -> dist/es5/subproviders/fetch.js
subproviders/filters.js -> dist/es5/subproviders/filters.js
subproviders/fixture.js -> dist/es5/subproviders/fixture.js
subproviders/gasprice.js -> dist/es5/subproviders/gasprice.js
subproviders/hooked-wallet-ethtx.js -> dist/es5/subproviders/hooked-wallet-ethtx.js
subproviders/hooked-wallet.js -> dist/es5/subproviders/hooked-wallet.js
subproviders/inflight-cache.js -> dist/es5/subproviders/inflight-cache.js
subproviders/infura.js -> dist/es5/subproviders/infura.js
subproviders/ipc.js -> dist/es5/subproviders/ipc.js
subproviders/nonce-tracker.js -> dist/es5/subproviders/nonce-tracker.js
subproviders/provider.js -> dist/es5/subproviders/provider.js
subproviders/rpc.js -> dist/es5/subproviders/rpc.js
subproviders/sanitizer.js -> dist/es5/subproviders/sanitizer.js
subproviders/stream.js -> dist/es5/subproviders/stream.js
subproviders/subprovider.js -> dist/es5/subproviders/subprovider.js
subproviders/subscriptions.js -> dist/es5/subproviders/subscriptions.js
subproviders/vm.js -> dist/es5/subproviders/vm.js
subproviders/wallet.js -> dist/es5/subproviders/wallet.js
subproviders/websocket.js -> dist/es5/subproviders/websocket.js
subproviders/whitelist.js -> dist/es5/subproviders/whitelist.js
util/assert.js -> dist/es5/util/assert.js
util/async.js -> dist/es5/util/async.js
util/create-payload.js -> dist/es5/util/create-payload.js
util/estimate-gas.js -> dist/es5/util/estimate-gas.js
util/random-id.js -> dist/es5/util/random-id.js
util/rpc-cache-utils.js -> dist/es5/util/rpc-cache-utils.js
util/rpc-hex-encoding.js -> dist/es5/util/rpc-hex-encoding.js
util/stoplight.js -> dist/es5/util/stoplight.js > web3-provider-engine@14.1. bundle /Users/wanghui/provider-engine-master
> mkdir -p ./dist && npm run bundle-engine && npm run bundle-zero > web3-provider-engine@14.1. bundle-engine /Users/wanghui/provider-engine-master
> browserify -s ProviderEngine -e index.js -t [ babelify --presets [ es2015 ] ] > dist/ProviderEngine.js > web3-provider-engine@14.1. bundle-zero /Users/wanghui/provider-engine-master
> browserify -s ZeroClientProvider -e zero.js -t [ babelify --presets [ es2015 ] ] > dist/ZeroClientProvider.js
然后运行test:
npm run test
返回:
> web3-provider-engine@14.1. test /Users/wanghui/provider-engine-master
> node test/index.js (node:) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
TAP version
# fallthrough test
ok did not error
ok has response
ok providerA did see "test_rpc"
ok providerA did NOT handle "test_rpc"
ok providerB did see "test_rpc"
ok providerB did handle "test_rpc"
ok providerC did NOT see "test_rpc"
ok providerC did NOT handle "test_rpc"
# cacheIdentifierForPayload for latest block
ok cacheIds are unique
# blockTagForPayload for different methods
ok block tag for eth_getBalance is correct
ok block tag for eth_getCode is correct
ok block tag for eth_getTransactionCount is correct
ok block tag for eth_getStorageAt is correct
ok block tag for eth_call is correct
ok block tag for eth_estimateGas is correct
ok block tag for eth_getBlockByNumber is correct
# cache - skipCache - true
ok did not error
ok has response
ok cacheProvider did see "eth_getBalance"
ok cacheProvider did NOT handle "eth_getBalance"
ok handlingProvider did see "eth_getBalance"
ok handlingProvider did handle "eth_getBalance"
ok did not error
ok has response
ok cacheProvider did see "eth_getBalance"
ok cacheProvider did handle "eth_getBalance"
ok handlingProvider did NOT see "eth_getBalance"
ok handlingProvider did NOT handle "eth_getBalance"
# cache - skipCache - false
ok did not error
ok has response
ok cacheProvider did see "eth_getBalance"
ok cacheProvider did NOT handle "eth_getBalance"
ok handlingProvider did see "eth_getBalance"
ok handlingProvider did handle "eth_getBalance"
ok did not error
ok has response
ok cacheProvider did see "eth_getBalance"
ok cacheProvider did handle "eth_getBalance"
ok handlingProvider did NOT see "eth_getBalance"
ok handlingProvider did NOT handle "eth_getBalance"
# cache - getBalance + undefined blockTag
ok did not error
ok has response
ok cacheProvider did see "eth_getBalance"
ok cacheProvider did NOT handle "eth_getBalance"
ok handlingProvider did see "eth_getBalance"
ok handlingProvider did handle "eth_getBalance"
ok did not error
ok has response
ok cacheProvider did see "eth_getBalance"
ok cacheProvider did handle "eth_getBalance"
ok handlingProvider did NOT see "eth_getBalance"
ok handlingProvider did NOT handle "eth_getBalance"
# cache - getBalance + latest blockTag
ok did not error
ok has response
ok cacheProvider did see "eth_getBalance"
ok cacheProvider did NOT handle "eth_getBalance"
ok handlingProvider did see "eth_getBalance"
ok handlingProvider did handle "eth_getBalance"
ok did not error
ok has response
ok cacheProvider did see "eth_getBalance"
ok cacheProvider did handle "eth_getBalance"
ok handlingProvider did NOT see "eth_getBalance"
ok handlingProvider did NOT handle "eth_getBalance"
# cache - getBalance + pending blockTag
ok did not error
ok has response
ok cacheProvider did see "eth_getBalance"
ok cacheProvider did NOT handle "eth_getBalance"
ok handlingProvider did see "eth_getBalance"
ok handlingProvider did handle "eth_getBalance"
ok did not error
ok has response
ok cacheProvider did see "eth_getBalance"
ok cacheProvider did handle "eth_getBalance"
ok handlingProvider did NOT see "eth_getBalance"
ok handlingProvider did NOT handle "eth_getBalance"
# cache - getTransactionByHash for transaction that doesn't exist
ok did not error
ok has response
ok cacheProvider did see "eth_getTransactionByHash"
ok cacheProvider did NOT handle "eth_getTransactionByHash"
ok handlingProvider did see "eth_getTransactionByHash"
ok handlingProvider did handle "eth_getTransactionByHash"
ok did not error
ok has response
ok cacheProvider did see "eth_getTransactionByHash"
ok cacheProvider did handle "eth_getTransactionByHash"
ok handlingProvider did NOT see "eth_getTransactionByHash"
ok handlingProvider did NOT handle "eth_getTransactionByHash"
# cache - getTransactionByHash for transaction that's pending
ok did not error
ok has response
ok cacheProvider did see "eth_getTransactionByHash"
ok cacheProvider did NOT handle "eth_getTransactionByHash"
ok handlingProvider did see "eth_getTransactionByHash"
ok handlingProvider did handle "eth_getTransactionByHash"
ok did not error
ok has response
ok cacheProvider did see "eth_getTransactionByHash"
ok cacheProvider did handle "eth_getTransactionByHash"
ok handlingProvider did NOT see "eth_getTransactionByHash"
ok handlingProvider did NOT handle "eth_getTransactionByHash"
# cache - getTransactionByHash for mined transaction
ok did not error
ok has response
ok cacheProvider did see "eth_getTransactionByHash"
ok cacheProvider did NOT handle "eth_getTransactionByHash"
ok handlingProvider did see "eth_getTransactionByHash"
ok handlingProvider did handle "eth_getTransactionByHash"
ok did not error
ok has response
ok cacheProvider did see "eth_getTransactionByHash"
ok cacheProvider did handle "eth_getTransactionByHash"
ok handlingProvider did NOT see "eth_getTransactionByHash"
ok handlingProvider did NOT handle "eth_getTransactionByHash"
# cache - getCode for latest block, then for earliest block, should not return cached response on second request
ok did not error
ok has response
ok cacheProvider did see "eth_getCode"
ok cacheProvider did NOT handle "eth_getCode"
ok handlingProvider did see "eth_getCode"
ok handlingProvider did handle "eth_getCode"
ok did not error
ok has response
ok cacheProvider did see "eth_getCode"
ok cacheProvider did handle "eth_getCode"
ok handlingProvider did NOT see "eth_getCode"
ok handlingProvider did NOT handle "eth_getCode"
# cache - getCode for a specific block, then for the one before it, should not return cached response on second request
ok did not error
ok has response
ok cacheProvider did see "eth_getCode"
ok cacheProvider did NOT handle "eth_getCode"
ok handlingProvider did see "eth_getCode"
ok handlingProvider did handle "eth_getCode"
ok did not error
ok has response
ok cacheProvider did see "eth_getCode"
ok cacheProvider did handle "eth_getCode"
ok handlingProvider did NOT see "eth_getCode"
ok handlingProvider did NOT handle "eth_getCode"
# cache - getCode for a specific block, then the one after it, should return cached response on second request
ok did not error
ok has response
ok cacheProvider did see "eth_getCode"
ok cacheProvider did NOT handle "eth_getCode"
ok handlingProvider did see "eth_getCode"
ok handlingProvider did handle "eth_getCode"
ok did not error
ok has response
ok cacheProvider did see "eth_getCode"
ok cacheProvider did handle "eth_getCode"
ok handlingProvider did NOT see "eth_getCode"
ok handlingProvider did NOT handle "eth_getCode"
# cache - getCode for an unspecified block, then for the latest, should return cached response on second request
ok did not error
ok has response
ok cacheProvider did see "eth_getCode"
ok cacheProvider did NOT handle "eth_getCode"
ok handlingProvider did see "eth_getCode"
ok handlingProvider did handle "eth_getCode"
ok did not error
ok has response
ok cacheProvider did see "eth_getCode"
ok cacheProvider did handle "eth_getCode"
ok handlingProvider did NOT see "eth_getCode"
ok handlingProvider did NOT handle "eth_getCode"
# cache - getBlockForNumber for latest then block
ok did not error
ok has response
ok cacheProvider did see "eth_getBlockByNumber"
ok cacheProvider did NOT handle "eth_getBlockByNumber"
ok handlingProvider did see "eth_getBlockByNumber"
ok handlingProvider did handle "eth_getBlockByNumber"
ok did not error
ok has response
ok cacheProvider did see "eth_getBlockByNumber"
ok cacheProvider did handle "eth_getBlockByNumber"
ok handlingProvider did NOT see "eth_getBlockByNumber"
ok handlingProvider did NOT handle "eth_getBlockByNumber"
# cache - getBlockForNumber for latest then block
ok did not error
ok has response
ok cacheProvider did see "eth_getBlockByNumber"
ok cacheProvider did NOT handle "eth_getBlockByNumber"
ok handlingProvider did see "eth_getBlockByNumber"
ok handlingProvider did handle "eth_getBlockByNumber"
ok did not error
ok has response
ok cacheProvider did see "eth_getBlockByNumber"
ok cacheProvider did handle "eth_getBlockByNumber"
ok handlingProvider did NOT see "eth_getBlockByNumber"
ok handlingProvider did NOT handle "eth_getBlockByNumber"
# cache - getBlockForNumber for then block
ok did not error
ok has response
ok cacheProvider did see "eth_getBlockByNumber"
ok cacheProvider did NOT handle "eth_getBlockByNumber"
ok handlingProvider did see "eth_getBlockByNumber"
ok handlingProvider did handle "eth_getBlockByNumber"
ok did not error
ok has response
ok cacheProvider did see "eth_getBlockByNumber"
ok cacheProvider did handle "eth_getBlockByNumber"
ok handlingProvider did NOT see "eth_getBlockByNumber"
ok handlingProvider did NOT handle "eth_getBlockByNumber"
# cache - getBlockForNumber for block
ok did not error
ok has response
ok cacheProvider did see "eth_getBlockByNumber"
ok cacheProvider did NOT handle "eth_getBlockByNumber"
ok handlingProvider did see "eth_getBlockByNumber"
ok handlingProvider did handle "eth_getBlockByNumber"
ok did not error
ok has response
ok cacheProvider did see "eth_getBlockByNumber"
ok cacheProvider did handle "eth_getBlockByNumber"
ok handlingProvider did NOT see "eth_getBlockByNumber"
ok handlingProvider did NOT handle "eth_getBlockByNumber"
# cache - getBlockForNumber for block
ok did not error
ok has response
ok cacheProvider did see "eth_getBlockByNumber"
ok cacheProvider did NOT handle "eth_getBlockByNumber"
ok handlingProvider did see "eth_getBlockByNumber"
ok handlingProvider did handle "eth_getBlockByNumber"
ok did not error
ok has response
ok cacheProvider did see "eth_getBlockByNumber"
ok cacheProvider did handle "eth_getBlockByNumber"
ok handlingProvider did NOT see "eth_getBlockByNumber"
ok handlingProvider did NOT handle "eth_getBlockByNumber"
# cache - getStorageAt for same block should cache
ok did not error
ok has response
ok cacheProvider did see "eth_getStorageAt"
ok cacheProvider did NOT handle "eth_getStorageAt"
ok handlingProvider did see "eth_getStorageAt"
ok handlingProvider did handle "eth_getStorageAt"
ok did not error
ok has response
ok cacheProvider did see "eth_getStorageAt"
ok cacheProvider did handle "eth_getStorageAt"
ok handlingProvider did NOT see "eth_getStorageAt"
ok handlingProvider did NOT handle "eth_getStorageAt"
# cache - getStorageAt for different block should not cache
ok did not error
ok has response
ok cacheProvider did see "eth_getStorageAt"
ok cacheProvider did NOT handle "eth_getStorageAt"
ok handlingProvider did see "eth_getStorageAt"
ok handlingProvider did handle "eth_getStorageAt"
ok did not error
ok has response
ok cacheProvider did see "eth_getStorageAt"
ok cacheProvider did handle "eth_getStorageAt"
ok handlingProvider did NOT see "eth_getStorageAt"
ok handlingProvider did NOT handle "eth_getStorageAt"
# inflight cache - getBalance for latest
ok did not error
ok has responses
ok cacheProvider did see "eth_getBalance"
ok cacheProvider did NOT handle "eth_getBalance"
ok handlingProvider did see "eth_getBalance"
ok handlingProvider did handle "eth_getBalance"
# inflight cache - getBlock for latest
ok did not error
ok has responses
ok cacheProvider did see "eth_getBlockByNumber"
ok cacheProvider did NOT handle "eth_getBlockByNumber"
ok handlingProvider did see "eth_getBlockByNumber"
ok handlingProvider did handle "eth_getBlockByNumber"
# inflight cache - getBlock for latest then
ok did not error
ok has responses
ok cacheProvider did see "eth_getBlockByNumber"
ok cacheProvider did NOT handle "eth_getBlockByNumber"
ok handlingProvider did see "eth_getBlockByNumber"
ok handlingProvider did handle "eth_getBlockByNumber"
# filters - basic block filter
ok did not error
ok has response
ok filterProvider did see "eth_newBlockFilter"
ok filterProvider did handle "eth_newBlockFilter"
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok correct result
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok did not error
# filters - log filter - basic
ok did not error
ok has response
ok filterProvider did see "eth_newFilter"
ok filterProvider did handle "eth_newFilter"
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok correct result
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok did not error
# filters - log filter - mixed case
ok did not error
ok has response
ok filterProvider did see "eth_newFilter"
ok filterProvider did handle "eth_newFilter"
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok correct result
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok did not error
# filters - log filter - address array
ok did not error
ok has response
ok filterProvider did see "eth_newFilter"
ok filterProvider did handle "eth_newFilter"
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok correct result
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok did not error
# filters - log filter - and logic
ok did not error
ok has response
ok filterProvider did see "eth_newFilter"
ok filterProvider did handle "eth_newFilter"
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok correct result
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok did not error
# filters - log filter - or logic
ok did not error
ok has response
ok filterProvider did see "eth_newFilter"
ok filterProvider did handle "eth_newFilter"
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok correct result
ok correct result
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok did not error
# filters - log filter - wildcard logic
ok did not error
ok has response
ok filterProvider did see "eth_newFilter"
ok filterProvider did handle "eth_newFilter"
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok correct result
ok correct result
ok did not error
ok did not error
ok has response
ok filterProvider did see "eth_getFilterChanges"
ok filterProvider did handle "eth_getFilterChanges"
ok correct number of results
ok did not error
# filters - eth_getFilterLogs called with non log filter id should return []
ok did not error
ok has response
ok filterProvider did see "eth_newBlockFilter"
ok filterProvider did handle "eth_newBlockFilter"
ok did not error
ok has response
ok has response.result
ok filterProvider did see "eth_getFilterLogs
ok filterProvider did handle "eth_getFilterLogs
ok eth_getFilterLogs returned an empty result for a non log filter
ok did not error
# subscriptions - basic block subscription
ok did not error
ok has response
ok subscriptionSubprovider did see "eth_subscribe"
ok subscriptionSubprovider did handle "eth_subscribe"
ok did not error
ok did not error
ok has notification
ok notification has correct subscription id
ok correct result
ok did not error
ok did not error
# subscriptions - log subscription - basic
ok did not error
ok has response
ok subscriptionSubprovider did see "eth_subscribe"
ok subscriptionSubprovider did handle "eth_subscribe"
ok did not error
ok did not error
ok has notification
ok notification has correct subscription id
ok correct result
ok did not error
ok did not error
# subscriptions - log subscription - and logic
ok did not error
ok has response
ok subscriptionSubprovider did see "eth_subscribe"
ok subscriptionSubprovider did handle "eth_subscribe"
ok did not error
ok did not error
ok has notification
ok notification has correct subscription id
ok correct result
ok did not error
ok did not error
# subscriptions - log subscription - or logic
ok did not error
ok has response
ok subscriptionSubprovider did see "eth_subscribe"
ok subscriptionSubprovider did handle "eth_subscribe"
ok did not error
ok did not error
ok has notification
ok notification has correct subscription id
ok correct result
ok did not error
ok did not error
ok has notification
ok correct result
ok did not error
ok did not error
# subscriptions - log subscription - wildcard logic
ok did not error
ok has response
ok subscriptionSubprovider did see "eth_subscribe"
ok subscriptionSubprovider did handle "eth_subscribe"
ok did not error
ok did not error
ok has notification
ok notification has correct subscription id
ok correct result
ok did not error
ok did not error
ok has notification
ok correct result
ok did not error
ok did not error
# tx sig
ok did not error
ok has response
ok providerA did see "signTransaction"
ok providerA did handle "signTransaction"
ok providerB did see "eth_getTransactionCount"
ok providerB did NOT handle "eth_getTransactionCount"
ok providerC did see "eth_getTransactionCount"
ok providerC did handle "eth_getTransactionCount"
ok providerB did see "eth_gasPrice"
ok providerB did handle "eth_gasPrice"
ok providerC did see "eth_sendRawTransaction"
ok providerC did handle "eth_sendRawTransaction"
# no such account
ok did error
# sign message
ok did not error
ok has response
ok signed response is correct
# sign message personal_sign - kumavis fml manual test I
ok null
ok has response
ok rpc result is as expected
# sign message personal_sign - kumavis fml manual test I
ok null
ok has response
ok rpc result is as expected
# sign message personal_sign - kumavis fml manual test II
ok null
ok has response
ok rpc result is as expected
# sign message personal_sign - kumavis fml manual test II
ok null
ok has response
ok rpc result is as expected
# sign message personal_sign - kumavis fml manual test III
ok null
ok has response
ok rpc result is as expected
# sign message personal_sign - kumavis fml manual test III
ok null
ok has response
ok rpc result is as expected
# recover message personal_ecRecover - geth kumavis manual I recover
ok null
ok has response
ok rpc result is as expected
# recover message personal_ecRecover - geth kumavis manual II recover
ok null
ok has response
ok rpc result is as expected
# sign message eth_signTypedData - sign typed message
ok null
ok has response
ok rpc result is as expected
# sender validation, with mixed-case
ok correctly validated sender
# Sanitizer removes unknown keys
ok should be falsy
ok should be equal
ok should be equal
ok should be equal
ok should be equal
ok should be equal
ok no error
ok result was received correctly
# binary search eth_estimateGas implementation
ok did not error
ok has response
ok properly calculates gas needed
ok ran expected number of iterations
ok did not error
ok has response
ok properly calculates gas needed
ok ran expected number of iterations
ok did not error
ok has response
ok properly calculates gas needed
ok ran expected number of iterations
ok did not error ..
# tests
# pass # ok
然后根目录下我们能够看见有一个example.js,对其进行修改:
const Ethjs = require('ethjs')
//const ProviderEngine = require('./index.js')//这里没使用到这个,因为zero.js中已经调用它,你可以自己使用这个来add自己想添加的Subprovider,设置自己的providerEngine
const ZeroClientProvider = require('./zero.js')//已经将ProviderEngine需要的Subprovider都add进去了 // create engine
const providerEngine = ZeroClientProvider({
// supports http and websockets
// but defaults to infura's mainnet rest api
// rpcUrl: 'https://mainnet.infura.io',
rpcUrl: 'http://localhost:7545',//连接本地的ganache
// rpcUrl: 'wss://mainnet.infura.io/ws',
// rpcUrl: 'ws://localhost:8545/ws',
}) // use the provider to instantiate Ethjs, Web3, etc
const eth = new Ethjs(providerEngine) // log new blocks
providerEngine.on('block', function(block) {
const blockNumber = Number.parseInt(block.number.toString('hex'), )
const blockHash = `0x${block.hash.toString('hex')}`
console.log(`block: #${blockNumber} ${blockHash}`)
})
然后在终端进行运行:
userdeMacBook-Pro:provider-engine-master user$ node example.js
block: # 0x9f19e5f94819dd3edba2b0ae9d08f9c7d93b507aef26ede53febf78fea06ae8d
该block是ganache上初始化生成的:
然后下面就分析下其的代码来学习这个是怎么实现的:
provider-engine/index.js
const EventEmitter = require('events').EventEmitter
const inherits = require('util').inherits
const ethUtil = require('ethereumjs-util')
const EthBlockTracker = require('eth-block-tracker') //看本博客MetaMask/eth-block-tracker
const map = require('async/map')
const eachSeries = require('async/eachSeries')
const Stoplight = require('./util/stoplight.js')
const cacheUtils = require('./util/rpc-cache-utils.js')
const createPayload = require('./util/create-payload.js')
const noop = function(){} module.exports = Web3ProviderEngine inherits(Web3ProviderEngine, EventEmitter) function Web3ProviderEngine(opts) {//
const self = this
EventEmitter.call(self)
self.setMaxListeners()
// parse options
opts = opts || {} // block polling
const directProvider = { sendAsync: self._handleAsync.bind(self) } //4 设置sendAsync方法,当以运行sendAsync就会去运行self._handleAsync
const blockTrackerProvider = opts.blockTrackerProvider || directProvider //5 设置区块跟踪器跟踪的provider
self._blockTracker = opts.blockTracker || new EthBlockTracker({ //6 设置blockTracker,如果没有则根据provider生成
provider: blockTrackerProvider,
pollingInterval: opts.pollingInterval || ,
}) // handle new block
self._blockTracker.on('block', (jsonBlock) => {//监听block,当生成block就会触发回调
const bufferBlock = toBufferBlock(jsonBlock)//并将block中数据值转换成buffer格式
self._setCurrentBlock(bufferBlock) //然后将该区块记录下来
}) // emit block events from the block tracker
self._blockTracker.on('block', self.emit.bind(self, 'rawBlock'))//监听'block'事件,触发时触发EventEmitter的'rawBlock'事件
self._blockTracker.on('sync', self.emit.bind(self, 'sync'))
self._blockTracker.on('latest', self.emit.bind(self, 'latest')) // set initialization blocker
self._ready = new Stoplight()
// unblock initialization after first block
self._blockTracker.once('block', () => {
self._ready.go()
})
// local state
self.currentBlock = null
self._providers = []
} // public Web3ProviderEngine.prototype.start = function(cb = noop){
const self = this
// start block polling
self._blockTracker.start().then(cb).catch(cb)
} Web3ProviderEngine.prototype.stop = function(){
const self = this
// stop block polling
self._blockTracker.stop()
} Web3ProviderEngine.prototype.addProvider = function(source){
const self = this
self._providers.push(source)//在zero.js处会调用engine.addProvider(各类subproviders),这些subproviders会存放在self._providers
source.setEngine(this) //调用该self._providers的setEngine,
} Web3ProviderEngine.prototype.send = function(payload){//说明这个Web3ProviderEngine的方法都是异步的
throw new Error('Web3ProviderEngine does not support synchronous requests.')
} Web3ProviderEngine.prototype.sendAsync = function(payload, cb){
const self = this
self._ready.await(function(){ if (Array.isArray(payload)) {
// handle batch
map(payload, self._handleAsync.bind(self), cb)
} else {
// handle single
self._handleAsync(payload, cb)
} })
} // private Web3ProviderEngine.prototype._handleAsync = function(payload, finished) {//
var self = this
var currentProvider = -1 //就是现在并没有添加任何的subproviders
var result = null
var error = null var stack = [] next() function next(after) {
currentProvider +=
stack.unshift(after)//unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度,stack中存储end之前要运行的操作after // Bubbled down as far as we could go, and the request wasn't
// handled. Return an error.
if (currentProvider >= self._providers.length) {//如果此时的currentProvider的值大于self._providers的长度,说明现有的subproviders不能够解决该payload
end(new Error('Request for method "' + payload.method + '" not handled by any subprovider. Please check your subprovider configuration to ensure this method is handled.'))
} else {
try {
var provider = self._providers[currentProvider]//获取对应的subproviders
provider.handleRequest(payload, next, end)//然后运行该subproviders的handleRequest,如果调用的method不是当前的provider能够解决的,就会重新调用next(),查找下一个subproviders是否能够解决
} catch (e) {
end(e)
}
}
} function end(_error, _result) {
error = _error
result = _result eachSeries(stack, function(fn, callback) {//eachSeries(arr, iterator, [callback]) if (fn) {
fn(error, result, callback)
} else {
callback()
}
}, function() {//将stack数组中的fn迭代运行后,就调用最后这个回调将运行结果输出 // console.log('COMPLETED:', payload)
// console.log('RESULT: ', result) var resultObj = {
id: payload.id,
jsonrpc: payload.jsonrpc,
result: result
} if (error != null) {
resultObj.error = {
message: error.stack || error.message || error,
code: -
}
// respond with both error formats
finished(error, resultObj)
} else {
finished(null, resultObj)
}
})
}
} //
// from remote-data
// Web3ProviderEngine.prototype._setCurrentBlock = function(block){
const self = this
self.currentBlock = block
self.emit('block', block)//触发block事件
} // util function toBufferBlock (jsonBlock) {//将block中数据值转换成buffer格式
return {
number: ethUtil.toBuffer(jsonBlock.number),
hash: ethUtil.toBuffer(jsonBlock.hash),
parentHash: ethUtil.toBuffer(jsonBlock.parentHash),
nonce: ethUtil.toBuffer(jsonBlock.nonce),
mixHash: ethUtil.toBuffer(jsonBlock.mixHash),
sha3Uncles: ethUtil.toBuffer(jsonBlock.sha3Uncles),
logsBloom: ethUtil.toBuffer(jsonBlock.logsBloom),
transactionsRoot: ethUtil.toBuffer(jsonBlock.transactionsRoot),
stateRoot: ethUtil.toBuffer(jsonBlock.stateRoot),
receiptsRoot: ethUtil.toBuffer(jsonBlock.receiptRoot || jsonBlock.receiptsRoot),
miner: ethUtil.toBuffer(jsonBlock.miner),
difficulty: ethUtil.toBuffer(jsonBlock.difficulty),
totalDifficulty: ethUtil.toBuffer(jsonBlock.totalDifficulty),
size: ethUtil.toBuffer(jsonBlock.size),
extraData: ethUtil.toBuffer(jsonBlock.extraData),
gasLimit: ethUtil.toBuffer(jsonBlock.gasLimit),
gasUsed: ethUtil.toBuffer(jsonBlock.gasUsed),
timestamp: ethUtil.toBuffer(jsonBlock.timestamp),
transactions: jsonBlock.transactions,
}
provider-engine/zero.js
const ProviderEngine = require('./index.js')
const DefaultFixture = require('./subproviders/default-fixture.js')//设置静态文件的默认存储区域
const NonceTrackerSubprovider = require('./subproviders/nonce-tracker.js')
const CacheSubprovider = require('./subproviders/cache.js')
const FilterSubprovider = require('./subproviders/filters.js')
const SubscriptionSubprovider = require('./subproviders/subscriptions')
const InflightCacheSubprovider = require('./subproviders/inflight-cache')
const HookedWalletSubprovider = require('./subproviders/hooked-wallet.js')
const SanitizingSubprovider = require('./subproviders/sanitizer.js')
const InfuraSubprovider = require('./subproviders/infura.js')
const FetchSubprovider = require('./subproviders/fetch.js')
const WebSocketSubprovider = require('./subproviders/websocket.js')
//zero将该添加进的subproviders都添加进来了 module.exports = ZeroClientProvider function ZeroClientProvider(opts = {}){//
const connectionType = getConnectionType(opts)// const engine = new ProviderEngine(opts.engineParams)//3 engineParams是对engine的设置,如果没有就使用默认定义,设置Web3ProviderEngine //7 设置相应的Subprovider,将其添加到Web3ProviderEngine中
// static
const staticSubprovider = new DefaultFixture(opts.static)
engine.addProvider(staticSubprovider) // nonce tracker
engine.addProvider(new NonceTrackerSubprovider()) // sanitization 卫生处理??
const sanitizer = new SanitizingSubprovider()
engine.addProvider(sanitizer) // cache layer
const cacheSubprovider = new CacheSubprovider()
engine.addProvider(cacheSubprovider) // filters + subscriptions
// for websockets, only polyfill filters
if (connectionType === 'ws') {
const filterSubprovider = new FilterSubprovider()
engine.addProvider(filterSubprovider)
// otherwise, polyfill both subscriptions and filters
} else {
const filterAndSubsSubprovider = new SubscriptionSubprovider()
// forward subscription events through provider
filterAndSubsSubprovider.on('data', (err, notification) => {
engine.emit('data', err, notification)
})
engine.addProvider(filterAndSubsSubprovider)
} // inflight cache
const inflightCache = new InflightCacheSubprovider()
engine.addProvider(inflightCache) // id mgmt
const idmgmtSubprovider = new HookedWalletSubprovider({ //钱包,只实现了一部分的功能
// accounts
getAccounts: opts.getAccounts,
// transactions
processTransaction: opts.processTransaction,
approveTransaction: opts.approveTransaction,
signTransaction: opts.signTransaction,
publishTransaction: opts.publishTransaction,
// messages
// old eth_sign
processMessage: opts.processMessage,
approveMessage: opts.approveMessage,
signMessage: opts.signMessage,
// new personal_sign
processPersonalMessage: opts.processPersonalMessage,
processTypedMessage: opts.processTypedMessage,
approvePersonalMessage: opts.approvePersonalMessage,
approveTypedMessage: opts.approveTypedMessage,
signPersonalMessage: opts.signPersonalMessage,
signTypedMessage: opts.signTypedMessage,
personalRecoverSigner: opts.personalRecoverSigner,
})
engine.addProvider(idmgmtSubprovider) // data source
const dataSubprovider = opts.dataSubprovider || createDataSubprovider(connectionType, opts)
// for websockets, forward subscription events through provider
if (connectionType === 'ws') {
dataSubprovider.on('data', (err, notification) => {
engine.emit('data', err, notification)
})
}
engine.addProvider(dataSubprovider) // start polling
if (!opts.stopped) {
engine.start() //8 打开engine
} return engine } function createDataSubprovider(connectionType, opts) {
const { rpcUrl, debug } = opts // default to infura
if (!connectionType) {//如果使用的不是http和ws,就使用infura进行连接
return new InfuraSubprovider()
}
if (connectionType === 'http') {
return new FetchSubprovider({ rpcUrl, debug })
}
if (connectionType === 'ws') {
return new WebSocketSubprovider({ rpcUrl, debug })
} throw new Error(`ProviderEngine - unrecognized connectionType "${connectionType}"`)
} function getConnectionType({ rpcUrl }) {//2检查传给zero的参数是否正确
if (!rpcUrl) return undefined//2如果没有传入rpcUrl,那么就返回连接失败 const protocol = rpcUrl.split(':')[].toLowerCase() //2要将协议处小写,因为大写将不成功,如需要将HTTP换成http
switch (protocol) {
case 'http':
case 'https': //2 http/https返回的type为http
return 'http'
case 'ws':
case 'wss'://2 ws/wss返回的类型是ws
return 'ws'
default: //2 否则就传无法识别协议类型
throw new Error(`ProviderEngine - unrecognized protocol in "${rpcUrl}"`)
}
}
这两个是核心代码,试着使用一下
const ProviderEngine = require('web3-provider-engine')
const CacheSubprovider = require('web3-provider-engine/subproviders/cache.js')
const FixtureSubprovider = require('web3-provider-engine/subproviders/fixture.js')
const FilterSubprovider = require('web3-provider-engine/subproviders/filters.js')
const VmSubprovider = require('web3-provider-engine/subproviders/vm.js')
const HookedWalletSubprovider = require('web3-provider-engine/subproviders/hooked-wallet.js')
const NonceSubprovider = require('web3-provider-engine/subproviders/nonce-tracker.js')
const RpcSubprovider = require('web3-provider-engine/subproviders/rpc.js')
const createPayload = require('web3-provider-engine/util/create-payload.js')
const ethUtil = require('ethereumjs-util')
const Transaction = require('ethereumjs-tx') var engine = new ProviderEngine()
// var web3 = new Web3(engine) var privateKey = new Buffer.from('9af0f29100b9575ffe7d5596d87003b6ada89076ca84342f1fe57d85acde4ca6', 'hex')
var address = new Buffer.from('0x3455f15cc11F2E77c055f931A6C918ccc7c18fd8', 'hex')
var addressHex = '0x'+address.toString('hex') // static results
engine.addProvider(new FixtureSubprovider({
web3_clientVersion: 'ProviderEngine/v0.0.0/javascript',
net_listening: true,
eth_hashrate: '0x00',
eth_mining: false,
eth_syncing: true,
})) // cache layer
engine.addProvider(new CacheSubprovider()) // filters
engine.addProvider(new FilterSubprovider()) // pending nonce
engine.addProvider(new NonceSubprovider()) // vm
engine.addProvider(new VmSubprovider()) // id mgmt
engine.addProvider(new HookedWalletSubprovider({
getAccounts: function(cb){
cb(null, [addressHex])
},
// approveTransaction: function(cb){ ... },
signTransaction: function(txParams, cb){
var tx = new Transaction(txParams)
tx.sign(privateKey)
var rawTx = '0x'+tx.serialize().toString('hex')
cb(null, rawTx)
},
})) // data source
engine.addProvider(new RpcSubprovider({
rpcUrl: 'http://localhost:7545',
eth_gasPrice: '0x1234',
eth_getTransactionCount: '0x00',
eth_sendRawTransaction: function(payload, next, done){
var rawTx = ethUtil.toBuffer(payload.params[])
var tx = new Transaction(rawTx)
var hash = '0x'+tx.hash().toString('hex')
done(null, hash)
}
})) // log new blocks
engine.on('block', function(block){
console.log('================================')
console.log('BLOCK CHANGED:', '#'+block.number.toString('hex'), '0x'+block.hash.toString('hex'))
console.log('================================')
}) // network connectivity error
engine.on('error', function(err){
// report connectivity errors
console.error(err.stack)
}) var txPayload1 = {
method: 'eth_sendTransaction',
params: [{
from: addressHex,
to: addressHex,
value: '0x01',
gas: '0x6691b7',
}]
} // start polling for blocks
engine.start() engine.sendAsync(createPayload(txPayload1), function(err, response){
if(!err){
console.log(response)
}else{
console.log(err.message+err.stack)
} })
然后运行可得:
userdeMacBook-Pro:test-provider user$ supervisor --harmony main.js Running node-supervisor with
program '--harmony main.js'
--watch '.'
--extensions 'node,js'
--exec 'node' Starting child process with 'node --harmony main.js'
Watching directory '/Users/user/test-provider' for changes.
Press rs for restarting the process.
================================
BLOCK CHANGED: # 0x9f19e5f94819dd3edba2b0ae9d08f9c7d93b507aef26ede53febf78fea06ae8d
================================
{ id: ,
jsonrpc: '2.0',
result:
'0xe1b85b3a4f7e02f2865d7b087698ef5428a0f9333b70fcef761e844051471737' }
================================
BLOCK CHANGED: # 0x93b6468b8a3176f15a2bf89fbe42e873f54e681e171605adf44aeb6e01582041
================================
从这里我们可以看出来,这个provider-engine的作用其实也就相当于自己定义了一个自己的web3 provider,然后就能够调用相应的函数了。
只是相应的函数的调用要自己在相应的Subprovider进行定义,不同Subprovider对应的函数是:
Current RPC method support:
static
- web3_clientVersion
- net_version
- net_listening
- net_peerCount
- eth_protocolVersion
- eth_hashrate
- eth_mining
- eth_syncing
filters
- eth_newBlockFilter
- eth_newPendingTransactionFilter
- eth_newFilter
- eth_uninstallFilter
- eth_getFilterLogs
- eth_getFilterChanges
accounts manager
- eth_coinbase
- eth_accounts
- eth_sendTransaction
- eth_sign
- eth_signTypedData
vm
- eth_call
- eth_estimateGas
db source
- db_putString
- db_getString
- db_putHex
- db_getHex
compiler
- eth_getCompilers
- eth_compileLLL
- eth_compileSerpent
- eth_compileSolidity
shh gateway
- shh_version
- shh_post
- shh_newIdentity
- shh_hasIdentity
- shh_newGroup
- shh_addToGroup
data source ( fallback to rpc )
- eth_gasPrice
- eth_blockNumber
- eth_getBalance
- eth_getBlockByHash
- eth_getBlockByNumber
- eth_getBlockTransactionCountByHash
- eth_getBlockTransactionCountByNumber
- eth_getCode
- eth_getStorageAt
- eth_getTransactionByBlockHashAndIndex
- eth_getTransactionByBlockNumberAndIndex
- eth_getTransactionByHash
- eth_getTransactionCount
- eth_getTransactionReceipt
- eth_getUncleByBlockHashAndIndex
- eth_getUncleByBlockNumberAndIndex
- eth_getUncleCountByBlockHash
- eth_getUncleCountByBlockNumber
- eth_sendRawTransaction
- eth_getLogs ( not used in web3.js )
( not supported )
- eth_getWork
- eth_submitWork
- eth_submitHashrate ( not used in web3.js )
可以看test代码了解一下这个到底怎么用:
npm run test 中有一个警告:
(node:) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
MetaMask/provider-engine-2-代码的更多相关文章
- 游戏音频技术备忘 (五)Wwise Unreal Engine 集成代码浅析 二
AkAmbientSound类的实现 Unreal Engine提供了一个基本对象的构造器ObjectInitializer,一般来说用户创建的类总是拥有很多变量,因此 AkAmbientSound ...
- 游戏音频技术备忘 (四) Wwise Unreal Engine 集成代码浅析 (一)
在Engine\Plugins\Wwise\Source下为主要Wwise相关代码,AkAudio文件夹下为运行时相关代码,AudiokineticTools下为编辑器工具相关代码,Audiokine ...
- arcgis engine 基础代码
1.开始编辑,save feature property,停止编辑 IWorkspace workspace = ((IDataset)pFeatureClass).Workspace;IWorksp ...
- MetaMask/provider-engine-1
https://github.com/MetaMask/provider-engine 在学习这个之前应该先看一下什么是zero-client,MetaMask/zero-client Web3 Pr ...
- AngularJS 之 Factory vs Service vs Provider【转】
英文原文:AngularJS: Factory vs Service vs Provider 当你初试 Angular 时,很自然地就会往 controller 和 scope 里堆满不必要的逻辑.一 ...
- AngularJS 之 Factory、Service、Provider
当你初试 Angular 时,很自然地就会往 controller 和 scope 里堆满不必要的逻辑.一定要早点意识到,controller 这一层应该很薄:也就是说,应用里大部分的业务逻辑和持久化 ...
- Android开发-API指南-Content Provider
Content Providers 英文原文:http://developer.android.com/guide/topics/providers/content-providers.html 采集 ...
- AngularJS之Factory vs Service vs Provider
原文 http://www.linuxeden.com/html/news/20140509/151538.html 当你初试 Angular 时,很自然地就会往 controller 和 scop ...
- 游戏音频技术备忘 (三) 集成Wwise到Unreal Engine
当前受众较广的商业游戏引擎有 Unreal Engine.Unity.cocos2d-x等,在音频领域的第三方中间件则有Wwise.FMOD.Criware等,言多且烦,我们首先集成Wwise到 Un ...
- MetaMask/metamask-extension-provider
用来探测你的浏览器中有没有安装metamask插件 https://github.com/MetaMask/metamask-extension-provider MetaMask Extension ...
随机推荐
- 为什么要用lock 【readonly】object?为什么不要lock(this)?
一. 为什么要用lock,lock了什么? 当我们使用线程的时候,效率最高的方式当然是异步,即各个线程同时运行,其间不相互依赖和等待.但当不同的线程都需要访问某个资源的时候,就需要同步机制了.也就是说 ...
- linux_shell_传递参数
在执行shell脚本时可以传递参数: 脚本获取参数的格式为:$0 $1 $2 ...其中$1 为传递的第一个参数 而$0 接受的是./test.sh 这个东西 代码:例: #!/bin/bash ...
- Java的接口和抽象类
对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的时候会以为它们可以随意互换使用, ...
- node.js(express)连接mongoDB入门指导
一.写在前面 人人都想成为全栈码农,作为一个web前端开发人员,通往全栈的简洁之路,貌似就是node.js了.前段时间学习了node.js,来谈谈新手如何快速的搭建自己的web服务,开启全栈之路. 二 ...
- 【读书笔记】iOS-网络-理解错误源
考虑一个字节是如何从设备发往运程服务器以及如何从远程服务器将这个字节接收到设备,这个过程只需要几百毫秒时间,不过确要求网络设备都能正常工作才行.设备网络和网络互联的复杂性导致了分层网络的产生.分层网络 ...
- 从零开始学习html(十一)CSS盒模型——下
六.盒模型--边框(一) <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type& ...
- 免费的协作和协同办公软件平台onlyoffice轻松部署
一般说,协同和协作是不同的,协同是指文档基于一个版本,大家都是基于这个版本来添加,而且大家只能引用这个文档,却不能在上面直接添加,而且只能一个人添加,即锁住,不让其他人添加了. 而协作就不同了,大家同 ...
- JSP指示元素<%@ %> 与指示类型
JSP提示元素 <%@ 指示类型 [属性="值"]%> 指示类型 指示类型有三种,分别是taglib.include.page taglib指示类型 用于引入标签库 ...
- AWS CSAA -- 04 AWS Object Storage and CDN - S3 Glacier and CloudFront(二)
015 Version Control - Lab 016 Cross Region Replication 017 Lifecycle Management Glacier - Lab 018 C ...
- Mongodb Windows 集群
我在一台Windows机器下搭建了一个 Replica Sets + Sharding 测试集群环境,以此作为我后续对于Mongodb更进一步学习的实验平台. 只有一台windows机器,配置方案:1 ...