Simple transactions are not indexed. So you either need to iterate over all the blocks, use some kind of an off-chain index (e.g. etherscan.io), or build one up yourself and use it.
For example, you can use this heuristic approach without having to process the entire chain
var myAddr = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413';
var currentBlock = eth.blockNumber;
var n = eth.getTransactionCount(myAddr, currentBlock);
var bal = eth.getBalance(myAddr, currentBlock);
for (var i=currentBlock; i >= 0 && (n > 0 || bal > 0); --i) {
try {
var block = eth.getBlock(i, true);
if (block && block.transactions) {
block.transactions.forEach(function(e) {
if (myAddr == e.from) {
if (e.from != e.to)
bal = bal.plus(e.value);
console.log(i, e.from, e.to, e.value.toString(10));
--n;
}
if (myAddr == e.to) {
if (e.from != e.to)
bal = bal.minus(e.value);
console.log(i, e.from, e.to, e.value.toString(10));
}
});
}
} catch (e) { console.error("Error in block " + i, e); }
}
How does it work?
Using the available information about the current state (number of "from" transactions and the current balance), it goes back in time until at least so many "from" transactions have been found, and then continues going back until the balance reaches 0
.
The inherent limitation is that 0-value transactions before the account was funded will not be found.
Contract events on the other hand, are indexed. So if you're developing a smart contract, you can make use of that.
Using web3 1.0.0 API:
web3.eth.getPastLogs({fromBlock:'0x0',address:'0x9e3319636e2126e3c0bc9e3134AEC5e1508A46c7'})
.then(res => {
res.forEach(rec => {
console.log(rec.blockNumber, rec.transactionHash, rec.topics);
});
}).catch(err => console.log("getPastLogs failed", err));
Or via JSON RPC eth_getLogs.
This solution seem very ineficient. You should use instead websocketprovider (ws), which will give filtering functionality using infura.
var ws_provider = 'wss://mainnet.infura.io/ws'
var web3 = new Web3(new Web3.providers.WebsocketProvider(ws_provider))
hope this helps
Best Answer
Getting all transaction history requires you to iterate over each and every block since the contract creation. As you might guess, this would be extremely slow, plus it depends on your
Infura
plan: rate limits and number of historical blocks available.Faster Solution without
web3py
Instead, you can use indexing services, such as
Etherscan
.As explained in API docs, you can then query for transaction history in the following way:
Slower solution with
web3py
If your Infura plan allows it, you can iterate over blocks and get block details using
eth_getBlockByNumber
JSON-RPC method. Inweb3py
, it is equivalent toweb3.eth.getBlock(blocknumber)
. Then you would iterate over transaction hashes usingweb3.eth.getTransaction(txhash)
and check for from/to address against your contract address. See:https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.getTransaction
https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.getBlock