0

I would like to list all the transactions to and from my ERC-20 Ethereum address, i can only seem to list to or from, but not both at the same time. Is there another filter I could use or way to re-structure the statement to obtain both values in one const? Thanks

const transactions = await Token123.getPastEvents('Transfer', { fromBlock: 0, toBlock: 'latest', filter: { to: this.state.account } })

and

const transactions = await Token123.getPastEvents('Transfer', { fromBlock: 0, toBlock: 'latest', filter: { from: this.state.account } })

Here is how I am viewing the results:

                  <tbody>
                { this.state.transactions.slice().reverse().map((tx, key) => {
                  return (
                    <tr key={key} >
                      <td>{tx.returnValues.to}</td>
                      <td>{window.web3.utils.fromWei(tx.returnValues.value.toString(), 'Ether')}</td>
                    </tr>
                  )
                }) }
              </tbody>

Using: "web3": "1.0.0-beta.55"

2 Answers 2

0

You cannot do this in one call with Web3, it is not supported yet. Using

const transactions = await Token123.getPastEvents('Transfer', { fromBlock: 0, toBlock: 'latest', filter: { from: this.state.account, to: this.state.account } })

will result in an empty list, unless the account happened to have send some money to himself. Your only option with Web3 are doing two calls. If you care about performance, you could use something like https://quickblocks.io/. But mostly just looking in the last X blocks will be good enough.

Command to get all transactions in one variable in one line:

const transactions = (await Promise.all([Token123.getPastEvents('Transfer', { fromBlock: 0, toBlock: 'latest', filter: { from: this.state.account } }), Token123.getPastEvents('Transfer', { fromBlock: 0, toBlock: 'latest', filter: { to: this.state.account } })])).flat()
3
  • Any chance you could provide an example of populating const transactions using two calls? As long as const transactions has to: and from: it will solve the problem.
    – Luc1d
    Apr 11, 2020 at 6:24
  • @Luc1d That should be easy, I have updated the answer above. Apr 11, 2020 at 7:16
  • 1
    Thanks @soliditydeveloper, in your example, theres a missing ")" before .flat(), but once added, it does function. filter: { to: this.state.account } })])).flat()
    – Luc1d
    Apr 11, 2020 at 16:42
0

A way to re-structure the statement to "obtain both values in one const":

const transactions = [
   ...(await Token123.getPastEvents('Transfer', {fromBlock: 0, toBlock: 'latest', filter: {from: this.state.account}})),
   ...(await Token123.getPastEvents('Transfer', {fromBlock: 0, toBlock: 'latest', filter: {to  : this.state.account}})),
]);

Alternatively, you can use Etherscan APIs:

const Web3    = require("web3");
const request = require("request");

const API_KEY     = "..."; // get an etherscan api key at https://etherscan.io/login
const MAX_RESULTS = 1000;  // this is etherscan limit per request; do not change it

const BASE_URL = "http://api.etherscan.io/api"
               + "?module="       + "logs"
               + "&action="       + "getLogs"
               + "&apikey="       + API_KEY
               + "&address="      + Token123.options.address
               + "&topic0="       + Web3.utils.keccak256("Transfer(address,address,uint256)")
               + "&topic1="       + this.state.account
               + "&topic2="       + this.state.account
               + "&topic1_2_opr=" + "or";

function scan(fromBlock, numOfBlocks) {
    const toBlock = fromBlock + numOfBlocks - 1;
    if (fromBlock <= toBlock) {
        request(`${BASE_URL}&fromBlock=${fromBlock}&toBlock=${toBlock}`, {timeout: 10000}, function(error, response, body) {
            const parsed = parse(body);
            if (parsed.result) {
                if (parsed.result.length < MAX_RESULTS) {
                    console.log(`blocks ${fromBlock} + ${numOfBlocks}: error = ${error}, status = ${response.statusCode}, message = ${parsed.message}, result = ${parsed.result}`);
                    scan(toBlock + 1, numOfBlocks + 1);
                }
                else {
                    console.log(`blocks ${fromBlock} + ${numOfBlocks}: error = ${error}, status = ${response.statusCode}, message = ${parsed.message}, too many results; retrying...`);
                    scan(fromBlock, numOfBlocks >> 1);
                }
            }
            else {
                console.log(`blocks ${fromBlock} + ${numOfBlocks}: error = ${error}; retrying...`);
                scan(fromBlock, numOfBlocks);
            }
        });
    }
}

function parse(str) {
    try {
        return JSON.parse(str);
    }
    catch (error) {
        return {};
    }
}

Then call, for example, scan(0, 9850000).

Note that:

  • For the 1st parameter, you can optimize the performance of this script by using the number of the block at which Token123 was deployed (instead of using 0)
  • For the 2nd parameter, you cannot use "latest" because it stands for "number of blocks"

This script was tested with web3.js v1.2.1.

10
  • Thanks @goodvibration, in the first part of your answer, if I add a "(" before await and ")" before .flat() the script functions, however it splits from: on top and to: on bottom of the list, is there a way to print a continuous list of to: & from: in chronological order instead of having the results split like that? This answer is close.
    – Luc1d
    Apr 11, 2020 at 13:01
  • @Luc1d: You're confused. There is no flat() in my answer. Apr 11, 2020 at 13:04
  • I added .flat() to your answer, else i get an error later: "TypeError: tx.returnValues is undefined" when I am listing the results on line: <td>{tx.returnValues.to}</td>.
    – Luc1d
    Apr 11, 2020 at 13:06
  • @Luc1d: That part is outside the context of your question (i.e., it does not even appear in your question). Therefore, it is not a part of my answer (and neither should it be). Following that, and with regards to the rest of your question in the comment above, I believe that you should post it as a separate question with all the relevant details. Apr 11, 2020 at 13:09
  • ok, can you tell me how you would list the results of the first part of your answer? So i can verify it.
    – Luc1d
    Apr 11, 2020 at 13:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.