https://github.com/MetaMask/eth-block-tracker

A JS module for keeping track of the latest Ethereum block by polling an ethereum provider.

通过拉取以太坊的provider来跟踪最新的以太坊区块

eth-block-tracker

This module walks the Ethereum blockchain, keeping track of the latest block. It uses a web3 provider as a data source and will continuously poll for the next block.

这个模块沿着以太坊区块链去跟踪最新的区块。它使用web3 provider作为其数据源,并不停地从最新的区块中拉取数据

const HttpProvider = require('ethjs-provider-http')
const PollingBlockTracker = require('eth-block-tracker') const provider = new HttpProvider('https://mainnet.infura.io')//设置provider
const blockTracker = new PollingBlockTracker({ provider })
blockTracker.on('latest', console.log)
 

methods

new PollingBlockTracker({ provider, pollingInterval, retryTimeout, keepEventLoopActive })

creates a new block tracker with provider as a data source and pollingInterval (ms) timeout between polling for the latest block. If an Error is encountered when fetching blocks, it will wait retryTimeout (ms) before attempting again. If keepEventLoopActive is false, in Node.js it will unref the polling timeout, allowing the process to exit during the polling interval. defaults to true, meaning the process will be kept alive.

创建了一个指定provider数据源的区块追踪器,并在pollingInterval的间隔时间内拉取最新区块。当获取区块的时候如果出现了错误,那么她就会等待retryTimeout (ms)再重新获取。如果keepEventLoopActive是false,在nodejs中它会取消轮询超时,即在拉取的间隔中允许进程退出。默认是true,意味着进程始终保持活跃

getCurrentBlock()

synchronous returns the current block. may be null.

同步等到当前的区块

console.log(blockTracker.getCurrentBlock())
async getLatestBlock()

Asynchronously returns the latest block. if not immediately available, it will fetch one.

异步得到最新区块

async checkForLatestBlock()

Tells the block tracker to ask for a new block immediately, in addition to its normal polling interval. Useful if you received a hint of a new block (e.g. via tx.blockNumber from getTransactionByHash). Will resolve to the new latest block when its done polling.

要求区块追踪器马上去取新的区块,除非现在正处于正常的polling间隔。如果你收到了新的区块的暗示时这个功能就十分有用(via tx.blockNumber from getTransactionByHash)。当其拉取完后,将释放最新的区块

EVENTS

latest

The latest event is emitted for whenever a new latest block is detected. This may mean skipping blocks if there were two created since the last polling period.

blockTracker.on('latest', (newBlock) => console.log(newBlock))

当新的区块被检测到时,这个事件就会被触发。如果在上一个拉取周期中生成了两个区块,那么将会跳过,不会触发事件

sync

The sync event is emitted the same as "latest" but includes the previous block.

blockTracker.on('sync', ({ newBlock, oldBlock }) => console.log(newBlock, oldBlock))

它跟"latest"是相同的,不同在与它还返回了之前的一个区块

error

The error event means an error occurred while polling for the latest block.

blockTracker.on('error', (err) => console.error(err))

当拉取最新的区块的时候出现错误时触发

代码:

eth-block-tracker/package.json

  "main": "src/polling.js",
"scripts": {
"test": "npm run build && node test/index.js",
"prepublish": "npm run build",
"build": "mkdir -p ./dist && npm run bundle",
"bundle": "babel src -d dist/es5/ && npm run bundle-polling && npm run bundle-base",
"bundle-polling": "browserify -s PollingBlockTracker -e src/polling.js -t [ babelify --presets [ es2015 ] ] > dist/PollingBlockTracker.js",
"bundle-base": "browserify -s BaseBlockTracker -e src/base.js -t [ babelify --presets [ es2015 ] ] > dist/BaseBlockTracker.js"
},

eth-block-tracker/example.js

const createInfuraProvider = require('eth-json-rpc-infura/src/createProvider')
const PollingBlockTracker = require('./src/polling') const provider = createInfuraProvider({ network: 'mainnet' })//使用infura的mainnet网生成provider
const blockTracker = new PollingBlockTracker({ provider }) //生成blockTracker blockTracker.on('sync', ({ newBlock, oldBlock }) => {//监听sync事件
if (oldBlock) {
console.log(`sync #${Number(oldBlock)} -> #${Number(newBlock)}`)
} else {
console.log(`first sync #${Number(newBlock)}`)
}
})

eth-block-tracker/src/polling.js

