https://github.com/MetaMask/provider-engine
在学习这个之前应该先看一下什么是zero-client,MetaMask/zero-client
Web3 ProviderEngine
Web3 ProviderEngine is a tool for composing your own web3 providers.
这个模块就是用来教你怎么去构建自己的web3 providers的,从之前的其他学习,如mascara和zero-client等中我们都能够看到需要一个自定义的http://localhost:9001 provider,这里就是怎么实现的模块
Composable
Built to be modular - works via a stack of 'sub-providers' which are like normal web3 providers but only handle a subset of rpc methods.
The subproviders can emit new rpc requests in order to handle their own; e.g. eth_call
may trigger eth_getAccountBalance
, eth_getCode
, and others. The provider engine also handles caching of rpc request results.
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') var engine = new ProviderEngine() var web3 = new Web3(engine) // 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){ ... }, approveTransaction: function(cb){ ... }, signTransaction: function(cb){ ... }, })) // data source engine.addProvider(new RpcSubprovider({ rpcUrl: 'https://testrpc.metamask.io/', })) // 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) }) // start polling for blocks engine.start()
When importing in webpack:
import * as Web3ProviderEngine from 'web3-provider-engine'; import * as RpcSource from 'web3-provider-engine/subproviders/rpc'; import * as HookedWalletSubprovider from 'web3-provider-engine/subproviders/hooked-wallet';
Built For Zero-Clients
The Ethereum JSON RPC was not designed to have one node service many clients. However a smaller, lighter subset of the JSON RPC can be used to provide the blockchain data that an Ethereum 'zero-client' node would need to function. We handle as many types of requests locally as possible, and just let data lookups fallback to some data source ( hosted rpc, blockchain api, etc ). Categorically, we don’t want / can’t have the following types of RPC calls go to the network:
Ethereum JSON RPC并不是设计成只有一个结点来服务许多用户的。然而更小、更轻的JSON RPC子集可以不需要使用以太坊'zero-client'的结点需要调用的功能就能够提供区块链数据。我们处理尽可能多的本地类型的请求,并让数据查找回退一些数据源。明确,我们不希望/不可能有以下类型的RPC调用网络
- id mgmt + tx signing (requires private data)
- filters (requires a stateful data api)
- vm (expensive, hard to scale)