filters - only keep history for log-filters + various log-filter fixes

This commit is contained in:
kumavis
2019-03-29 15:42:57 +08:00
parent 404e89dcc7
commit ad2f0cd8e3
4 changed files with 66 additions and 34 deletions

31
base-filter-history.js Normal file
View File

@@ -0,0 +1,31 @@
const BaseFilter = require('./base-filter')
// tracks all results ever recorded
class BaseFilterWithHistory extends BaseFilter {
constructor () {
super()
this.allResults = []
}
async update () {
throw new Error('BaseFilterWithHistory - no update method specified')
}
addResults (newResults) {
this.allResults = this.allResults.concat(newResults)
super.addResults(newResults)
}
addInitialResults (newResults) {
this.allResults = this.allResults.concat(newResults)
super.addInitialResults(newResults)
}
getAllResults () {
return this.allResults
}
}
module.exports = BaseFilterWithHistory

View File

@@ -5,7 +5,6 @@ class BaseFilter extends SafeEventEmitter {
constructor () {
super()
this.updates = []
this.allResults = []
}
async initialize () {}
@@ -16,24 +15,17 @@ class BaseFilter extends SafeEventEmitter {
addResults (newResults) {
this.updates = this.updates.concat(newResults)
this.allResults = this.allResults.concat(newResults)
newResults.forEach(result => this.emit('update', result))
}
addInitialResults (newResults) {
this.allResults = this.allResults.concat(newResults)
}
addInitialResults (newResults) {}
getChangesAndClear () {
const updates = this.updates
this.updates = []
return updates
}
getAllResults () {
return this.allResults
}
}
module.exports = BaseFilter

View File

@@ -1,5 +1,4 @@
const Mutex = require('await-semaphore').Mutex
const EthQuery = require('ethjs-query')
const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware')
const createJsonRpcMiddleware = require('eth-json-rpc-middleware/scaffold')
const LogFilter = require('./log-filter.js')
@@ -11,8 +10,6 @@ module.exports = createEthFilterMiddleware
function createEthFilterMiddleware({ blockTracker, provider }) {
// ethQuery for log lookups
const ethQuery = new EthQuery(provider)
// create filter collection
let filterIndex = 0
let filters = {}
@@ -75,19 +72,19 @@ function createEthFilterMiddleware({ blockTracker, provider }) {
//
async function newLogFilter(params) {
const filter = new LogFilter({ provider, ethQuery, params })
const filter = new LogFilter({ provider, params })
const filterIndex = await installFilter(filter)
return filter
}
async function newBlockFilter() {
const filter = new BlockFilter({ provider, ethQuery })
const filter = new BlockFilter({ provider })
const filterIndex = await installFilter(filter)
return filter
}
async function newPendingTransactionFilter() {
const filter = new TxFilter({ provider, ethQuery })
const filter = new TxFilter({ provider })
const filterIndex = await installFilter(filter)
return filter
}
@@ -112,7 +109,12 @@ function createEthFilterMiddleware({ blockTracker, provider }) {
if (!filter) {
throw new Error(`No filter for index "${filterIndex}"`)
}
const results = filter.getAllResults()
// only return results for log filters
if (filter.type === 'log') {
results = filter.getAllResults()
} else {
results = []
}
return results
}

View File

@@ -1,20 +1,29 @@
const BaseFilter = require('./base-filter')
const EthQuery = require('eth-query')
const pify = require('pify')
const BaseFilterWithHistory = require('./base-filter-history')
const { bnToHex, hexToInt, incrementHexInt, minBlockRef, blockRefIsNumber } = require('./hexUtils')
class LogFilter extends BaseFilter {
class LogFilter extends BaseFilterWithHistory {
constructor ({ ethQuery, params }) {
constructor ({ provider, params }) {
super()
this.type = 'log'
this.ethQuery = ethQuery
this.ethQuery = new EthQuery(provider)
this.params = Object.assign({
fromBlock: 'latest',
toBlock: 'latest',
address: undefined,
topics: [],
}, params)
// normalize address
if (this.params.address) this.params.address = this.params.address.toLowerCase()
// normalize address parameter
if (this.params.address) {
// ensure array
if (!Array.isArray(this.params.address)) {
this.params.address = [this.params.address]
}
// ensure lowercase
this.params.address = this.params.address.map(address => address.toLowerCase())
}
}
async initialize({ currentBlock }) {
@@ -51,13 +60,7 @@ class LogFilter extends BaseFilter {
}
async _fetchLogs (params) {
const newLogs = await this.ethQuery.getLogs(params)
// de-BN ethQuery results
newLogs.forEach((log) => {
log.blockNumber = bnToHex(log.blockNumber)
log.logIndex = bnToHex(log.logIndex)
log.transactionIndex = bnToHex(log.transactionIndex)
})
const newLogs = await pify(cb => this.ethQuery.getLogs(params, cb))()
// add to results
return newLogs
}
@@ -68,7 +71,8 @@ class LogFilter extends BaseFilter {
if (blockRefIsNumber(this.params.toBlock) && hexToInt(this.params.toBlock) <= hexToInt(log.blockNumber)) return false
// address is correct:
if (this.params.address && this.params.address !== log.address) return false
const normalizedLogAddress = log.address && log.address.toLowerCase()
if (this.params.address && normalizedLogAddress && !this.params.address.includes(normalizedLogAddress)) return false
// topics match:
// topics are position-dependant
@@ -76,12 +80,15 @@ class LogFilter extends BaseFilter {
// topics can be null, representing a wild card for that position
const topicsMatch = this.params.topics.every((topicPattern, index) => {
// pattern is longer than actual topics
const logTopic = log.topics[index]
let logTopic = log.topics[index]
if (!logTopic) return false
// wild card
const subtopicsToMatch = Array.isArray(topicPattern) ? topicPattern : [topicPattern]
logTopic = logTopic.toLowerCase()
// normalize subTopics
let subtopicsToMatch = Array.isArray(topicPattern) ? topicPattern : [topicPattern]
// check for wild card
const subtopicsIncludeWildcard = subtopicsToMatch.includes(null)
if (subtopicsIncludeWildcard) return true
subtopicsToMatch = subtopicsToMatch.map(topic => topic.toLowerCase())
// check each possible matching topic
const topicDoesMatch = subtopicsToMatch.includes(logTopic)
return topicDoesMatch