const EthQuery = require('eth-query')
const EventEmitter = require('events')
const pify = require('pify')
const BaseBlockTracker = require('./base') const sec =
const min = * sec class PollingBlockTracker extends BaseBlockTracker {//1 继承自BaseBlockTracker constructor(opts = {}) {
// parse + validate args
if (!opts.provider) throw new Error('PollingBlockTracker - no provider specified.')//2 必须要传入provider
const pollingInterval = opts.pollingInterval || * sec //3 设置poll间隔时间
const retryTimeout = opts.retryTimeout || pollingInterval / 10 //4 设置出错后的重试时间
const keepEventLoopActive = opts.keepEventLoopActive !== undefined ? opts.keepEventLoopActive : true //5进程是否保持活跃
// BaseBlockTracker constructor
super(Object.assign({//6 将opts复制到前一个参数数组中,并作为BaseBlockTracker参数传给其构造函数
blockResetDuration: pollingInterval,
}, opts))
// config,配置相应的信息
this._provider = opts.provider
this._pollingInterval = pollingInterval
this._retryTimeout = retryTimeout
this._keepEventLoopActive = keepEventLoopActive
// util
this._query = new EthQuery(this._provider)
} //
// public
//
//公有函数
// trigger block polling
async checkForLatestBlock() {
await this._updateLatestBlock()
return await this.getLatestBlock() //调用BaseBlockTracker的函数getLatestBlock
} //
// private
//
//下面为私有函数
_start() {
this._performSync().catch(err => this.emit('error', err))
} async _performSync () {
while (this._isRunning) {
try {
await this._updateLatestBlock()
await timeout(this._pollingInterval, !this._keepEventLoopActive)
} catch (err) {
const newErr = new Error(`PollingBlockTracker - encountered an error while attempting to update latest block:\n${err.stack}`)
try {
this.emit('error', newErr)
} catch (emitErr) {
console.error(newErr)
}
await timeout(this._retryTimeout, !this._keepEventLoopActive)
}
}
} async _updateLatestBlock () {
// fetch + set latest block
const latestBlock = await this._fetchLatestBlock()
this._newPotentialLatest(latestBlock)
} async _fetchLatestBlock () {
return await pify(this._query.blockNumber).call(this._query)
} } module.exports = PollingBlockTracker function timeout (duration, unref) {
return new Promise(resolve => {
const timoutRef = setTimeout(resolve, duration)
// don't keep process open
if (timoutRef.unref && unref) {
timoutRef.unref()
}
})
}

eth-block-tracker/src/base.js

const EthQuery = require('eth-query')
const pify = require('pify')
const SafeEventEmitter = require('safe-event-emitter') const sec = const calculateSum = (accumulator, currentValue) => accumulator + currentValue
const blockTrackerEvents = ['sync', 'latest'] class BaseBlockTracker extends SafeEventEmitter { //
// public
// constructor(opts = {}) {//6
super()
// config
this._blockResetDuration = opts.blockResetDuration || * sec //拉取的间隔时间
// state
this._blockResetTimeout
this._currentBlock = null
this._isRunning = false
// bind functions for internal use
this._onNewListener = this._onNewListener.bind(this)
this._onRemoveListener = this._onRemoveListener.bind(this)
this._resetCurrentBlock = this._resetCurrentBlock.bind(this)
// listen for handler changes
this._setupInternalEvents()
} isRunning() {
return this._isRunning
} getCurrentBlock () {
return this._currentBlock
} async getLatestBlock () {
// return if available
if (this._currentBlock) return this._currentBlock
// wait for a new latest block
const latestBlock = await new Promise(resolve => this.once('latest', resolve))
// return newly set current block
return latestBlock
} // dont allow module consumer to remove our internal event listeners
removeAllListeners(eventName) {
// perform default behavior, preserve fn arity
if (eventName) {
super.removeAllListeners(eventName)
} else {
super.removeAllListeners()
}
// re-add internal events
this._setupInternalEvents()
// trigger stop check just in case
this._onRemoveListener()
} //
// to be implemented in subclass
// _start () {
// default behavior is noop
} _end () {
// default behavior is noop
} //
// private
// _setupInternalEvents () {
// first remove listeners for idempotence
this.removeListener('newListener', this._onNewListener)
this.removeListener('removeListener', this._onRemoveListener)
// then add them
this.on('newListener', this._onNewListener)
this.on('removeListener', this._onRemoveListener)
} _onNewListener (eventName, handler) {
// `newListener` is called *before* the listener is added
if (!blockTrackerEvents.includes(eventName)) return
this._maybeStart()
} _onRemoveListener (eventName, handler) {
// `removeListener` is called *after* the listener is removed
if (this._getBlockTrackerEventCount() > ) return
this._maybeEnd()
} _maybeStart () {
if (this._isRunning) return
this._isRunning = true
// cancel setting latest block to stale
this._cancelBlockResetTimeout()
this._start()
} _maybeEnd () {
if (!this._isRunning) return
this._isRunning = false
this._setupBlockResetTimeout()
this._end()
} _getBlockTrackerEventCount () {
return blockTrackerEvents
.map(eventName => this.listenerCount(eventName))
.reduce(calculateSum)
} _newPotentialLatest (newBlock) {
const currentBlock = this._currentBlock
// only update if blok number is higher
if (currentBlock && (hexToInt(newBlock) <= hexToInt(currentBlock))) return
this._setCurrentBlock(newBlock)
} _setCurrentBlock (newBlock) {
const oldBlock = this._currentBlock
this._currentBlock = newBlock
this.emit('latest', newBlock)
this.emit('sync', { oldBlock, newBlock })
} _setupBlockResetTimeout() {
// clear any existing timeout
this._cancelBlockResetTimeout()
// clear latest block when stale
this._blockResetTimeout = setTimeout(this._resetCurrentBlock, this._blockResetDuration)
// nodejs - dont hold process open
if (this._blockResetTimeout.unref) {
this._blockResetTimeout.unref()
}
} _cancelBlockResetTimeout() {
clearTimeout(this._blockResetTimeout)
} _resetCurrentBlock () {
this._currentBlock = null
} } module.exports = BaseBlockTracker function hexToInt(hexInt) {
return Number.parseInt(hexInt, )
}
 

