0%
HomeBlogTechnical
How to get historical transactions on Polygon?

How to get historical transactions on Polygon?

Author: Isaac Lau

Reviewed by Brady Werkheiser


Published on February 4, 20224 min read

Ethereum Layer 2 scaling solutions, like Polygon, have allowed developers to take advantage of low transaction costs and far faster confirmation times. However, this introduces a new challenge for devs: how to process and store large swaths of blockchain data. Traditionally, developers had to spin up, manage, and index across their own nodes to build databases. This left developers constrained by an expensive and slow solution that ultimately limits their apps’ feature sets regardless of whether they are deployed on Layer 1 or Layer 2 solutions.

While building historical queries into dApps has traditionally been complicated and time-consuming, the Alchemy Transfers API on Polygon allows for developers to get Polygon transaction details, dating back to the very beginning, in a single request. 

In this tutorial, we’ll look at an example of how, with just a few lines of code, your Polygon dApp can integrate historical transactions.

Code sneak peek 👀

Copied
import json from web3 import Web3 import requests try: ALCHEMY_KEY = "Rt4_MeHEE8mQWVi-uSppHNSDmOG" except: print("Please insert your Alchemy API Key!") w3 = Web3(Web3.HTTPProvider("https://polygon-mainnet.g.alchemy.com/v2/"+ALCHEMY_KEY)) # includes the standard ERC20 ABI info ERC20_ABI = json.loads('[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],......{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]') # noqa: 501 # configures web3 to point towards the USDT token address # make sure that these addresses are Ethereum-checksummed! (use this tool: https://ethsum.netlify.app/ to make sure) USDT_ADDRESS = '0xc2132D05D31c914a87C6611C10748AEb04B58e8F' FROM_ADDRESS = '0x5350E1068f0E138ff306990B16fA4910d970c692' TO_ADDRESS = '0x9d2b758E3ffd2569c6956676fAE7f8B71A53Ffb5' from_Block = '0x16C5376' to_Block = '0x16C537A' usdt = w3.eth.contract(address=USDT_ADDRESS, abi=ERC20_ABI) transfer_json = requests.post('https://polygon-mainnet.g.alchemy.com/v2/'+ALCHEMY_KEY, json={"jsonrpc": "2.0","id": 0,"method": "alchemy_getAssetTransfers","params": [{"fromBlock": from_Block,"toBlock": to_Block,"fromAddress": FROM_ADDRESS,"toAddress": TO_ADDRESS,"contractAddresses": [USDT_ADDRESS],"category": ["erc20"]}]}) json_response = transfer_json.json() #print(json_response) transfer_val = (json_response['result']['transfers'][0]['rawContract']['value']) # convert hexadecimal make to decimal format val = (int(transfer_val, 16)) print("USDT TRANSFERED:") print("--> FROM: " + FROM_ADDRESS) print("--> TO: " + TO_ADDRESS) # unit conversion! print(val/1000000)

Before diving into the Alchemy Transfers API on Polygon, let’s clarify the 3 types of transfers we see on-chain (note - the Polygon Transfers API only supports token transfers)

These are top-level Polygon transactions that occur with a from address being an external (user-created) address. External addresses have private keys and are accessed by users.

* External transfers are not currently supported by the Alchemy Transfers API on Polygon

Event logs for ERC20 (fungible tokens), ERC721 (NFTs), and ERC1155 (hybrid fungible and non-fungible tokens) transfers.

These are transfers that occur where the fromAddress is an internal (smart contract) address. (ex: a smart contract calling another smart contract or smart contract calling another external address).

* Internal transfers are not currently supported by the Alchemy Transfers API on Polygon

For more information on API parameters and JSON responses, read the Alchemy Transfers API.

In this example, we are trying to query and find the transfer of this transaction. We can see from Polyscan that ~12,000 USDT was transferred from 0x5350e1068f0e138ff306990b16fa4910d970c692 to 0x9d2b758e3ffd2569c6956676fae7f8b71a53ffb5.

