read.cash Log in
@mosambi edited more from that month

Web3 Development - First Contact (Python) Welcome to the Python branch of my Web3 Development series. This is the first section, where we'll walk through some basic use cases of web3.py, Ethereum's Web3 library for Python. We'll create a short script to accomplish the following: https://read.cash/@mosambi/web3-development-series-introduction-558c1a97 https://web3py.readthedocs.io/en/latest/quickstart.html Get the latest block Get the first transaction from the latest block Fetch the balances of the to and from address in that transaction   Prerequisites *If you run into any issues installing or configuring these prerequisites, please do not hesitate to comment below. I'll do my best to help and will probably update this section accordingly over time.* Prerequisites are mentioned in some capacity in the series introduction post. For our purposes today, they include: https://read.cash/@mosambi/web3-development-series-introduction-558c1a97 A Python3 development environment--at the bare minimum, the ability to edit and run a python script--which could include one of the following: An IDE such as PyCharm https://www.jetbrains.com/pycharm/ Python3 and pip installed along with a text editor (could also be an IDE) and a shell/command prompt/terminal from which Python and pip may be accessed. In fact, if you're comfortable enough, you might even try to run the lines provided herein from the Python shell itself. https://pip.pypa.io/en/stable/getting-started/ RPC endpoint - see the series introduction post referenced above. This is a common requirement across all web3 development environments, so I'll try to just go in depth in one place.   How to Install Python and pip Results may vary across operating systems, but here is a nice guide I found that walks through the most common cases (MacOS, Windows, and various Linux distros): https://howchoo.com/python/install-pip-python.   Setting Things Up First, we'll install the web3.py library, which we'll be using to interact with the blockchain. https://github.com/ethereum/web3.py pip install web3 Now, web3 should be accessible from Python scripts, so we can begin coding. From here, we'll build the script out line by line. *If you don't wish to build this script out line by line, you may optionally just* *download it from GitHub* *and follow along to see how it's put together.* https://raw.githubusercontent.com/santraji/applied-web3-content/main/python/first-contact/first_contact.py Let's create a fresh Python file, **first_contact.py**, and top of it, import the **Web3** object from **web3** like so: from web3 import Web3 The **Web3** object is the root from which we can make the magic happen. To use it, we must create a new instance of it, but first, we'll need an RPC endpoint. If unsure, I've covered RPC endpoints to some extent in the Prerequisites section of the Series Introduction. https://web3py.readthedocs.io/en/latest/web3.main.html#web3.Web3 https://read.cash/@mosambi/web3-development-series-introduction-558c1a97 Let's store our RPC endpoint value in a variable, like so (replacing the URL with your endpoint): RPC_ENDPOINT = "<YOUR_RPC_ENDPOINT_HERE>" A new Web3 object expects a provider, which by default could be HTTP-, IPC-, or Websocket-based (see their docs on Built In Providers for details). For our purposes here, we'll use their **HTTPProvider**, which expects an RPC endpoint input. Convenient! https://web3py.readthedocs.io/en/v5/providers.html#built-in-providers w3 = Web3(Web3.HTTPProvider(RPC_ENDPOINT))   First Contact Now we have our own **Web3** object, but more importantly, we have access to its eth property, which we can use to talk to the blockchain. https://web3py.readthedocs.io/en/latest/web3.eth.html   ChainId To demonstrate connectivity here, and for good fun, let's print the chainId: print(f"ChainID: {hex(web3.eth.chainId)}") We make use of the built-in **hex()** here to convert the decimal value provided by **chainId** to its hex representation. The string provided to **print()** is a special string called an f-string that allows for quick inline formatting. For more information on f-strings, I quite like DigitalOcean's post about them. https://docs.python.org/3/library/functions.html#hex https://www.digitalocean.com/community/tutorials/python-f-strings-literal-string-interpolation If all is well, running **first_contact.py** now should produce something like the following: $ python first_contact.py ChainID: 0x1 Behind the scenes, **web3.eth.chainId** does actually delegate to an RPC call, meaning you just talked to the blockchain! https://web3py.readthedocs.io/en/v5/web3.eth.html#web3.eth.Eth.chain_id   Latest Block Let's try something a bit more interesting. block_latest = web3.eth.get_block("latest") print(block_latest) The above fetches the latest block to hit the chain. Returned by **get_block()** and contained within **block_latest** will be a sizable AttributeDict, or more simply, a structure housing key-value pairs. The **get_block()** docs provide a pretty good example output. https://web3py.readthedocs.io/en/v5/web3.eth.html#web3.eth.Eth.get_block For now, we'll focus on two of the block's properties: **number** and **transactions**. Let's print those as well: print(f"Latest block number: {block_latest['number']}") print(f"Transaction count: {len(block_latest['transactions'])}") Running **first_contact.py** again should produce something like: ChainID: 0x1 AttributeDict({...}) Latest block number: 16152249 Transaction count: 90 The **number** property represents the block's number, while **transactions** is a list of transaction ids contained in the block (hence us using **len()** to print the transaction count). https://docs.python.org/3/library/functions.html#len   Transactions Since we already have a block with transactions, let's explore one of them. transaction = web3.eth.get_transaction(block_latest["transactions"][0]) print(transaction) Again, if you check out the **get_transaction()** docs, you'll find a good output example. Each transaction object will have **to** and **from** attributes containing the addresses of the transaction initiator and recipient respectively. https://web3py.readthedocs.io/en/v5/web3.eth.html#web3.eth.Eth.get_transaction   Balances For kicks and giggles, let's check the balances of the **to** and **from** addresses from this transaction. To achieve this, we'll use **eth.get_balance()**: https://web3py.readthedocs.io/en/v5/web3.eth.html#web3.eth.Eth.get_balance address_to = transaction["to"] address_from = transaction["from"] balance_to = web3.eth.get_balance(address_to) balance_from = web3.eth.get_balance(address_from) print(f"Balance of {address_to} ('to' address) is {balance_to}") print(f"Balance of {address_from} ('from' address) is {balance_from}") If you run **first_contact.py** again, you may notice something weird about the balances: ... Balance of 0x929832b1f1515cf02c9548A0fF454f1B0E216B18 ('to' address) is 0 Balance of 0x8A01fa5A77311BBCf29e293D8EcB48707cfDB700 ('from' address) is 8924442679551502040 **get_balance** returns the account's balance in *wei*. If this is what you're looking for, great. Otherwise, thankfully, the library provides a nice little helper function to convert this to a more familiar representation: **web3.fromWei()**. Let's rewrite those two lines that fetch the balances: https://ethereum.org/en/developers/docs/intro-to-ether/#denominations https://web3py.readthedocs.io/en/v5/web3.main.html#web3.Web3.fromWei balance_to = web3.fromWei(web3.eth.get_balance(address_to), "ether") balance_from = web3.fromWei(web3.eth.get_balance(address_from), "ether") That's better: ... Balance of 0x929832b1f1515cf02c9548A0fF454f1B0E216B18 ('to' address) is 0 Balance of 0x8A01fa5A77311BBCf29e293D8EcB48707cfDB700 ('from' address) is 8.92444267955150204   Putting Everything Together Now, our **first_contact.py** should be roughly identical to the one in the GitHub repo. Let's run the entire script once more: https://github.com/santraji/applied-web3-content/blob/main/python/first-contact/first_contact.py ChainID: 0x1 AttributeDict({...}) Latest block number: 16152249 Transaction count: 90 AttributeDict({...}) Balance of 0x929832b1f1515cf02c9548A0fF454f1B0E216B18 ('to' address) is 0 Balance of 0x8A01fa5A77311BBCf29e293D8EcB48707cfDB700 ('from' address) is 8.297836181652525434   That's a Wrap! Today, we accomplished a number of things. For those new to this, we spoke to the blockchain for the first time, and in fact, had a decent chat with it (4 calls in total: 1 to **chainId**, 1 to **get_transaction()**, and 2 to **get_balance()**). The complete script for this section may be found on the series Github repo. https://github.com/santraji/applied-web3-content/blob/main/python/first-contact/first_contact.py In the next section, we'll explore how to create and manage transactions and talk to smart contracts. Thanks for reading and hope to see you then! This article was originally published on my Publish0x Applied Web3 blog. https://www.publish0x.com/applied-web3/web3-development-first-contact-python-xqeywpe?a=Jrb2RpvzbW&tid=read

No comments yet

Log in to join in Reading is open to everyone. Replying needs an account.