如何通过web3.py用Python存取Ethereum

这篇文章主要介绍了如何通过web3.py用Python存取Ethereum的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何通过web3.py用Python存取Ethereum文章都会有所收获,下面我们一起来看看吧。

配置 web3.py 执行环境

web3.py 可以直接通过 pip 安装。

pipinstallweb3

需注意的是,在 Windows 上想安装时,会需要事先安装 Visual C++ Builder,否则在安装的最后阶段会因为无法编译而失败。

通过 web3.py 连结 Ethereum 节点

web3.py 因为自身不会作为一个区块链的节点存在,因此它需要有一个节点用来存取区块链上的资料。一般来说最安全的方式应该是自己使用 geth 或者 parity 来自建节点,不过如果在不想要自建节点的状况时,可以考虑看看 infura 提供的 HTTP 节点服务。

以 infura 现在的 API 来说,如果要连结 Ropsten 测试链,连结的网址是 https://ropsten.infura.io/v3/api_key,其中 api_key 要去注册帐号才取得。以下的程序仿照了 web3.py 内建的 auto.infura 的作法,会从环境变数读取 INFURA_API_KEY 这个参数来组出 infura.io 的 HTTP 位址,用来建立跟 Ropsten 测试链的连线。

存取区块链上的 ERC20 合约
importos
fromweb3import(
HTTPProvider,
Web3,
)
INFURA_ROPSTEN_BASE_URL='https://ropsten.infura.io/v3'
defload_infura_url():
key=os.environ.get('INFURA_API_KEY','')
return"%s/%s"%(INFURA_ROPSTEN_BASE_URL,key)
w3=Web3(HTTPProvider(load_infura_url()))

在开始存取合约之前,需要先谈谈什么是 ABI 。在 Ethereum 中,因为合约都是以编译过的 binary code 形式存在,因此其实函数库没办法直接知道合约传输的内容到底是什么,因为合约的回传值全都是 binary。因此在操作合约之前,需要提供一份 ABI 文件,告诉函数库如何使用合约。

#Assumethecontractwe'regoingtoinvokeisastandardERC20contract.
withopen("erc20.abi.json")asf:
erc20_abi=json.load(f)
#Web3acceptonlychecksumaddress.Soweshouldensurethegivenaddressisa
#checksumaddressbeforeaccessingthecorrespondingcontract.
contract_addr=w3.toChecksumAddress('0x4e470dc7321e84ca96fcaedd0c8abcebbaeb68c6');
    
erc20_contract=w3.eth.contract(address=contract_addr,abi=erc20_abi)
forfuncinerc20_contract.all_functions():
logger.debug('contractfunctions:%s',func)
logger.debug("Nameofthetoken:%s",erc20_contract.functions.name().call())

这里假设我们想存取 Ropsten 测试链上位址是 0x4e470dc7321e84ca96fcaedd0c8abcebbaeb68c6 的智能合约。这个合约是透过 etherscan 随便找的某个 ERC20 的合约,因此可以用标准的 ERC20 的 ABI 来存取它。我们在建立这个合约的 instance 时,先跑一个回圈印出合约内所有的 function(这个步骤其实是在列出 ABI 上的信息),接着试着呼叫合约中的 name() 来取得这个合约宣告的代币名称。最后输出的内容如下:

2018-09-0715:02:53,815|__main__|DEBUG|contractfunctions:2018-09-0715:02:53,816|__main__|DEBUG|contractfunctions:2018-09-0715:02:53,824|__main__|DEBUG|contractfunctions:2018-09-0715:02:53,824|__main__|DEBUG|contractfunctions:2018-09-0715:02:53,824|__main__|DEBUG|contractfunctions:2018-09-0715:02:53,824|__main__|DEBUG|contractfunctions:2018-09-0715:02:53,824|__main__|DEBUG|contractfunctions:2018-09-0715:02:53,825|__main__|DEBUG|contractfunctions:2018-09-0715:02:53,825|__main__|DEBUG|contractfunctions:2018-09-0715:02:54,359|__main__|DEBUG|Nameofthetoken:KyberNetwork
签署并送出交易

在上面的例子中,呼叫智能合约时是直接呼叫合约里的 function,但这一般只能用在读取区块链上的资料的状况。如果是想要通过呼叫智能合约来写入资料到区块链,就必须要用另一种方式来呼叫合约,也就是必须先签署交易,然后付 gas 去执行这个交易。

假设我们一样是要呼叫一个 ERC20 的合约,要执行合约上的 transferFrom() 这个函数。transferFrom() 需要三个参数 _from、 _to、 _value,表示要从 _from 帐号转帐给 _to 帐号,转帐金额是 _value。

#Settheaccountwhichmakesthetransaction.
account=w3.toChecksumAddress(os.environ.get('ETHEREUM_ACCOUNT',''))
w3.eth.defaultAccount=account
#Web3acceptonlychecksumaddress.Soweshouldensurethegivenaddressisa
#checksumaddressbeforeaccessingthecorrespondingcontract.
contract_address=w3.toChecksumAddress('0x4e470dc7321e84ca96fcaedd0c8abcebbaeb68c6')
contract=w3.eth.contract(address=contract_address,abi=contract_abi)
#Preparethenecessaryparametersformakingatransactionontheblockchain.
estimate_gas=contract.functions.transferFrom(account,account,w3.toWei('1','eth')).estimateGas()
nonce=w3.eth.getTransactionCount(account)
#Buildthetransaction.
txn=contract.functions.transferFrom(account,account,w3.toWei('1','eth')).buildTransaction({

'chainId':3,
'gas':estimate_gas,
'gasPrice':w3.toWei('1','gwei'),
'nonce':nonce
}
    )
logger.debug('Transaction:%s',txn)
#Signthetransaction.
private_key=bytes.fromhex(os.environ.get('ETHEREUM_ACCOUNT_PKEY',''))
signed_txn=w3.eth.account.signTransaction(txn,private_key=private_key)
tx_hash=w3.eth.sendRawTransaction(signed_txn.rawTransaction)
logger.debug('Txhash:0x%s',bytes.hex(tx_hash))

在上面的程序中,首先第 2 ~ 3 行先从环境变量中读取我们要使用的帐号,这个帐号将会用来发送交易,当然要付 gas 时也会从这个帐号扣。第 10 ~ 20 行建立一个原始交易(raw transaction),这个交易中因为我们需要自行指定包括 gas、nonce 等参数,因此需要在前面 11 ~ 12 行确认参数要设定多少。然后最重要的第 25 ~ 26 行读取私钥,并且用私钥去签署交易。这里假设私钥的组成会是用 Hex 编码的文字,所以使用 bytes.fromhex 把 Hex 编码转回成 byte 格式。签好以后就送出交易,送出交易时 API 会回传 byte 格式的交易的 transaction hash,可以把它编码后印出来,之后就可以去 etherscan 上查找这笔交易了。

关于“如何通过web3.py用Python存取Ethereum”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“如何通过web3.py用Python存取Ethereum”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注行业资讯频道。