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.jszero.jssubproviders和util文件夹中的所有文件都使用babel转成es5的版本,存放在dist文件夹中。然后分别使用browserify将index.jszero.js转成es5版本的dist/ProviderEngine.jsdist/ZeroClientProvider.js

browserify命令行参数意思:

–transform, -t: 对上层文件进行转换
–entry, -e: 应用程序的入口
–standalone -s: 生成一个UMB的绑定的接口,提供给其他模块使用。

返回:

> web3-provider-engine@14.1.0 prepublish /Users/wanghui/provider-engine-master
> npm run build && npm run bundle


> web3-provider-engine@14.1.0 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.0 bundle /Users/wanghui/provider-engine-master
> mkdir -p ./dist && npm run bundle-engine && npm run bundle-zero


> web3-provider-engine@14.1.0 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.0 bundle-zero /Users/wanghui/provider-engine-master
> browserify -s ZeroClientProvider -e zero.js -t [ babelify --presets [ es2015 ] ] > dist/ZeroClientProvider.js
View Code

然后运行test:

npm run test

返回:

> web3-provider-engine@14.1.0 test /Users/wanghui/provider-engine-master
> node test/index.js

(node:3033) [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 13
# fallthrough test
ok 1 did not error
ok 2 has response
ok 3 providerA did see "test_rpc"
ok 4 providerA did NOT handle "test_rpc"
ok 5 providerB did see "test_rpc"
ok 6 providerB did handle "test_rpc"
ok 7 providerC did NOT see "test_rpc"
ok 8 providerC did NOT handle "test_rpc"
# cacheIdentifierForPayload for latest block
ok 9 cacheIds are unique
# blockTagForPayload for different methods
ok 10 block tag for eth_getBalance is correct
ok 11 block tag for eth_getCode is correct
ok 12 block tag for eth_getTransactionCount is correct
ok 13 block tag for eth_getStorageAt is correct
ok 14 block tag for eth_call is correct
ok 15 block tag for eth_estimateGas is correct
ok 16 block tag for eth_getBlockByNumber is correct
# cache - skipCache - true
ok 17 did not error
ok 18 has response
ok 19 cacheProvider did see "eth_getBalance"
ok 20 cacheProvider did NOT handle "eth_getBalance"
ok 21 handlingProvider did see "eth_getBalance"
ok 22 handlingProvider did handle "eth_getBalance"
ok 23 did not error
ok 24 has response
ok 25 cacheProvider did see "eth_getBalance"
ok 26 cacheProvider did handle "eth_getBalance"
ok 27 handlingProvider did NOT see "eth_getBalance"
ok 28 handlingProvider did NOT handle "eth_getBalance"
# cache - skipCache - false
ok 29 did not error
ok 30 has response
ok 31 cacheProvider did see "eth_getBalance"
ok 32 cacheProvider did NOT handle "eth_getBalance"
ok 33 handlingProvider did see "eth_getBalance"
ok 34 handlingProvider did handle "eth_getBalance"
ok 35 did not error
ok 36 has response
ok 37 cacheProvider did see "eth_getBalance"
ok 38 cacheProvider did handle "eth_getBalance"
ok 39 handlingProvider did NOT see "eth_getBalance"
ok 40 handlingProvider did NOT handle "eth_getBalance"
# cache - getBalance + undefined blockTag
ok 41 did not error
ok 42 has response
ok 43 cacheProvider did see "eth_getBalance"
ok 44 cacheProvider did NOT handle "eth_getBalance"
ok 45 handlingProvider did see "eth_getBalance"
ok 46 handlingProvider did handle "eth_getBalance"
ok 47 did not error
ok 48 has response
ok 49 cacheProvider did see "eth_getBalance"
ok 50 cacheProvider did handle "eth_getBalance"
ok 51 handlingProvider did NOT see "eth_getBalance"
ok 52 handlingProvider did NOT handle "eth_getBalance"
# cache - getBalance + latest blockTag
ok 53 did not error
ok 54 has response
ok 55 cacheProvider did see "eth_getBalance"
ok 56 cacheProvider did NOT handle "eth_getBalance"
ok 57 handlingProvider did see "eth_getBalance"
ok 58 handlingProvider did handle "eth_getBalance"
ok 59 did not error
ok 60 has response
ok 61 cacheProvider did see "eth_getBalance"
ok 62 cacheProvider did handle "eth_getBalance"
ok 63 handlingProvider did NOT see "eth_getBalance"
ok 64 handlingProvider did NOT handle "eth_getBalance"
# cache - getBalance + pending blockTag
ok 65 did not error
ok 66 has response
ok 67 cacheProvider did see "eth_getBalance"
ok 68 cacheProvider did NOT handle "eth_getBalance"
ok 69 handlingProvider did see "eth_getBalance"
ok 70 handlingProvider did handle "eth_getBalance"
ok 71 did not error
ok 72 has response
ok 73 cacheProvider did see "eth_getBalance"
ok 74 cacheProvider did handle "eth_getBalance"
ok 75 handlingProvider did NOT see "eth_getBalance"
ok 76 handlingProvider did NOT handle "eth_getBalance"
# cache - getTransactionByHash for transaction that doesn't exist
ok 77 did not error
ok 78 has response
ok 79 cacheProvider did see "eth_getTransactionByHash"
ok 80 cacheProvider did NOT handle "eth_getTransactionByHash"
ok 81 handlingProvider did see "eth_getTransactionByHash"
ok 82 handlingProvider did handle "eth_getTransactionByHash"
ok 83 did not error
ok 84 has response
ok 85 cacheProvider did see "eth_getTransactionByHash"
ok 86 cacheProvider did handle "eth_getTransactionByHash"
ok 87 handlingProvider did NOT see "eth_getTransactionByHash"
ok 88 handlingProvider did NOT handle "eth_getTransactionByHash"
# cache - getTransactionByHash for transaction that's pending
ok 89 did not error
ok 90 has response
ok 91 cacheProvider did see "eth_getTransactionByHash"
ok 92 cacheProvider did NOT handle "eth_getTransactionByHash"
ok 93 handlingProvider did see "eth_getTransactionByHash"
ok 94 handlingProvider did handle "eth_getTransactionByHash"
ok 95 did not error
ok 96 has response
ok 97 cacheProvider did see "eth_getTransactionByHash"
ok 98 cacheProvider did handle "eth_getTransactionByHash"
ok 99 handlingProvider did NOT see "eth_getTransactionByHash"
ok 100 handlingProvider did NOT handle "eth_getTransactionByHash"
# cache - getTransactionByHash for mined transaction
ok 101 did not error
ok 102 has response
ok 103 cacheProvider did see "eth_getTransactionByHash"
ok 104 cacheProvider did NOT handle "eth_getTransactionByHash"
ok 105 handlingProvider did see "eth_getTransactionByHash"
ok 106 handlingProvider did handle "eth_getTransactionByHash"
ok 107 did not error
ok 108 has response
ok 109 cacheProvider did see "eth_getTransactionByHash"
ok 110 cacheProvider did handle "eth_getTransactionByHash"
ok 111 handlingProvider did NOT see "eth_getTransactionByHash"
ok 112 handlingProvider did NOT handle "eth_getTransactionByHash"
# cache - getCode for latest block, then for earliest block, should not return cached response on second request
ok 113 did not error
ok 114 has response
ok 115 cacheProvider did see "eth_getCode"
ok 116 cacheProvider did NOT handle "eth_getCode"
ok 117 handlingProvider did see "eth_getCode"
ok 118 handlingProvider did handle "eth_getCode"
ok 119 did not error
ok 120 has response
ok 121 cacheProvider did see "eth_getCode"
ok 122 cacheProvider did handle "eth_getCode"
ok 123 handlingProvider did NOT see "eth_getCode"
ok 124 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 125 did not error
ok 126 has response
ok 127 cacheProvider did see "eth_getCode"
ok 128 cacheProvider did NOT handle "eth_getCode"
ok 129 handlingProvider did see "eth_getCode"
ok 130 handlingProvider did handle "eth_getCode"
ok 131 did not error
ok 132 has response
ok 133 cacheProvider did see "eth_getCode"
ok 134 cacheProvider did handle "eth_getCode"
ok 135 handlingProvider did NOT see "eth_getCode"
ok 136 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 137 did not error
ok 138 has response
ok 139 cacheProvider did see "eth_getCode"
ok 140 cacheProvider did NOT handle "eth_getCode"
ok 141 handlingProvider did see "eth_getCode"
ok 142 handlingProvider did handle "eth_getCode"
ok 143 did not error
ok 144 has response
ok 145 cacheProvider did see "eth_getCode"
ok 146 cacheProvider did handle "eth_getCode"
ok 147 handlingProvider did NOT see "eth_getCode"
ok 148 handlingProvider did NOT handle "eth_getCode"
# cache - getCode for an unspecified block, then for the latest, should return cached response on second request
ok 149 did not error
ok 150 has response
ok 151 cacheProvider did see "eth_getCode"
ok 152 cacheProvider did NOT handle "eth_getCode"
ok 153 handlingProvider did see "eth_getCode"
ok 154 handlingProvider did handle "eth_getCode"
ok 155 did not error
ok 156 has response
ok 157 cacheProvider did see "eth_getCode"
ok 158 cacheProvider did handle "eth_getCode"
ok 159 handlingProvider did NOT see "eth_getCode"
ok 160 handlingProvider did NOT handle "eth_getCode"
# cache - getBlockForNumber for latest then block 0
ok 161 did not error
ok 162 has response
ok 163 cacheProvider did see "eth_getBlockByNumber"
ok 164 cacheProvider did NOT handle "eth_getBlockByNumber"
ok 165 handlingProvider did see "eth_getBlockByNumber"
ok 166 handlingProvider did handle "eth_getBlockByNumber"
ok 167 did not error
ok 168 has response
ok 169 cacheProvider did see "eth_getBlockByNumber"
ok 170 cacheProvider did handle "eth_getBlockByNumber"
ok 171 handlingProvider did NOT see "eth_getBlockByNumber"
ok 172 handlingProvider did NOT handle "eth_getBlockByNumber"
# cache - getBlockForNumber for latest then block 1
ok 173 did not error
ok 174 has response
ok 175 cacheProvider did see "eth_getBlockByNumber"
ok 176 cacheProvider did NOT handle "eth_getBlockByNumber"
ok 177 handlingProvider did see "eth_getBlockByNumber"
ok 178 handlingProvider did handle "eth_getBlockByNumber"
ok 179 did not error
ok 180 has response
ok 181 cacheProvider did see "eth_getBlockByNumber"
ok 182 cacheProvider did handle "eth_getBlockByNumber"
ok 183 handlingProvider did NOT see "eth_getBlockByNumber"
ok 184 handlingProvider did NOT handle "eth_getBlockByNumber"
# cache - getBlockForNumber for 0 then block 1
ok 185 did not error
ok 186 has response
ok 187 cacheProvider did see "eth_getBlockByNumber"
ok 188 cacheProvider did NOT handle "eth_getBlockByNumber"
ok 189 handlingProvider did see "eth_getBlockByNumber"
ok 190 handlingProvider did handle "eth_getBlockByNumber"
ok 191 did not error
ok 192 has response
ok 193 cacheProvider did see "eth_getBlockByNumber"
ok 194 cacheProvider did handle "eth_getBlockByNumber"
ok 195 handlingProvider did NOT see "eth_getBlockByNumber"
ok 196 handlingProvider did NOT handle "eth_getBlockByNumber"
# cache - getBlockForNumber for block 0
ok 197 did not error
ok 198 has response
ok 199 cacheProvider did see "eth_getBlockByNumber"
ok 200 cacheProvider did NOT handle "eth_getBlockByNumber"
ok 201 handlingProvider did see "eth_getBlockByNumber"
ok 202 handlingProvider did handle "eth_getBlockByNumber"
ok 203 did not error
ok 204 has response
ok 205 cacheProvider did see "eth_getBlockByNumber"
ok 206 cacheProvider did handle "eth_getBlockByNumber"
ok 207 handlingProvider did NOT see "eth_getBlockByNumber"
ok 208 handlingProvider did NOT handle "eth_getBlockByNumber"
# cache - getBlockForNumber for block 1
ok 209 did not error
ok 210 has response
ok 211 cacheProvider did see "eth_getBlockByNumber"
ok 212 cacheProvider did NOT handle "eth_getBlockByNumber"
ok 213 handlingProvider did see "eth_getBlockByNumber"
ok 214 handlingProvider did handle "eth_getBlockByNumber"
ok 215 did not error
ok 216 has response
ok 217 cacheProvider did see "eth_getBlockByNumber"
ok 218 cacheProvider did handle "eth_getBlockByNumber"
ok 219 handlingProvider did NOT see "eth_getBlockByNumber"
ok 220 handlingProvider did NOT handle "eth_getBlockByNumber"
# cache - getStorageAt for same block should cache
ok 221 did not error
ok 222 has response
ok 223 cacheProvider did see "eth_getStorageAt"
ok 224 cacheProvider did NOT handle "eth_getStorageAt"
ok 225 handlingProvider did see "eth_getStorageAt"
ok 226 handlingProvider did handle "eth_getStorageAt"
ok 227 did not error
ok 228 has response
ok 229 cacheProvider did see "eth_getStorageAt"
ok 230 cacheProvider did handle "eth_getStorageAt"
ok 231 handlingProvider did NOT see "eth_getStorageAt"
ok 232 handlingProvider did NOT handle "eth_getStorageAt"
# cache - getStorageAt for different block should not cache
ok 233 did not error
ok 234 has response
ok 235 cacheProvider did see "eth_getStorageAt"
ok 236 cacheProvider did NOT handle "eth_getStorageAt"
ok 237 handlingProvider did see "eth_getStorageAt"
ok 238 handlingProvider did handle "eth_getStorageAt"
ok 239 did not error
ok 240 has response
ok 241 cacheProvider did see "eth_getStorageAt"
ok 242 cacheProvider did handle "eth_getStorageAt"
ok 243 handlingProvider did NOT see "eth_getStorageAt"
ok 244 handlingProvider did NOT handle "eth_getStorageAt"
# inflight cache - getBalance for latest
ok 245 did not error
ok 246 has responses
ok 247 cacheProvider did see "eth_getBalance"
ok 248 cacheProvider did NOT handle "eth_getBalance"
ok 249 handlingProvider did see "eth_getBalance"
ok 250 handlingProvider did handle "eth_getBalance"
# inflight cache - getBlock for latest
ok 251 did not error
ok 252 has responses
ok 253 cacheProvider did see "eth_getBlockByNumber"
ok 254 cacheProvider did NOT handle "eth_getBlockByNumber"
ok 255 handlingProvider did see "eth_getBlockByNumber"
ok 256 handlingProvider did handle "eth_getBlockByNumber"
# inflight cache - getBlock for latest then 0
ok 257 did not error
ok 258 has responses
ok 259 cacheProvider did see "eth_getBlockByNumber"
ok 260 cacheProvider did NOT handle "eth_getBlockByNumber"
ok 261 handlingProvider did see "eth_getBlockByNumber"
ok 262 handlingProvider did handle "eth_getBlockByNumber"
# filters - basic block filter
ok 263 did not error
ok 264 has response
ok 265 filterProvider did see "eth_newBlockFilter"
ok 266 filterProvider did handle "eth_newBlockFilter"
ok 267 did not error
ok 268 did not error
ok 269 has response
ok 270 filterProvider did see "eth_getFilterChanges"
ok 271 filterProvider did handle "eth_getFilterChanges"
ok 272 correct number of results
ok 273 correct result
ok 274 did not error
ok 275 did not error
ok 276 has response
ok 277 filterProvider did see "eth_getFilterChanges"
ok 278 filterProvider did handle "eth_getFilterChanges"
ok 279 correct number of results
ok 280 did not error
# filters - log filter - basic
ok 281 did not error
ok 282 has response
ok 283 filterProvider did see "eth_newFilter"
ok 284 filterProvider did handle "eth_newFilter"
ok 285 did not error
ok 286 did not error
ok 287 has response
ok 288 filterProvider did see "eth_getFilterChanges"
ok 289 filterProvider did handle "eth_getFilterChanges"
ok 290 correct number of results
ok 291 correct result
ok 292 did not error
ok 293 did not error
ok 294 has response
ok 295 filterProvider did see "eth_getFilterChanges"
ok 296 filterProvider did handle "eth_getFilterChanges"
ok 297 correct number of results
ok 298 did not error
# filters - log filter - mixed case
ok 299 did not error
ok 300 has response
ok 301 filterProvider did see "eth_newFilter"
ok 302 filterProvider did handle "eth_newFilter"
ok 303 did not error
ok 304 did not error
ok 305 has response
ok 306 filterProvider did see "eth_getFilterChanges"
ok 307 filterProvider did handle "eth_getFilterChanges"
ok 308 correct number of results
ok 309 correct result
ok 310 did not error
ok 311 did not error
ok 312 has response
ok 313 filterProvider did see "eth_getFilterChanges"
ok 314 filterProvider did handle "eth_getFilterChanges"
ok 315 correct number of results
ok 316 did not error
# filters - log filter - address array
ok 317 did not error
ok 318 has response
ok 319 filterProvider did see "eth_newFilter"
ok 320 filterProvider did handle "eth_newFilter"
ok 321 did not error
ok 322 did not error
ok 323 has response
ok 324 filterProvider did see "eth_getFilterChanges"
ok 325 filterProvider did handle "eth_getFilterChanges"
ok 326 correct number of results
ok 327 correct result
ok 328 did not error
ok 329 did not error
ok 330 has response
ok 331 filterProvider did see "eth_getFilterChanges"
ok 332 filterProvider did handle "eth_getFilterChanges"
ok 333 correct number of results
ok 334 did not error
# filters - log filter - and logic
ok 335 did not error
ok 336 has response
ok 337 filterProvider did see "eth_newFilter"
ok 338 filterProvider did handle "eth_newFilter"
ok 339 did not error
ok 340 did not error
ok 341 has response
ok 342 filterProvider did see "eth_getFilterChanges"
ok 343 filterProvider did handle "eth_getFilterChanges"
ok 344 correct number of results
ok 345 correct result
ok 346 did not error
ok 347 did not error
ok 348 has response
ok 349 filterProvider did see "eth_getFilterChanges"
ok 350 filterProvider did handle "eth_getFilterChanges"
ok 351 correct number of results
ok 352 did not error
# filters - log filter - or logic
ok 353 did not error
ok 354 has response
ok 355 filterProvider did see "eth_newFilter"
ok 356 filterProvider did handle "eth_newFilter"
ok 357 did not error
ok 358 did not error
ok 359 has response
ok 360 filterProvider did see "eth_getFilterChanges"
ok 361 filterProvider did handle "eth_getFilterChanges"
ok 362 correct number of results
ok 363 correct result
ok 364 correct result
ok 365 did not error
ok 366 did not error
ok 367 has response
ok 368 filterProvider did see "eth_getFilterChanges"
ok 369 filterProvider did handle "eth_getFilterChanges"
ok 370 correct number of results
ok 371 did not error
# filters - log filter - wildcard logic
ok 372 did not error
ok 373 has response
ok 374 filterProvider did see "eth_newFilter"
ok 375 filterProvider did handle "eth_newFilter"
ok 376 did not error
ok 377 did not error
ok 378 has response
ok 379 filterProvider did see "eth_getFilterChanges"
ok 380 filterProvider did handle "eth_getFilterChanges"
ok 381 correct number of results
ok 382 correct result
ok 383 correct result
ok 384 did not error
ok 385 did not error
ok 386 has response
ok 387 filterProvider did see "eth_getFilterChanges"
ok 388 filterProvider did handle "eth_getFilterChanges"
ok 389 correct number of results
ok 390 did not error
# filters - eth_getFilterLogs called with non log filter id should return []
ok 391 did not error
ok 392 has response
ok 393 filterProvider did see "eth_newBlockFilter"
ok 394 filterProvider did handle "eth_newBlockFilter"
ok 395 did not error
ok 396 has response
ok 397 has response.result
ok 398 filterProvider did see "eth_getFilterLogs
ok 399 filterProvider did handle "eth_getFilterLogs
ok 400 eth_getFilterLogs returned an empty result for a non log filter
ok 401 did not error
# subscriptions - basic block subscription
ok 402 did not error
ok 403 has response
ok 404 subscriptionSubprovider did see "eth_subscribe"
ok 405 subscriptionSubprovider did handle "eth_subscribe"
ok 406 did not error
ok 407 did not error
ok 408 has notification
ok 409 notification has correct subscription id
ok 410 correct result
ok 411 did not error
ok 412 did not error
# subscriptions - log subscription - basic
ok 413 did not error
ok 414 has response
ok 415 subscriptionSubprovider did see "eth_subscribe"
ok 416 subscriptionSubprovider did handle "eth_subscribe"
ok 417 did not error
ok 418 did not error
ok 419 has notification
ok 420 notification has correct subscription id
ok 421 correct result
ok 422 did not error
ok 423 did not error
# subscriptions - log subscription - and logic
ok 424 did not error
ok 425 has response
ok 426 subscriptionSubprovider did see "eth_subscribe"
ok 427 subscriptionSubprovider did handle "eth_subscribe"
ok 428 did not error
ok 429 did not error
ok 430 has notification
ok 431 notification has correct subscription id
ok 432 correct result
ok 433 did not error
ok 434 did not error
# subscriptions - log subscription - or logic
ok 435 did not error
ok 436 has response
ok 437 subscriptionSubprovider did see "eth_subscribe"
ok 438 subscriptionSubprovider did handle "eth_subscribe"
ok 439 did not error
ok 440 did not error
ok 441 has notification
ok 442 notification has correct subscription id
ok 443 correct result
ok 444 did not error
ok 445 did not error
ok 446 has notification
ok 447 correct result
ok 448 did not error
ok 449 did not error
# subscriptions - log subscription - wildcard logic
ok 450 did not error
ok 451 has response
ok 452 subscriptionSubprovider did see "eth_subscribe"
ok 453 subscriptionSubprovider did handle "eth_subscribe"
ok 454 did not error
ok 455 did not error
ok 456 has notification
ok 457 notification has correct subscription id
ok 458 correct result
ok 459 did not error
ok 460 did not error
ok 461 has notification
ok 462 correct result
ok 463 did not error
ok 464 did not error
# tx sig
ok 465 did not error
ok 466 has response
ok 467 providerA did see "signTransaction"
ok 468 providerA did handle "signTransaction"
ok 469 providerB did see "eth_getTransactionCount"
ok 470 providerB did NOT handle "eth_getTransactionCount"
ok 471 providerC did see "eth_getTransactionCount"
ok 472 providerC did handle "eth_getTransactionCount"
ok 473 providerB did see "eth_gasPrice"
ok 474 providerB did handle "eth_gasPrice"
ok 475 providerC did see "eth_sendRawTransaction"
ok 476 providerC did handle "eth_sendRawTransaction"
# no such account
ok 477 did error
# sign message
ok 478 did not error
ok 479 has response
ok 480 signed response is correct
# sign message personal_sign - kumavis fml manual test I
ok 481 null
ok 482 has response
ok 483 rpc result is as expected
# sign message personal_sign - kumavis fml manual test I
ok 484 null
ok 485 has response
ok 486 rpc result is as expected
# sign message personal_sign - kumavis fml manual test II
ok 487 null
ok 488 has response
ok 489 rpc result is as expected
# sign message personal_sign - kumavis fml manual test II
ok 490 null
ok 491 has response
ok 492 rpc result is as expected
# sign message personal_sign - kumavis fml manual test III
ok 493 null
ok 494 has response
ok 495 rpc result is as expected
# sign message personal_sign - kumavis fml manual test III
ok 496 null
ok 497 has response
ok 498 rpc result is as expected
# recover message personal_ecRecover - geth kumavis manual I recover
ok 499 null
ok 500 has response
ok 501 rpc result is as expected
# recover message personal_ecRecover - geth kumavis manual II recover
ok 502 null
ok 503 has response
ok 504 rpc result is as expected
# sign message eth_signTypedData - sign typed message
ok 505 null
ok 506 has response
ok 507 rpc result is as expected
# sender validation, with mixed-case
ok 508 correctly validated sender
# Sanitizer removes unknown keys
ok 509 should be falsy
ok 510 should be equal
ok 511 should be equal
ok 512 should be equal
ok 513 should be equal
ok 514 should be equal
ok 515 no error
ok 516 result was received correctly
# binary search eth_estimateGas implementation
ok 517 did not error
ok 518 has response
ok 519 properly calculates gas needed
ok 520 ran expected number of iterations
ok 521 did not error
ok 522 has response
ok 523 properly calculates gas needed
ok 524 ran expected number of iterations
ok 525 did not error
ok 526 has response
ok 527 properly calculates gas needed
ok 528 ran expected number of iterations
ok 529 did not error

1..529
# tests 529
# pass  529

# ok
View Code

然后根目录下我们能够看见有一个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'), 16)
  const blockHash = `0x${block.hash.toString('hex')}`
  console.log(`block: #${blockNumber} ${blockHash}`)
})

然后在终端进行运行:

userdeMacBook-Pro:provider-engine-master user$ node example.js 
block: #0 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) {//3
  const self = this
  EventEmitter.call(self)
  self.setMaxListeners(30)
  // 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 || 4000,
  })

  // 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) {//4
  var self = this
  var currentProvider = -1 //就是现在并没有添加任何的subproviders
  var result = null
  var error = null

  var stack = []

  next()

  function next(after) {
    currentProvider += 1
    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: -32000
        }
        // 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 = {}){//1
  const connectionType = getConnectionType(opts)//2

  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(':')[0].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[0])
    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: #00 0x9f19e5f94819dd3edba2b0ae9d08f9c7d93b507aef26ede53febf78fea06ae8d
================================
{ id: 1542183381901999,
  jsonrpc: '2.0',
  result:
   '0xe1b85b3a4f7e02f2865d7b087698ef5428a0f9333b70fcef761e844051471737' }
================================
BLOCK CHANGED: #01 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:3033) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
原文地址:https://www.cnblogs.com/wanghui-garcia/p/9955206.html