As far as the pending transactions do not differ from any other transaction objects not included in the blockchain, the more correct question would be:
How to get the receipt for a Transaction Object before including it into the blockchain?
We use this approach to simulate our transactions and to check the expected status and logs before submitting them to the network. You can pick a transaction from the mempool and perform the same simulations.
- We use hardhat to simulate the transaction. The simulation is executed instantly and in-process, which means you don't need to launch any local development networks.
- You would execute the transaction on the
latest
block, which means you don't need to have the archive
node - a basic RPC node is enough.
- Accounts:
- By picking the transactions from the mempool, they are already signed, so you can execute them immediately.
- In our case, we simulate transactions for other accounts whose private keys we don't have. But
hardhat
has a special method called impersonateAccount
that allows you to execute transactions for any address.
To get a feeling for how it works, here is an example of how we simulate transactions using the dequanto library
import { ERC20 } from '@dequanto-contracts/openzeppelin/ERC20';
import { HardhatProvider } from '@dequanto/hardhat/HardhatProvider';
import { $address } from '@dequanto/utils/$address';
const provider = new HardhatProvider();
const client = await provider.forked({ url: 'https://eth.public-rpc.com' });
const ownerImpersonated = '0x60faae176336dab62e284fe19b885b095d29fb7f';
const daiAddress = '0x6b175474e89094c44da98b954eedeac495271d0f';
await client.debug.impersonateAccount(ownerImpersonated);
const erc20 = new ERC20(daiAddress, client);
// transfer 100DAI from account to zero address
const writer = await erc20.transfer({ address: ownerImpersonated }, $address.ZERO, 100n ** 18n);
const receipt = await writer.wait();
let transferEvents = erc20.extractLogsTransfer(receipt);
console.log(transferEvents);
With raw hardhat and web3js plugin it would be something like this:
import hardhat from 'hardhat'
import { Transaction } from '@ethereumjs/tx';
// Transaction from mempool
let tx: TransactionConfig & { v, r, s };
// point the in-process network to target the mainnets latest
await hardhat.reset('https://eth.public-rpc.com');
let hex = '0x' + new Transaction(tx).serialize().toString('hex');
let receipt = await hardhat.web3.eth.sendSignedTransaction(hex);
Hope it helps.