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.