从零到英雄:使用infura和python学习web3
#python #web3 #区块链 #ethereum

Web3,区块链技术和加密货币都是引人入胜的主题。技术,应用,生态系统和对社会的影响都以令人难以置信的速度移动。在本文中,我们将从一位经验丰富的Web3 Newbie的经验丰富的开发人员的角度来学习Web3开发。我们将查看Web3开发的先决条件,使用Python通过Infura,Web3的顶级API服务访问区块链,并浏览一个简单的项目来管理钱包。

如何开始

即使自1990年代后期以来我一直在编码,但我确实是Web3世界的完整初学者。我不是专家,所以我不会尝试解释基本面。那里有很多很棒的内容指南和教程。我建议starting with the Infura documentation,非常全面且可理解。

如果您更喜欢一种更具互动的学习风格,也有一个community discord

无论如何,让我们从一些基础开始。我们需要一个infura帐户,一个钱包来存储我们的加密货币,我们需要一些钱来玩。

开设一个infura的帐户

Infura是区块链API和开发人员工具的提供商。这意味着,如果您想访问区块链,则无需自己运行节点。取而代之的是,您只需访问友好的API即可,而Infura为您完成了所有繁重的举重。 Infura是免费且完全安全的,因为它没有存储您的私钥,也没有修改交易或多次重播交易的能力。

您可以open an account here for free,无需信用卡。

创建一个Infura项目

一个项目变得有趣。每个项目都有一个API密钥,可以标识并允许您使用Infura。 Follow the instructions here

设置加密钱包

下一个难题是加密钱包。这是橡胶遇到道路的地方。在区块链环境中,加密钱包拥有由一组数字钥匙完全控制的余额。没有一个帐户的个人所有权。每个帐户都有一个公共密钥 - 在区块链中可见 - 和一个控制帐户的私钥。持有私钥的人都可以完全控制帐户。您还可以将多个帐户作为一组私钥管理。钱包为您提供了管理帐户/私钥以及其他好处(例如便利性,可移植性和兼容性)的安全方法。

infura推荐MetaMask。您可以作为浏览器扩展名为install MetaMask

太好了,我们有一个加密钱包。现在让我们谈谈!

赚钱

区块链不是免费的。加密经济学远高于我的工资等级,但简单来说,每笔交易要花钱。如果您想在区块链上玩,则需要资金。幸运的是,对于开发人员来说,有一些测试网络可让您免费获得测试资金。您不能将其换成真钱,但是您可以将其用于开发和测试Web3应用程序。

谈到哪些类型的网络。在这里,我们将重点关注Ethereum区块链。

在这个项目中,我使用了Testnet Sepolia。您可以通过进入水龙头站点从Sepolia获得测试ETH。 (ETH是以太坊的本地加密货币。

水龙头站点可以将少量的TestNet ETH转移到您的钱包中。有些水龙头将要求您进行一些采矿以赚钱,有些则会定期给您一些钱。我在ConsenSys Sepolia faucet上取得了成功,该ConsenSys Sepolia faucet每天给出.5 Sepolia Eth的地址。

好的。我们涵盖了所有基础知识。让我们检查一下infura api。

访问Infura API

INFURA通过HTTPS(REST)和WebSocket提供JSON-RPC API。它有多个类别和you can read all about them here

此外,INFURA API支持多个不同的网络。每个网络都有自己的HTTPS端点,您在访问API时用作基本URL。

这是以太坊的终点:

主网

Goerli

sepolia

只是为了测试我们可以访问API,让我们使用卷发来获得钱包的平衡。

我在环境变量中存储了infura api键和API密钥秘密,称为

INFURA_API_KEYINFURA_API_KEY_SECRET。我还将metamask钱包的公共密钥存储在称为SEPOLIA_ACCOUNT的环境变量中。

curl命令是:

$ 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"}

如您所见,我的余额为0x1d7e6e62f1523600 !!!!但是,无需太兴奋;余额单位是WEI。一个eth等于10^18 wei。如果我们处理数字,我们可以看到我的帐户中有2个以上的ETH。当然,这都是Testnet Money。

请注意,我不必使用我的帐户的私钥来检查我的余额。任何人都可以检查区块链中任何帐户的余额。任何帐户的余额都不是敏感信息。但是,帐户的身份和持有私钥的人是敏感和机密的。

好吧…我们很开心直接击中Infura API。让我们做一些编码。

Web3开发与Python

Web3生态系统支持许多编程语言。可以从JavaScript(web3.js and ethers.js),Golang(github.com/ethereum/go-ethereum)和Python(web3.py)中的流行库中访问INFURA API。

选择您的武器web3.py

尽管如今的大多数编码都在JavaScript/node.js和Ruby中,但在学习新主题时,Python很棒。 Web3.py库似乎有力,成熟且有据可查。所以我决定选择它。

选择您的目标 - 钱包经理

Web3世界可能是压倒性的:交易,智能合约,IPFS,DAO(分散自主组织),Defi(分散融资),NFTS。我决定为此Web3测试项目选择一个简单的钱包经理概念。钱包经理是一个“ Hello Web3世界”项目,因为它所做的就是获得您的余额并向目的地帐户发送一些钱。由于我从棕褐色的水龙头那里得到了钱,因此我决定通过寄出一些资金来回馈。让我们查看代码。

Web3检测DAPP(分散应用程序)

代码为available on Github here。 (特别感谢the-gigi!)

我使用Poetry脚手架。 README提供了分步说明来设置所有内容。
在我们深入了解代码之前,让我们运行程序,看看会发生什么:

$ poetry run python main.py

balance before transaction: 2.1252574454
send 20,000 gwei to 0xea4d57b2dd421c5bfc893d126ec15bc42b3d0bcd (Sepolia faucet account)
balance after transaction: 2.125184945399832

您可以看到,我的平衡最初有点超过2个testnet eth。然后,我向我从首先从我那里得到的Sepolia水龙头帐户发送了20,000 Gwei(为200亿WEI)。如您所见,它几乎没有使我的平衡陷入困境。这只是显示了WEI是一个小单位。

代码非常简单。只有一个叫做main.py的文件。该文件包含main()函数和WalletManager类。让我们从main()函数开始,这是程序的切入点。

main()函数没有命令行参数或配置文件。一切都是为简单而硬编码的。首先,该函数实例化WalletManager类,然后定义Sepolia Faucet帐户的公共密钥。现在,我们开始采取行动。该函数通过调用WalletManagerget_balance()方法,然后通过请求的单元(ether)来获得钱包的余额,并将其显示在屏幕上。接下来,该函数调用send_eth()方法将20,000 GWEI发送到目标帐户。最后,它在寄出钱后再次获得并再次显示余额。

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

让我们看一下WalletManager类。它有四种方法:

  1. __init__()
  2. __create_web3_instance()
  3. get_balance()
  4. sent_eth()

方法1:__init__()

让我们一一看看它们。 __init__()方法是构造函数,首先称为__create_web3_instance()方法,并将结果存储在称为w3的变量中。然后,__init__()提取了几个环境变量并将其存储。它继续计算几个汽油费(这是区块链正在运行的燃料),并给予验证交易的人的奖励。如果您想know more about gas and fees, read this

它还存储链ID,该链ID标识了棕褐色测试网(在这种情况下)。将交易发送到Sepolia testnet时,我们稍后将需要此ID。

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

方法2:__create_web3_instance()

让我们看看__create_web3_instance()方法中会发生什么。
__create_web3_instance()是一种静态方法,因为它不需要WalletManager类中的任何信息。它从环境中获取Infura API密钥和API密钥秘密,然后将它们编码为基本的身份验证令牌。它为我们的项目在Sepolia TestNet上准备了适当的端点,然后从Web3库中实例化Web3对象,并使用所有信息。该对象将允许我们通过方便的Python接口调用Infura API(而不是构造JSON-RPC请求并解析结果)。

@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)))

方法3:get_balance()

好吧,接下来是get_balance()方法。

这是一种非常简单的方法。它只是调用Web3对象的w3.eth.get_balance()方法并通过我们的帐户。 eth.get_balance()总是返回Wei中的结果,该结果通常太小。我们的方法为我们提供了将结果转换为GweiEther等另一个面额的选项。它通过调用我们的Web3实例再次提供的w3.fromWei()方法来做到这一点。请注意,我们不必使用私钥来检查余额。

balance = self.w3.eth.get_balance(selpytf.account)
if unit != 'wei':
    return self.w3.fromWei(balance, unit)

方法4:send_eth()

最后但并非最不重要的是send_eth()方法。这里有很多事情发生,所以让我们将其分解为多个块。

首先,send_eth()将发送到WEI的金额转换为WEI(如有必要),然后将其获取帐户的交易计数,并将其存储为Nonce。 NONCE允许我们在需要时覆盖未决的交易。

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)

接下来,它构建一个事务对象。最重要的字段是from(钱包帐户),to(交易的收件人)和value(要发送多少)。然后,有一些田地决定要支付多少汽油。 (气体越多,验证器包含交易的可能性就越大)chainId标识网络可以运行此交易的网络和几个管理字段(空的datatype)。

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)

好的。我们有一项交易,所以我们可以发送吗?不那么快。首先,我们需要用我们的私钥签名。这就是阻止其他人从我们的帐户中转移资金的原因。使用私钥签署交易,允许验证者确认私钥是否对应于帐户的公钥。

signed_tx = self.w3.eth.account.sign_transaction(tx, self.account_private_key)

现在,我们可以将交易作为原始交易发送。这意味着infura从未看到我们的私钥,它不能改变我们的交易或将我们的转移转移到另一个帐户。这是区块链在行动中的魔力。发送交易后,我们恢复了哈希代码,并等待交易完成。如果结果的状态为1,那么一切都很好。如果不是,则代码会引起例外。

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}')

这就是与区块链以非常基本但安全的方式进行交互所需的。

结论:使用Infura开始您的W​​eb3旅程

首先进入Web3世界也可能令人生畏,即使对于经验丰富的程序员来说。我们学到了很多;大多数情况下,我们了解到我们还有更多的学习! Infura通过提供可靠的API,出色的指导和与生态系统的其他组件(如MetAmask和Web3.Py库)的强大集成来轻松实现。如果您处于类似的位置,并且想学习Web3开发 - 甚至想开始Web3职业 - 我强烈建议您从Infura开始。看看旅程带您到哪里!