Query Ethereum data with Web3.py, Infura and Graph

5c81b9e9e1d02e965002e924d50f4f16.png

In this article we will use the Python library Web3.py to directly query Ethereum data. Web3.py is a Python library built for interacting with the Ethereum blockchain. With it, we can build various core functions for decentralized applications. We can interact directly with smart contracts, collect blockchain data, and send transactions. Let's start installing Web3.py.

pip install web3

The function of Web3.py is to connect nodes to the Ethereum network to retrieve data and broadcast data to the network. Nodes store blockchain data, so we can query the status of the Ethereum blockchain to gather the data we need. Data retrieval is effectively a free operation for us since the only cost is the storage and computation being done by the nodes.

With this library we can connect to our own nodes or existing nodes on the network to build what we want. We can set up a local node on our own machine, but the cost of doing so is quite high; as of 4/21, a full node has about 7TB of data. Rather than operating our own nodes whenever we want to access data, we can achieve this by using a service like Infura.

Infura is a product of Consensys and we will use it as our node to connect to the Ethereum blockchain. Many top projects are users of Infura. First register on the Infura website and create a new project. There you will find a project ID.

3ffd036bc0d5cd75774abc3b522c3838.png

The project ID will be placed at the end of this code in Web3.py and it will define the node you want to connect to.

from web3 importWeb3
w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/YOUR_PROJECT_ID'))

Now that the connection to the Ethereum network is ready, you can do some basic queries.

# Get information about the latest block
w3.eth.getBlock('latest')
# Get the ETH balance of an address
w3.eth.getBalance('YOUR_ADDRESS_HERE')

This code is very concise, we can try to dig deeper. How about mimicking the functionality of a product like Zapper ( https://zapper.fi/dashboard) that tracks the USD value of our token? First, we need to scan our address to see which coins are held. In order to do this, we will interact with the smart contracts of the individual tokens. The addresses of these contracts look like our wallet addresses, except these are contract addresses. There is smart contract code at this address. The tokens will adhere to the ERC-20 standard, making it easier for us to interact with these contracts. An ERC-20 contract has the following functions by default:

function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)

balanceOfis a function that allows us to see how many tokens are held by the wallet address we query.

import json
ABI = json.loads('[{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf",
                    "outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]')

We start by defining an ABI. ABI (application binary interface) is a format we define for interacting with contracts. It is what we use to define how data should be encoded/decoded in the EVM. Technical details aside, it is important to understand that it is a format that we define how we will interact with the smart contracts we want.

wallet_address = 'YOUR_ADDRESS_HERE'
wallet_address = Web3.toChecksumAddress(wallet_address)
token_contract_address = '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f'
token_contract_address = Web3.toChecksumAddress(token_contract_address)
# define contract
contract = w3.eth.contract(token_contract_address, abi=ABI)
# call contract and get data from balanceOf for argument wallet_address
raw_balance = contract.functions.balanceOf(wallet_address).call()
# convert the value from Wei to Ether
synthetix_value = Web3.fromWei(raw_balance, 'ether')

Next we take a series of steps that enter an address and return the number of tokens held by the wallet address of our choice. Our sample address is Synthetix (SNX), you can enter any contract address you like. You can imagine that you could build a master list of ERC-20 contract addresses and iterate through it to find the tokens held by a specific wallet.

We use Web3 functions toChecksumAddress()to ensure that our addresses are in correct format. We use fromWei()to convert our Wei price to ether. 1ETH is 1E18 Wei.

Finally, we will use The Graph to get some market data. Since we want everything to be on-chain, we need to get the value we want of the token in DAI, a stablecoin that is pegged relatively to the U.S. dollar.

from gql import gql, Client
from gql.transport.requests importRequestsHTTPTransport
sample_transport=RequestsHTTPTransport(
   url='https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2',
   verify=True,
   retries=5,
)
client = Client(
   transport=sample_transport
)
# Get the value of SNX/ETH
query = gql('''
query {
 pair(id: "0x43ae24960e5534731fc831386c07755a2dc33d47"){
     reserve0
     reserve1
}
}
''')
response = client.execute(query)
snx_eth_pair = response['pair']
eth_value = float(snx_eth_pair['reserve1']) / float(snx_eth_pair['reserve0'])
# Get the value of ETH/DAI
query = gql('''
query {
 pair(id: "0xa478c2975ab1ea89e8196811f51a7b7ade33eb11"){
     reserve0
     reserve1
}
}
''')
response = client.execute(query)
eth_dai_pair = response['pair']
dai_value = float(eth_dai_pair['reserve0']) / float(eth_dai_pair['reserve1'])
snx_dai_value = eth_value * dai_value

We query The Graph to get the DAI value of SNX. We first get the ETH value of each SNX, and then multiply it by the amount of DAI equivalent to one ETH to get the DAI value of one SNX. We can then multiply the final DAI value by the amount of SNX our wallet holds to find the total USD value of the position. We had to do all these extra steps because there isn't an active pool in Uniswap to directly swap DAI for SNX. So we go from SNX to ETH to DAI. The next step will explain how we query real-time blockchain data to understand the latest status of on-chain activities.

0b3222297ab4e95d30f8b19730588f4f.png

- Click below to read the original text and join the community membership -

Guess you like

Origin blog.csdn.net/BF02jgtRS00XKtCx/article/details/124357699