Last active
September 13, 2024 06:17
-
-
Save wschwab/528153cb6f2ea17ef9eee0c180425961 to your computer and use it in GitHub Desktop.
a handmade Ethereum event filter that you should never really use
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const eventFilter = (contractAddress, contractAbi, eventName, _provider) => { | |
const provider = _provider | |
// this will return an array with an object for each event | |
const events = contractAbi.abi.filter(obj => obj.type ? obj.type === "event" : false); | |
// getting the Transfer event and pulling it out of its array | |
const event = events.filter(event => event.name === eventName)[0]; | |
// getting the types for the event signature | |
const types = event.inputs.map(input => input.type) | |
// knowing which types are indexed will be useful later | |
let indexedInputs = []; | |
let unindexedInputs = []; | |
event.inputs.forEach(input => { | |
input.indexed ? | |
indexedInputs.push(input) : | |
unindexedInputs.push(input) | |
}); | |
// event signature | |
const eventSig = `${event.name}(${types.toString()})`; | |
// getting the topic | |
const eventTopic = ethers.utils.keccak256(eventSig); | |
// you could also filter by blocks using fromBlock and toBlock | |
const logs = provider.getLogs({ | |
address: contractAddress, | |
topics: [eventTopic] | |
}); | |
// need to decode the topics and events | |
const decoder = new ethers.utils.AbiCoder(); | |
const decodedLogs = logs.map(log => { | |
// remember how we separated indexed and unindexed events? | |
// it was because we need to sort them differently here | |
const decodedTopics = indexedInputs.map(input => { | |
// we use the position of the type in the array as an index for the | |
// topic, we need to add 1 since the first topic is the event signature | |
const value = decoder.decode(input.type, log.topics[indexedInputs.indexOf(input) + 1]); | |
return `${input.name}: ${value}`; | |
}) | |
const decodedDataRaw = decoder.decode(unindexedInputs, log.data); | |
const decodedData = unindexedInputs.map((input, i) => { | |
return `${input.name}: ${decodedDataRaw[i]}` | |
}); | |
return [...decodedTopics, ...decodedData] | |
}); | |
return decodedLogs | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment