Web3, blockchain technology, and cryptocurrency are all fascinating topics. The technology, applications, ecosystem, and impact on society are all moving at incredible speeds. In this article, we will talk about learning web3 development from the point of view of a seasoned developer who is a total web3 newbie. We will look at the prerequisites for web3 development, use Python to access the blockchain via Infura, web3's top API service, and go over a simple project for managing a wallet. How to Get Started Even though I've been coding since the late 1990s, I am truly a complete beginner in the web3 world. I'm no expert, so I won't try to explain the fundamentals. There are a lot of great content guides and tutorials out there. I suggest , which is very comprehensive as well as comprehensible. starting with the Infura documentation There is also a if you prefer a more interactive style of learning. community discord Anyway, let's start with some basics. We need an Infura account, a wallet to store our cryptocurrency, and we need some money to play with. Opening an Account With Infura is a provider of blockchain APIs and developer tools. This means that if you want to access the blockchain, you don't need to run a node yourself. Instead, you just access a friendly API, and Infura does all the heavy lifting for you. Infura Infura is free and totally secure, as it doesn't store your private keys and doesn't have the ability to modify your transactions or replay them multiple times. You can ; no credit card required. open an account here for free Creating an Infura Project A project is where things become interesting. Each project has an API key, which identifies it and allows you to use Infura. . Follow the instructions here Setting Up a Crypto Wallet The next piece of the puzzle is a crypto wallet. This is where the rubber meets the road. In the blockchain environment, crypto wallets hold balances that are fully controlled by a set of digital keys. There is no such thing as personal ownership of an account. Each account has a public key - which is visible in the blockchain - and a private key that controls the account. Whoever holds a private key has total control of an account. You may also manage multiple accounts as a set of private keys. Wallets give you a secure way to manage your accounts/private keys as well as other benefits such as convenience, portability, and compatibility. Infura recommends . You can as a browser extension. MetaMask install MetaMask Great, we have a crypto wallet. Now let's talk money! Getting Some Money The blockchain is not free. Crypto economics are way above my pay grade, but in simple terms, each transaction costs money. If you want to play on the blockchain, you need funds. Luckily for developers, there are test networks that let you get test money for free. You can't exchange it for real money, but you can use it for developing and testing web3 applications. Speaking of which, there are different types of networks. Here, we will focus on the blockchain. Ethereum In this project, I used the testnet Sepolia. You can get test ETH from Sepolia by going to a faucet site. (ETH is Ethereum's native cryptocurrency. You use it to pay for transactions on the Ethereum network. Test ETH is a necessity for Ethereum development.) A faucet site can transfer a small amount of testnet ETH to your wallet. Some faucets will require you to do some mining to earn your money, and some will gift you some money periodically. I had success with the which gives out .5 Sepolia ETH per day to an address. ConsenSys Sepolia faucet OK. We covered all the basics. Let's check out the Infura API. Accessing the Infura API Infura provides a JSON-RPC API over HTTPS (REST) and WebSockets. It has several categories, and . you can read all about them here Additionally, the Infura API supports multiple different networks. Each network has its own HTTPs endpoint that you use as a base URL when accessing the API. Here are the endpoints for Ethereum: Mainnet Ethereum Mainnet JSON-RPC over HTTPS— https://mainnet.infura.io/v3/<API-KEY> Ethereum Mainnet JSON-RPC over WebSocket— wss://mainnet.infura.io/ws/v3/<API-KEY> Goerli Ethereum Goerli Testnet JSON-RPC over HTTPS— https://goerli.infura.io/v3/<API-KEY> Ethereum Goerli Testnet JSON-RPC over WebSocket— wss://goerli.infura.io/ws/v3/<API-KEY> Sepolia Ethereum Sepolia Testnet JSON-RPC over HTTPS— https://sepolia.infura.io/v3/<API-KEY> Ethereum Sepolia Testnet JSON-RPC over WebSocket— wss://sepolia.infura.io/ws/v3/<API-KEY> Just to test that we can access the API, let's get our wallet balance using curl. I stored the Infura API key and API key secret in environment variables called simply: and . I also stored the public key of the MetaMask wallet in an environment variable called . INFURA_API_KEY INFURA_API_KEY_SECRET SEPOLIA_ACCOUNT The curl command is: $ curl --user ${INFURA_API_KEY}:${INFURA_API_KEY_SECRET} \ -X POST \ -H "Content-Type: application/json" \ --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["'"${SEPOLIA_ACCOUNT}"'","latest"],"id":1}' \ https://sepolia.infura.io/v3/${INFURA_API_KEY} {"jsonrpc":"2.0","id":1,"result":"0x1d7e6e62f1523600"} As you can see, I have a HUGE balance of 0x1d7e6e62f1523600!!!! But, no need to get too excited; the balance units are Wei. One ETH is equal to Wei. If we crunch the numbers, we can see that I have a little more than 2 ETH in my account. Of course, this is all testnet money. 10^18 Note that I didn't have to use my account's private key to check my balance. Anyone can check the balance of any account in the blockchain. The balance of any account is not sensitive information. However, the identity of the account and the person that holds the private key is sensitive and confidential. All right… we had our fun with hitting the Infura API directly. Let's do some coding. Web3 Development With Python The web3 ecosystem supports many programming languages. Infura APIs can be accessed from popular libraries in JavaScript (web3.js and ethers.js), Golang ( ), and Python ( ). github.com/ethereum/go-ethereum web3.py Choose Your Weapon — web3.py Although most coding these days is in JavaScript/Node.js and Ruby, Python is great when learning a new topic. The library seems powerful, mature, and well-documented. So, I decided to go with it. web3.py Choose Your Target — Wallet Manager The web3 world can be overwhelming: transactions, smart contracts, IPFS, DAO (decentralized autonomous organizations), defi (decentralized finance), and NFTs. I decided to pick a simple concept of a wallet manager for this web3 test project. The wallet manager is kind of a "hello web3 world" project because all it does is get your balance and send some money to a destination account. Since I got my money from a Sepolia faucet, I decided to give back by sending some of the funds. Let's check out the code. The Web3-Test Dapp (Decentralized App) The code is . (Special thanks to !) available on Github here the-gigi I used to scaffold the application. The README provides step-by-step instructions to set up everything. Poetry Before we dive into the code, let's run the program and see what happens: $ poetry run python main.py balance before transaction: 2.1252574454 send 20,000 gwei to 0xea4d57b2dd421c5bfc893d126ec15bc42b3d0bcd (Sepolia faucet account) balance after transaction: 2.125184945399832 As you can see, my balance was initially a little over 2 testnet ETH. Then, I sent 20,000 Gwei (which is 20 billion Wei) to the Sepolia faucet account that I got the money from in the first place. As you can see, it barely made a dent in my balance. This just shows what a tiny unit the Wei is. The code is pretty simple. There is just a single file called . The file contains a function and a class. Let's start with the function which is the entry point to the program. main.py main() WalletManager main() The function takes no command-line arguments or configuration files. Everything is hard-coded for simplicity. First, the function instantiates the class; then it defines the public key of the Sepolia faucet account. main() WalletManager Now, we get to the action. The function obtains the balance of the wallet by invoking the method of ; then it passes the requested unit ( ), and displays it on screen. get_balance() WalletManager ether Next, the function invokes the method to send 20,000 Gwei to the target account. Finally, it gets and displays the balance again after the money has been sent. send_eth() def main(): wm = WalletManager() sepolia_faucet_account = wm.w3.toChecksumAddress('0xea4d57b2dd421c5bfc893d126ec15bc42b3d0bcd') balance = str(wm.get_balance('ether')) print(f'balance before transaction: {balance}') print(f'send 20,000 gwei to {sepolia_faucet_account} (Sepolia faucet account)') wm.send_eth(sepolia_faucet_account, 20000, 'gwei') balance = str(wm.get_balance('ether')) print(f'balance after transaction: {balance}') if __name__ == '__main__': main() Let's look at the class. It has four methods: WalletManager __init__() __create_web3_instance() get_balance() sent_eth() Method 1: __init__() Let's look at them one by one. The method, which is the constructor, first calls the method and stores the result in a variable called . __init__() __create_web3_instance() w3 Then extracts a couple of environment variables and stores them. It continues to compute a couple of gas fees (which is the fuel the blockchain is running on) and the rewards that are given to the people that validate transactions. __init__() If you want to . know more about gas and fees, read this It also stores the chain ID, which identifies the Sepolia testnet (in this case). We will need this ID later when sending transactions to the Sepolia testnet. import base64 import os import web3 class WalletManager: def __init__(self): self.w3 = self.__create_web3_instance() self.account = os.environ['SEPOLIA_ACCOUNT'] self.account_private_key = os.environ['METAMASK_PRIVATE_KEY'] self.max_fee_per_gas = self.w3.toWei('250', 'gwei') self.max_priority_fee_per_gas = self.w3.eth.max_priority_fee self.chain_id = self.w3.eth.chain_id Method 2: __create_web3_instance() Let's see what happens inside the method. is a static method because it doesn't need any information from the class. __create_web3_instance() __create_web3_instance() WalletManager It gets the Infura API key and API key secret from the environment, and then it encodes them into a basic authentication token. It prepares the proper endpoint for our project on the Sepolia testnet, and then it instantiates a web3 object from the web3 library with all the information. This object will allow us to invoke the Infura API via a convenient Python interface (instead of constructing JSON-RPC requests and parsing the results). @staticmethod def __create_web3_instance(): infura_api_key = os.environ['INFURA_API_KEY'] infura_api_key_secret = os.environ['INFURA_API_KEY_SECRET'] data = f'{infura_api_key}:{infura_api_key_secret}'.encode('ascii') basic_auth_token = base64.b64encode(data).strip().decode('utf-8') infura_sepolia_endpoint = f'https://sepolia.infura.io/v3/{infura_api_key}' headers = dict(Authorization=f'Basic {basic_auth_token}') return web3.Web3(web3.HTTPProvider(infura_sepolia_endpoint, request_kwargs=dict(headers=headers))) Method 3: get_balance() Alright, next is the method. get_balance() It is an extremely simple method. It just invokes the method of the web3 object and passes our account. The always returns the result in , which is often too small. w3.eth.get_balance() eth.get_balance() Wei Our method provides us with the option to convert the result to another denomination like or . It does it by invoking the method provided again by our web3 instance. Note that we didn't have to use our private key to check the balance. Gwei Ether w3.fromWei() balance = self.w3.eth.get_balance(selpytf.account) if unit != 'wei': return self.w3.fromWei(balance, unit) Method 4: send_eth() Last, but not least, is the method. There is a lot going on here, so let's break it into multiple blocks. send_eth() First, converts the amount to send to Wei (if necessary), and then it gets the transaction count of the account and stores it as nonce. The nonce allows us to overwrite pending transactions if needed. send_eth() def send_eth(self, target_account, amount, unit='wei'): if unit != 'wei': amount = self.w3.toWei(amount, unit) nonce = self.w3.eth.get_transaction_count(self.account) Next, it constructs a transaction object. The most important fields are the (the wallet's account), the (the transaction's recipient) and the (how much to send). Then, there are the fields that determine how much gas to pay. from to value (The more gas, the more likely that validators will include the transaction,) The identifies the network to run this transaction against and a couple of administrative fields (empty and ). chainId data type tx = {'nonce': nonce, 'maxFeePerGas': self.max_fee_per_gas, 'maxPriorityFeePerGas': self.max_priority_fee_per_gas, 'from': self.account, 'to': target_account, 'value': amount, 'data': b'', 'type': 2, 'chainId': self.chain_id} tx['gas'] = self.w3.eth.estimate_gas(tx) OK. We have a transaction, so can we send it? Not so fast. First, we need to sign it with our private key. This is what prevents other people from transferring money out of our account. Signing the transaction with the private key allows validators to confirm that the private key corresponds to the public key of the account. signed_tx = self.w3.eth.account.sign_transaction(tx, self.account_private_key) Now we can send the transaction as a raw transaction. This means that Infura never sees our private key, and it can't change our transaction or direct our transfer to a different account. This is the magic of the blockchain in action. After sending the transaction, we get back a hash code and wait for the transaction to complete. If the status of the result is 1, then all is well. If not, the code raises an exception. tx_hash = self.w3.eth.send_raw_transaction(signed_tx.rawTransaction) result = self.w3.eth.wait_for_transaction_receipt(tx_hash) if result['status'] != 1: raise RuntimeError('transaction failed: {tx_hash}') That's all it takes to interact in a very basic, yet secure way with the blockchain. Conclusion: Start Your Web3 Journey With Infura Diving headfirst into the world of web3 can be intimidating, even for an experienced programmer. We've learned a lot; mostly, we've learned that we have a lot more to learn! Infura made it easy by providing a solid API, great guidance, and strong integration with other components of the ecosystem, like MetaMask and the library. web3.py If you are in a similar position and want to learn web3 development - or even want to start a web3 career - I highly recommend starting with Infura. See where the journey takes you!