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
然后运行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
然后根目录下我们能够看见有一个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
- 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:3033) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.