MetaMask/eth-block-tracker的更多相关文章

  1. MetaMask/provider-engine-2-代码

    package.json "main": "index.js", "scripts": { "test": " ...

  2. metamask源码学习-controllers-network

    https://github.com/MetaMask/metamask-extension/tree/master/app/scripts/controllers/network metamask- ...

  3. Spark Streaming 架构

    图 1   Spark Streaming 架构图 组件介绍:‰ Network Input Tracker : 通 过 接 收 器 接 收 流 数 据, 并 将 流 数 据 映 射 为 输 入DSt ...

  4. Spark应用程序的运行框架

    几个基本概念: (1)job:包含多个task组成的并行计算,往往由action催生. (2)stage:job的调度单位. (3)task:被送到某个executor上的工作单元. (4)taskS ...

  5. spark基础知识介绍2

    dataframe以RDD为基础的分布式数据集,与RDD的区别是,带有Schema元数据,即DF所表示的二维表数据集的每一列带有名称和类型,好处:精简代码:提升执行效率:减少数据读取; 如果不配置sp ...

  6. Spark应用程序的运行架构几种说

    (1)简单的说: 由driver向集群申请资源,集群分配资源,启动executor.driver将spark应用程序的代码和文件传送给executor.executor上运行task,运行完之后将结果 ...

  7. metamask源码学习-controller-transaction

    ()metamask-extension/app/scripts/controllers/transactions Transaction Controller is an aggregate of ...

  8. ganache与metamask

    1.其实ganache其实就相当于一个私有链ganache安装,这个是图形化界面的: 2.(testRpc跟他其实是一个用处,有一个即可,只不过testRpc是非图形化界面.要注意两者都仅运行在內存中 ...

  9. metamask源码学习-metamask-controller.js

    The MetaMask Controller——The central metamask controller. Aggregates other controllers and exports a ...

随机推荐

  1. 了解java虚拟机---JVM的基本结构(1)

    1. JVM的基本结构 1.1. 类加载子系统 类加载子系统负责从文件或者网络中加载Class信息,加载的类信息存放于方法区的内存空间.方法区中可能还会存放运行时常量信息,包括字符串与数字常量.(这部 ...

  2. Redis——基础数据结构

    Redis提供了5种基础数据结构,分别是String,list,set,hash和zset. 1.String Redis所有的键都是String.Redis的String是动态字符串,内部结构类似J ...

  3. volatile关键值

    happens-before原则 我们编写的程序都要经过优化后(编译器和处理器会对我们的程序进行优化以提高运行效率)才会被运行,优化分为很多种,其中有一种优化叫做重排序,重排序需要遵守happens- ...

  4. 清空mysql数据表中的所有数据

    - 清空全部数据,不写日志,不可恢复,速度极快 truncate table_name;   -- 清空全部数据,写日志,数据可恢复,速度慢 delete from 表名     详情请查看区别

  5. JS中深浅拷贝 函数封装代码

    一.了解 基本数据类型保存在栈内存中,按值访问,引用数据类型保存在堆内存中,按址访问. 二.浅拷贝 浅拷贝只是复制了指向某个对象的指针,而不是复制对象本身,新旧对象其实是同一内存地址的数据,修改其中一 ...

  6. format格式化字符串

    假如想要表达这样一条语句:李明今年十二岁 输出这样一条语句 name = 'LiMing' age = 12 print( name + 'is' + age + 'years old') #输出 L ...

  7. 排序算法(9)--Distribution Sorting--分布排序[1]--Counting sort--计数器排序

    1.基本思想 假设数序列中小于元素a的个数为n,则直接把a放到第n+1个位置上.当存在几个相同的元素时要做适当的调整,因为不能把所有的元素放到同一个位置上.计数排序假设输入的元素都是0到k之间的整数. ...

  8. Java基础笔记(3) 进制与进制转换

    ---恢复内容开始--- 进制 在一般生活中,我们一直在应用的十进制,就是逢十进一,而今天我们要接触的是,计算机编程常用的进制!首先我们要知道,计算机内部运算采用的是二进制,也就是逢二进制! 1.什么 ...

  9. hibernate动态表名映射

    引自:http://blog.csdn.net/xvshu/article/details/39187779 最近的一个项目有一个需求,有N个考核单位,要对每个考核单位生成一张考核情况表,这样做的目的 ...

  10. Oracle中SQL语句转化IP地址到数字

    CREATE OR REPLACE FUNCTION ip_num(ipaddress IN VARCHAR2) RETURN NUMBER AS ipnum ; pos1 ; pos2 ; BEGI ...