(If you want to skip ahead to the code, fork the starter script [https://github.com/pileofscraps/historical_transactions_polygon_scripts] and follow along)


To use the Transfers API to track the USDT transfer, we need a few pieces of key information that help narrow down our search. We format this request information into a JSON object as follows:

Copied
 { "jsonrpc":"2.0", "id":0, "method":"alchemy_getAssetTransfers", "params":[ { "fromBlock":"from_Block", "toBlock":"to_Block", "fromAddress":"FROM_ADDRESS", "toAddress":"TO_ADDRESS", "contractAddresses":[ "USDT_ADDRESS" ], "category":[ "erc20" ] } ] })

We can reduce the amount of time it takes for the API to return our JSON response by constraining the start and end block numbers that we are attempting to search. 

Our transaction takes place in block 23876472 so we adjust our search to a small buffer around this block number. 

The JSON object allows us to either use a hexadecimal string or for block number inputs. In this case, we use hexadecimals, so we input 0x16C5376 for afromBlock of 23876470 and 0x16C537A for a toBlock


The To & From addresses represent where the transaction was sent and where it originated from respectively. 

In our example, To Address is 0x9d2b758e3ffd2569c6956676fae7f8b71a53ffb5 and From Address is 0x5350e1068f0e138ff306990b16fa4910d970c692.

The contract address is the address denoting the specific ERC20, ERC721, or ERC1155 contract that we seek to find.In our example, the ERC20 contract for Polygon USDT is 0xc2132d05d31c914a87c6611c10748aeb04b58e8f

Putting together this information, we can now use Alchemy’s Composer tool to return results that include our target transaction. 

Visit this Alchemy Composer Example!

screenshot of alchemy composer view
Alchemy Composer View

Now, to try out the Alchemy Transfers API we query for the same transfer; this time, however, we use code! If you want to follow along, fork the starter script.

To try out Alchemy Transfers API, we start off with a few import statements to import modules we’ll use later. 

Copied
import json from web3 import Web3 import requests

If you don’t have any of these modules around installed in your python environment, be sure to run the following pip commands in your python environment.

Copied
pip install web3 pip install requests

If you don’t already have one, you’ll first need to create an account on Alchemy. The free version will work fine for getting started!

Replace the string “ALCHEMY KEY” with your own private API key. 

screenshot of alchemy dashboard API key
Alchemy Key
Copied
ALCHEMY_KEY = “ALCHEMY KEY” w3 = Web3(Web3.HTTPProvider('https://polygon-mainnet.alchemyapi.io/v2/'+ALCHEMY_KEY))

Since we are working with USDT, an ERC20 contract, we need an additional piece of code on top of what we would normally call in Web3 to interact with our contract correctly. Note that we include the ERC20 ABI in this code snippet in order to properly read the USDT contract. 

(The Contract Application Binary Interface (ABI) is the standard way to interact with contracts in the Ethereum ecosystem and we use the ERC20 ABI to interact with ERC20 contracts such as the USDT contract)

Copied
ERC20_ABI = json.loads('[{"constant":true,"inputs":[],"name":"name","outputs"......{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]')

(For readability, the entire ERC20 ABI is not included in the above code snippet. To find the full ABI, visit this Github Gist)

As described above, we configure our variables to point towards the right addresses and block numbers. In addition, we use the w3.eth.contract method so that we can read data via the USDT contract.

Copied
USDT_ADDRESS = '0xc2132D05D31c914a87C6611C10748AEb04B58e8F' FROM_ADDRESS = '0x5350E1068f0E138ff306990B16fA4910d970c692' TO_ADDRESS = '0x9d2b758E3ffd2569c6956676fAE7f8B71A53Ffb5' from_Block = '0x16C5376' to_Block = '0x16C537A' usdt = w3.eth.contract(address=USDT_ADDRESS, abi=ERC20_ABI)

Here, we POST a request to the Alchemy Transfers API. Embedded in our request is the specific alchemy_getAssetTransfers method that we call and all the previous parameters [From Block & To Block, To & From Addresses, and Contract Address]

Note that we also process the JSON result and parse it to give us the exact USDT value that was transferred within the transaction that our query returns.

Copied
transfer_json = requests.post('https://polygon-mainnet.g.alchemy.com/v2/'+ALCHEMY_KEY, json={"jsonrpc": "2.0","id": 0,"method": "alchemy_getAssetTransfers","params": [{"fromBlock": from_Block,"toBlock": to_Block,"fromAddress": FROM_ADDRESS,"toAddress": TO_ADDRESS,"contractAddresses": [USDT_ADDRESS],"category": ["erc20"]}]}) json_response = transfer_json.json() transfer_val = (json_response['result']['transfers'][0]['rawContract']['value'])

After receiving and parsing the USDT value from the JSON response, we then convert the hexadecimal string into decimal format and do a unit conversion!

Copied
# convert hexadecimal make to decimal format val = (int(transfer_val, 16)) print("USDT TRANSFERED:") print("--> FROM: " + FROM_ADDRESS) print("--> TO: " + TO_ADDRESS) # unit conversion! print(val/1000000)
screenshot of command line output
Command Line Output

With Alchemy Transfers API, you can build historical queries into Polygon dApps to populate historical wallet activity and token transfers, allowing you to develop more user-friendly UI and create more detailed on-chain analytics. Take advantage of Layer 2 cheap fees and keep your users informed about their plethora of on-chain transaction activity both in the present and the past!

Section background image

Build blockchain magic

Alchemy combines the most powerful web3 developer products and tools with resources, community and legendary support.

Get your API key