通过web3。py用Python存取Ethereum
想要通过 Python 存取 Ethereum,从 Ethereum 官方的 Github 中可以看到有两种模块可以达成:web3.py 和 pyethereum 。就我目前的理解来说,两者的差别在于 web3.py 主要是作为外部存取 Ethereum 客户端,也就是说 web3.py 函数库本身不会成为区块链节点,也不会进行区块链同步,而是连接一个区块链上的节点,把区块链当成是外部资料库一样取用而已;而 pyethereum 则比较像是 geth 那样,是用来把自己做成一个区块链节点,会正常进行区块同步,也可以作为矿工开始挖矿。
在本篇当中,因为是想要一个轻量级的客户端来与区块链互动,并不想要准备庞大的储存空间来存放区块链的资料,因此会以 web3.py 为主。 配置 web3.py 执行环境 通过 web3.py 连接 Ethereum 节点 存取区块链上的 ERC20 合约 签署并送出交易
配置 web3.py 执行环境
web3.py 可以直接通过 pip 安装。 pip install web3
需注意的是,在 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 测试链的连线。 import os from web3 import ( HTTPProvider, Web3, ) INFURA_ROPSTEN_BASE_URL = "https://ropsten.infura.io/v3" def load_infura_url(): key = os.environ.get("INFURA_API_KEY", "") return "%s/%s" % (INFURA_ROPSTEN_BASE_URL, key) w3 = Web3(HTTPProvider(load_infura_url()))
存取区块链上的 ERC20 合约
在开始存取合约之前,需要先谈谈什么是 ABI 。在 Ethereum 中,因为合约都是以编译过的 binary code 形式存在,因此其实函数库没办法直接知道合约传输的内容到底是什么,因为合约的回传值全都是 binary。因此在操作合约之前,需要提供一份 ABI 文件,告诉函数库如何使用合约。 # Assume the contract we"re going to invoke is a standard ERC20 contract. with open("erc20.abi.json") as f: erc20_abi = json.load(f) # Web3 accept only checksum address. So we should ensure the given address is a # checksum address before accessing the corresponding contract. contract_addr = w3.toChecksumAddress("0x4e470dc7321e84ca96fcaedd0c8abcebbaeb68c6"); erc20_contract = w3.eth.contract(address=contract_addr, abi=erc20_abi) for func in erc20_contract.all_functions(): logger.debug("contract functions: %s", func) logger.debug("Name of the token: %s", erc20_contract.functions.name().call())
这里假设我们想存取 Ropsten 测试链上位置是 0x4e470dc7321e84ca96fcaedd0c8abcebbaeb68c6 的智能合约。这个合约是透过 etherscan 随便找的某个 ERC20 这个合约,因此可以用标准的 ERC20 的 ABI 来存取它。我们在建立这个合约的 instance 时,先跑一个回圈印出合约内所有的 function(这个步骤其实是在列出 ABI 上面的信息),接着试着呼叫合约中的 name() 来取得这个合约宣告的代币名称。最后输出的内容如下: 2018-09-07 15:02:53,815 | __main__ | DEBUG | contract functions: 2018-09-07 15:02:53,816 | __main__ | DEBUG | contract functions: 2018-09-07 15:02:53,824 | __main__ | DEBUG | contract functions: 2018-09-07 15:02:53,824 | __main__ | DEBUG | contract functions: 2018-09-07 15:02:53,824 | __main__ | DEBUG | contract functions: 2018-09-07 15:02:53,824 | __main__ | DEBUG | contract functions: 2018-09-07 15:02:53,824 | __main__ | DEBUG | contract functions: 2018-09-07 15:02:53,825 | __main__ | DEBUG | contract functions: 2018-09-07 15:02:53,825 | __main__ | DEBUG | contract functions: 2018-09-07 15:02:54,359 | __main__ | DEBUG | Name of the token: KyberNetwork
签署并送出交易
在上面的例子中,呼叫智能合约时是直接呼叫智能合约里的 function,但这一般只能用在读取区块链上的资料的状况。如果是想要通过呼叫智能合约来写入资料到区块链,就必须要用另一种方式来呼叫合约,也就是必须先签署交易,然后付 gas 去执行这个交易。
假设我们一样是要呼叫一个 ERC20 这个合约,要执行合约上的 transferFrom() 这个函数。transferFrom() 需要三个参数 _from 、 _to 、 _value ,表示要从 _from 帐号转帐给 _to 帐号,转账金额是 _value 。 # Set the account which makes the transaction. account = w3.toChecksumAddress(os.environ.get("ETHEREUM_ACCOUNT", "")) w3.eth.defaultAccount = account # Web3 accept only checksum address. So we should ensure the given address is a # checksum address before accessing the corresponding contract. contract_address = w3.toChecksumAddress("0x4e470dc7321e84ca96fcaedd0c8abcebbaeb68c6") contract = w3.eth.contract(address=contract_address, abi=contract_abi) # Prepare the necessary parameters for making a transaction on the blockchain. estimate_gas = contract.functions.transferFrom(account, account, w3.toWei("1", "eth")).estimateGas() nonce = w3.eth.getTransactionCount(account) # Build the transaction. 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) # Sign the transaction. 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 上查找这笔交易了。
美巨头没想到打脸来得这么快,欧洲多国明确表态,华为危机解除?华为的5G热潮,让中国的通信技术登上了世界之巅。然而,这引起了美国的仇恨。一轮强力镇压,试图通过限制他人的发展来保护自己的利益。尽管芯片禁令对华为的各项业务产生了重大影响,但任正非
雅迪爱玛推出新款两轮电动车,一次充电,续航最高能到300公里十年前我们还经常能够看到道路上有着汽车摩托车电动车自行车一同出行的场景,由于政策的原因,出行需求变化的原因,现在道路上几乎只能看到汽车和电动车,而自行车和摩托车基本已经被电动车所完
一个众包外卖小哥的年中总结!很中肯,也很深切自述者小文,33岁,男性,离异,一个7岁的女儿,和爸妈同住。从去年8月底开始,主业上班工资少,再加上父母年纪大了,孩子读书等开销大,让自己试图去寻找一份兼职很有必要。在刷刷小视频的
什么人的手机号长期不换?随着科学技术进步,通信功能从固定电话,寻呼机至砖头般移动手机,直到现代3G4G5G智能手机号,有关重要企业业务人员,主管(总经理董事长等),为方便业务,是不换手机号。有些企业还备有
秀出你的手机卡套餐,敢问套餐哪家强?电信29,500分钟100G全国流量。我移动用的是9块钱月,40G流量(4G),1300分钟通话时长。我办的携号转网套餐,不过移动有个大坑,大家要小心!我是今年年初办携号转网,套餐
程序员2021。9。90知乎月饼吃了拉肚子?官方致歉9月8日,知乎月饼吃了拉肚子话题登上微博热榜第一。微博凰家实验室称中秋将至,知乎给自己的国内大V发月饼,陆续有大量大V反馈试吃后化身喷射战士,腹泻拉肚
以比心陪玩为首的七款陪玩软件被强制下架原因疑似涉黄现如今游戏领域玩家已达三千万,这个数据还在不断增长,因此衍生出的许多产业链也随之出现,比如最近国家新颁发的未成年人游戏政策,又比如陪玩领域,就在近日包括比心在内的七款陪玩APP因涉
美团骑手的社保,谁来交?王兴估计不会管了互联网还没有影响人们的生活之前,虚拟网络和现实生活的联系并不多,许多人可以完全将虚拟网络和现实生活分得一清二楚。但随着互联网的不断发展,人们可以通过虚拟网络完成购物,各大平台可以通
比亚迪海豚电动飞度提前国产了?最近汽车圈动物园家族命名越来越火,例如我们耳熟能详的大狗白猫蚂蚁,最近有一款海洋朋友刚刚在成都车展上市,它就是比亚迪的全新新能源车型海豚。乍一看有些朋友可能会觉得新车和飞度有几分神
华为发布会13日召开14寸大屏手机真相大白中关村在线消息昨日华为官方宣布,9月13日召开华为智慧办公新品发布会。据悉,本次发布会华为还将发布一款14寸智能设备,被称为14寸为大屏手机。今日,据博主菊厂影业Fans爆料,所谓
20万以内纯电动车特斯拉有Model2,大众有ID。3,比亚迪呢?由于特斯拉的存在,国内纯电动车市场变得好看起来,不为别的,特斯拉不按常理出牌,动不动就官降,鲶鱼成了鲨鱼,使得众多竞争对手疲于应付。现在还好,引入国产的Model3也只是在20万以