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
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-代码的更多相关文章

  1. 游戏音频技术备忘 (五)Wwise Unreal Engine 集成代码浅析 二

    AkAmbientSound类的实现 Unreal Engine提供了一个基本对象的构造器ObjectInitializer,一般来说用户创建的类总是拥有很多变量,因此 AkAmbientSound  ...

  2. 游戏音频技术备忘 (四) Wwise Unreal Engine 集成代码浅析 (一)

    在Engine\Plugins\Wwise\Source下为主要Wwise相关代码,AkAudio文件夹下为运行时相关代码,AudiokineticTools下为编辑器工具相关代码,Audiokine ...

  3. arcgis engine 基础代码

    1.开始编辑,save feature property,停止编辑 IWorkspace workspace = ((IDataset)pFeatureClass).Workspace;IWorksp ...

  4. MetaMask/provider-engine-1

    https://github.com/MetaMask/provider-engine 在学习这个之前应该先看一下什么是zero-client,MetaMask/zero-client Web3 Pr ...

  5. AngularJS 之 Factory vs Service vs Provider【转】

    英文原文:AngularJS: Factory vs Service vs Provider 当你初试 Angular 时,很自然地就会往 controller 和 scope 里堆满不必要的逻辑.一 ...

  6. AngularJS 之 Factory、Service、Provider

    当你初试 Angular 时,很自然地就会往 controller 和 scope 里堆满不必要的逻辑.一定要早点意识到,controller 这一层应该很薄:也就是说,应用里大部分的业务逻辑和持久化 ...

  7. Android开发-API指南-Content Provider

    Content Providers 英文原文:http://developer.android.com/guide/topics/providers/content-providers.html 采集 ...

  8. AngularJS之Factory vs Service vs Provider

    原文  http://www.linuxeden.com/html/news/20140509/151538.html 当你初试 Angular 时,很自然地就会往 controller 和 scop ...

  9. 游戏音频技术备忘 (三) 集成Wwise到Unreal Engine

    当前受众较广的商业游戏引擎有 Unreal Engine.Unity.cocos2d-x等,在音频领域的第三方中间件则有Wwise.FMOD.Criware等,言多且烦,我们首先集成Wwise到 Un ...

  10. MetaMask/metamask-extension-provider

    用来探测你的浏览器中有没有安装metamask插件 https://github.com/MetaMask/metamask-extension-provider MetaMask Extension ...

随机推荐

  1. 【JVM】5、JVM内存管理机制

    转自:http://blog.csdn.net/lengyuhong/article/details/5953544 近期看了看Java内存泄露的一些案例,跟原来的几个哥们讨论了一下,深入研究发现JV ...

  2. js获取指定格式的时间字符串

    如下: // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h).分(m).秒(s).季度(q) 可以用 1-2 个占位符, // 年(y)可以用 1- ...

  3. SpringBoot阿里巴巴Fastjson的一些常用配置

    SpringBoot阿里巴巴Fastjson的一些常用配置 @Bean public HttpMessageConverters fastJsonHttpMessageConverters() { F ...

  4. mysql建表以及列属性

    一.整型( int, tinyint, smallint 等 ) ------------------------------------------------------------------- ...

  5. 转载文章CSS3的calc()使用

    calc()对大家来说,或许很陌生,不太会相信calc()是css中的部分.因为看其外表像个函数,既然是函数为何又出现在CSS中呢?这一点也让我百思不得其解,今天有一同事告诉我,说CSS3中有一个属性 ...

  6. python-外观模式

    源码地址:https://github.com/weilanhanf/PythonDesignPatterns 说明: 外观模式又叫做门面模式.在面向对象程序设计中,解耦是一种推崇的理念.但事实上由于 ...

  7. 清除input numer 点击样式

    input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { -webkit-appearance: none; }

  8. memset初始化数组的问题

    今天才搞清楚,memset用于初始化数组,仅能初始化为0值,而不能初始化一个特定的值,这怎么能模糊了呢??? 因此,如果对申请的一段存放数组的内存进行初始化,每个数组元素均初始化为特定的值,必须使用循 ...

  9. Android HandlerThread和IntentService

    HandlerThreadHandlerThread继承了Thread,它是一种可以使用Handler的Thread,它实现也很简单,就是在run中通过Looper.prepare()来创建消息队列, ...

  10. js替换数组中字符串实例

    这个是替换数组中的一个对象字符串: 直接上代码: var aaa=[ {"name":"张珊","sex":"man"} ...