7

The following function:

async function getPendingTransactions(address){
    var pendingBlock = await web3.eth.getBlock('pending');
    var i = 0;
    var pendingTransactions = await pendingBlock.transactions.filter(async function(txHash)  {
        var tx = await web3.eth.getTransaction(txHash);
        console.log(tx);
        if(tx != null) {
            return tx.from==address && tx.to == CONTRACT_ADDRESS;
        }
    });
    console.log(pendingTransactions);   
    return pendingTransactions;
}

The filter does not work and all transactions are displayed (console.log), and the filter loops seems to be processed afterwards. I guess it is a async/await problem. How can I keep the the filter synchronous?

2 Answers 2

11

You can't use an async function as a filter callback, because:

  1. filter won't wait for the promises to be settled, and

  2. async functions always return promises, and promises like all non-null objects are truthy, so as far as filter is concerned you're returning a flag saying you should keep the element

In this case, you can use Promise.all to wait for all the transactions to be retrieved and then filter the results; see comments:

async function getPendingTransactions(address) {
    const pendingBlock = await web3.eth.getBlock("pending");
    // *** Get the transactions by creating an array of promises and then waiting
    // via `await` for all of them to settle
    const transactions = await Promise.all(
        pendingBlock.transactions.map(txHash => web3.eth.getTransaction(txHash))
    );
    // *** Filter them
    const pendingTransactions = transactions.filter(
        tx => tx && tx.from == address && tx.to == CONTRACT_ADDRESS
    );
    return pendingTransactions;
}

All of the calls to web3.eth.getTransaction will be started in parallel, then we wait for all of them to settle via await Promise.all(/*...*/), then filter the result and return it.

Sign up to request clarification or add additional context in comments.

Comments

0

Solution below is using iter-ops library, which supports async filter:

async function getPendingTransactions(address) {
    const pendingBlock = await web3.eth.getBlock('pending');
    return pipeAsync(
        pendingBlock.transactions,
        filter(async txHash => {
            const tx = await web3.eth.getTransaction(txHash);
            console.log(tx);
            if(tx != null) {
                return tx.from == address && tx.to == CONTRACT_ADDRESS;
            }
        })
    );
}

Function getPendingTransactions will return AsyncIterable<Transaction>, which you can easily loop through:

for await (const t of getPendingTransactions('address')) {
    console.log(t); // transaction details
}

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.