Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Listing all transactions of a wallet #326

Closed
ruzpuz opened this issue Oct 30, 2018 · 23 comments
Closed

Listing all transactions of a wallet #326

ruzpuz opened this issue Oct 30, 2018 · 23 comments
Labels
discussion Questions, feedback and general information.

Comments

@ruzpuz
Copy link

ruzpuz commented Oct 30, 2018

Hello. My intentions are to list all balance changes of a particular wallet (address provided).

this.provider.resetEventsBlock(0);
this.provider.on(this.wallet.address, (balance) => {
  console.log('New Balance: ' + balance);
});

However this callback is never called. Is there a reason why?

@ricmoo
Copy link
Member

ricmoo commented Oct 30, 2018

The address event type cannot be used for historic information, unfortunately. This is restriction with the indexed data available on-chain.

Fortunately, Etherscan supports what you are trying to accomplish. :)

let provider = new ethers.providers.EtherscanProvider();
let history = await provider.getHistory(address);

This is possible because Etherscan has independently indexed all this data in their own, much more complex DB.

Let me know if you have any issues with this method. :)

@ricmoo ricmoo assigned ricmoo and unassigned ricmoo Oct 30, 2018
@ricmoo ricmoo added the discussion Questions, feedback and general information. label Oct 30, 2018
@ruzpuz
Copy link
Author

ruzpuz commented Oct 30, 2018

@ricmoo thanks for reply, however this kinda feels sub-optimal (it does work what I want)

This searches for all history related to given address. But this operation will be part of the larger procedure that will be run multiple times per day (imagine clearing in banks). And as history grows it will become harder to filter relevant data from history. How to tackle this issue?

reading the docs helped, forget my ignorance... Cheers

@ricmoo
Copy link
Member

ricmoo commented Oct 30, 2018

Oh, the getHistory(address [ , fromBlock [ , toBlock ] ] ) command lets you filter further by block numbers. :)

I agree it isn’t ideal, but the data isn’t actually indexed in the node, so access to it isn’t really available, even passing a block height into the getBalance call. :s

@ricmoo
Copy link
Member

ricmoo commented Oct 30, 2018

Oh! Haha. Good timing. :)

@ricmoo
Copy link
Member

ricmoo commented Nov 5, 2018

Im going to close this now, but if you have any more issues, please feel free to re-open.

Thanks! :)

@ricmoo ricmoo closed this as completed Nov 5, 2018
@Amirhb
Copy link

Amirhb commented Dec 27, 2019

too bad that it doesn't support ropsten!

@ricmoo
Copy link
Member

ricmoo commented Dec 27, 2019

@Amirhb It should support Ropsten. What address are you using? I’ve used it on Ropsten.

@Amirhb
Copy link

Amirhb commented Dec 28, 2019

@ricmoo I just instantiated ethers and used the code snippet you mentioned above. The history fetched out from the mainnet. Am I missing something?

@ricmoo
Copy link
Member

ricmoo commented Dec 28, 2019

@Amirhb Oh, well yes; the above sample connects to mainnet. :)

To connect to Ropsten, use:

// This is the important part -------------------------v
let provider = new ethers.providers.EtherscanProvider("ropsten");
let history = await provider.getHistory(address);

For more info, check out the documentation for the Providers. And let me know if you have any other issues.

@Amirhb
Copy link

Amirhb commented Dec 28, 2019

@ricmoo Thank you so much

@jacko125
Copy link

jacko125 commented Mar 17, 2020

@ricmoo Has anyone had any issues with EtherscanProvider().getHistory() such as API rate limiting ?

Looking to use the default EtherscanProvider() to retrieve wallet transactions but concerned etherscan will hit rate limit.

@miguelmota
Copy link

Is there an alternative to etherscan for transaction history?

@ricmoo
Copy link
Member

ricmoo commented Jun 30, 2020

I’ve used getHistory for quite a while in production wallets, without any obvious throttling issues, but it is a concern I have. It’s hard to know whether any of my users have been throttled in the wild though. And if Etherscan ever dials up throttling it could be an issue.

I’ve been building out some libraries to help mitigate this and will be sharing them, but it is certainly non-trivial...

@emclab
Copy link

emclab commented Jul 3, 2021

In 5.4, where to find the doc for provider.getHistory(address)? I am looking for a method to pull out transactions for an account (address) within a period of time.

@AlmostEfficient
Copy link

AlmostEfficient commented Nov 7, 2021

For anyone that stumbles onto this from Google, v5 docs haven't been updated. Here is the function itself -

https://github.com/ethers-io/ethers.js/blob/master/packages/providers/src.ts/etherscan-provider.ts#L423

provider.getHistory(addressOrName: string | Promise<string>, startBlock?: BlockTag, endBlock?: BlockTag)

