How to get historical transactions on Polygon?

Isaac Lau
February 4, 2022

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 👀

-- CODE language-js line-numbers -- 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)

Types of Transfers:

1. External MATIC 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

2. Token Transfers

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

3. Internal Eth 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.

Understanding Alchemy Transfers API on Polygon

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.


https://polygonscan.com/tx/0x1e85ace98f4fc4ad7b1b64465df81d0a275d494421e553e23a238b156f42b17f

(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:

-- CODE language-js line-numbers -- { "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" ] } ] })


1. From Block & To Block

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. 

<p>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 a <code class="language-js">fromBlock</code> of 23876470 and 0x16C537A for a <code class="language-js">toBlock</code> of 23876474) </p>


2. To & From Addresses 

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.


3. Contract Address

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!

Alchemy Composer View


Trying out Alchemy Transfers API on Polygon via Python

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

1. Import Statements:

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

-- CODE language-js line-numbers -- 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.

-- CODE language-js line-numbers -- pip install web3 pip install requests


2. Insert Alchemy Key for API access:

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. 

Alchemy Key


-- CODE language-js line-numbers -- ALCHEMY_KEY = “ALCHEMY KEY” w3 = Web3(Web3.HTTPProvider('https://polygon-mainnet.alchemyapi.io/v2/'+ALCHEMY_KEY))

3. Configure Web3.py to handle ERC20 contracts

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)

-- CODE language-js line-numbers -- 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)

4. Set variables.

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.

-- CODE language-js line-numbers -- 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)


5. Query via the Alchemy Transfers API

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.

-- CODE language-js line-numbers -- 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'])


6. Convert units for readability!

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!

-- CODE language-js line-numbers -- # 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)


Final command line output:


Congratulations! You have now successfully queried from the Alchemy Transfers API on Polygon. As a next project, try querying for other types of token transfers!

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!

More articles