ethers-io / ethers.js

Complete Ethereum library and wallet implementation in JavaScript.
https://ethers.org/
MIT License
7.9k stars 1.83k forks source link

Add `getPastEvents` #630

Closed grepfruit19 closed 4 years ago

grepfruit19 commented 4 years ago

It doesn't seem like there's a good way to get past events from a contract. I've written the below code, maybe we can add it to the codebase if it seems like there's a need for it.

Thoughts?


/**
 * Converts any BigNumbers in an object to numbers.
 *
 * @memberof dapp-utils/ethers
 *
 * @param {object} object - Object to parse.
 * @returns {object} Object with converted BigNumbers.
 */
const parseBigNumbers = object => {
  const output = Object.assign({}, object);
  const entries = Object.entries(output);
  entries.forEach(([key, value]) => {
    if (value instanceof BigNumber) {
      output[key] = value.toNumber();
    }
  });
  return output;
};

/**
 * Abstraction for getting events from ethers. Returns human readable events.
 *
 * @memberof dapp-utils/ethers
 *
 * @param {ethers.Contract} contract - ethers contract instance.
 * @param {object} options
 * @param {number} options.from - Block to query from.
 * @param {number|string} options.to - block to query to.
 * @param {string} options.topics - name of event as it appears in the contract (i.e., 'Transfer').
 * @returns {array} - Array of events.
 */
const getEvents = async (contract, options) => {
  const { fromBlock = 0, toBlock = 'latest', topics } = options;

  const provider = getProvider();

  const parsedTopic = topics ? ethers.utils.id(contract.interface.events[topics].signature) : null;

  const events = await provider.getLogs({
    fromBlock,
    toBlock,
    address: contract.address,
    topics: [parsedTopic],
  });

  const parsedEventData = events.map(log => contract.interface.parseLog(log));

  const combinedEventData = events.map((event, index) => {
    return {
      ...event,
      name: parsedEventData[index].name,
      values: parsedEventData[index].values,
    };
  });

  const output = combinedEventData.map(event => {
    return {
      ...event,
      values: removeNumericKeys(event.values),
    };
  });
  return output;
};```
ricmoo commented 4 years ago

In v5, you can use the contract.queryFilter(filter [ , fromBlock [ , toBlock ] ] ) function on the Contract objects. The filter object can be computed for you using: contract.filters.Transfer(null, myAddress), for example, which will create a filter for you that lists all ERC20 transactions to myAddress.

grepfruit19 commented 4 years ago

Ah nice, what's the state of the v5 beta? Any estimations on when it might come out?

pcowgill commented 4 years ago

@willKim19 See this PR for the answer https://github.com/ethers-io/ethers.js/pull/621