Example -
I'm using this to get the last few txs for an address that might not have been active recently.

  const currentBlock= await provider.getBlockNumber()
  const blockTime = 15; // ETH block time is 15 seconds

  //Block number 2 hours, 24 hours and 48 hours ago
  const block2 = currentBlock - (2 * 60 * 60 / blockTime);
  const block24 = currentBlock - (24 * 60 * 60 / blockTime);
  const block48 = currentBlock - (48 * 60 * 60 / blockTime);

  // Get all txs for address since 2 hours ago
  let history = await provider.getHistory(address, block2, currentBlock);

  // If you got nothing back (i.e no txns), try 24 hours and then 48 hours
  (history.length === 0 ? history = await provider.getHistory(address, block24, currentBlock) : null);
  (history.length === 0 ? history = await provider.getHistory(address, block48, currentBlock) : null);

@MidnightLightning
Copy link

The Ethers.js documentation now has an entry for the Etherscan provider (https://docs.ethers.io/v5/api/providers/api-providers/#EtherscanProvider), but the documentation for the getHistory function is still @TODO...

@aki-anz
Copy link

aki-anz commented Aug 15, 2022

The address event type cannot be used for historic information, unfortunately. This is restriction with the indexed data available on-chain.

Fortunately, Etherscan supports what you are trying to accomplish. :)

let provider = new ethers.providers.EtherscanProvider();
let history = await provider.getHistory(address);

This is possible because Etherscan has independently indexed all this data in their own, much more complex DB.

Let me know if you have any issues with this method. :)

Thank you.

@sullof
Copy link

sullof commented Sep 12, 2022

Does the EtherscanProvider work also with Etherscan-compatible stuff, like Polygon Scan or BNB Scan?

@ham-evans
Copy link

Any updates on how to do this on other chains? Seems to only be compatible with etherscan based chains, and have not found an equivalent for chains like Polygon, Optimism, Avalanche, etc...

@toniengelhardt
Copy link

toniengelhardt commented Jan 18, 2023

The address event type cannot be used for historic information, unfortunately. This is restriction with the indexed data available on-chain.

Fortunately, Etherscan supports what you are trying to accomplish. :)

let provider = new ethers.providers.EtherscanProvider();
let history = await provider.getHistory(address);

This is possible because Etherscan has independently indexed all this data in their own, much more complex DB.

Let me know if you have any issues with this method. :)

It seems like this doesn't provide the full history, bc incoming transactions from ERC 20 contracts are missing.

If you look for instance at hayden.eth, getHistory() spits out only 4 transactions, when there are actually 18 transactions involving the address (according to Zerion).

This one for instance is missing, even though it deposits tokens into the contract: https://etherscan.io/tx/0xe632460600b0b967c95f0d39caedd17dee495ae7b8d6004c00442d65dc4c5c28

I'm trying to plot the balance over time in my app (merklin.xyz), which doesn't work with this method. Is there any solution to get all incoming and outgoing transactions?

@MidnightLightning
Copy link

MidnightLightning commented Jan 18, 2023

incoming transactions from ERC 20 contracts are missing

@toniengelhardt the Etherscan API does separate out "transactions" (non-token transactions initiated by the requested address) from "ERC20 token transfers", as well as "ERC721 token transfers" and other "internal transactions". Their API does have a way to query the ERC20 token transfers (https://docs.etherscan.io/api-endpoints/accounts#get-a-list-of-erc20-token-transfer-events-by-address), which you could query that way, though that's not as convenient as using a "provider"

@toniengelhardt
Copy link

incoming transactions from ERC 20 contracts are missing

@toniengelhardt the Etherscan API does separate out "transactions" (non-token transactions initiated by the requested address) from "ERC20 token transfers", as well as "ERC721 token transfers" and other "internal transactions". Their API does have a way to query the ERC20 token transfers (https://docs.etherscan.io/api-endpoints/accounts#get-a-list-of-erc20-token-transfer-events-by-address), which you could query that way, though that's not as convenient as using a "provider"

Thanks so much @MidnightLightning, this looks very promising! I'll give it a shot.

@Josema
Copy link

Josema commented Mar 25, 2024

For anyone that stumbles onto this from Google, v5 docs haven't been updated. Here is the function itself -

https://github.com/ethers-io/ethers.js/blob/master/packages/providers/src.ts/etherscan-provider.ts#L423

provider.getHistory(addressOrName: string | Promise<string>, startBlock?: BlockTag, endBlock?: BlockTag)

Example - I'm using this to get the last few txs for an address that might not have been active recently.

  const currentBlock= await provider.getBlockNumber()
  const blockTime = 15; // ETH block time is 15 seconds

  //Block number 2 hours, 24 hours and 48 hours ago
  const block2 = currentBlock - (2 * 60 * 60 / blockTime);
  const block24 = currentBlock - (24 * 60 * 60 / blockTime);
  const block48 = currentBlock - (48 * 60 * 60 / blockTime);

  // Get all txs for address since 2 hours ago
  let history = await provider.getHistory(address, block2, currentBlock);

  // If you got nothing back (i.e no txns), try 24 hours and then 48 hours
  (history.length === 0 ? history = await provider.getHistory(address, block24, currentBlock) : null);
  (history.length === 0 ? history = await provider.getHistory(address, block48, currentBlock) : null);

Is it possible to achieve this with v6?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion Questions, feedback and general information.
Projects
None yet
Development

No branches or pull requests