以太坊 geth 客户端提供自带的交互接口即 web3j ,来控制节点的信息操作。到实际开发中,不论是采用 Java 版的 web3j,还是 Python 版的 web3j,其实关系就不是很大了。
web3 js :https://web3js.readthedocs.io/en/v2.0.0-alpha/
java-web3j:https://docs.web3j.io/getting_started/
python-web3j:https://web3py.readthedocs.io/en/latest/index.html
Tips:<对应的可自行搜索中文相关文档,这里就不一一列出,英语文档想对详细些。中文看过后,开发过程中遇到问题,查看英语文档可了解更多相关信息。>
下面主要列举些 web3.py 里面的常用语句。这里我是写了一个关于节点的类,常用的语句单独写为一个方法。
1. 连接节点
def start_node(db='D:/eth-test/db/', port='30303', rpcport='8545'): cmdOrder = 'geth --datadir ' + db + ' --rpc --rpcapi "eth,net,web3,personal,admin,txpool,debug,miner"' ' --port ' + port + ' --rpcport ' + rpcport + ' --nodiscover --rpccorsdomain "*" --allow-insecure-unlock' ' --ipcdisable' os.system(cmdOrder)
2. 生成 web3 实例
def __init__(self, ip, rpcport): # 连接本地以太坊节点 self.w3 = Web3(Web3.HTTPProvider('http://' + ip + ':' + rpcport, request_kwargs={'timeout': 60}))
3. 返回当前的账户列表
# 返回当前所有账户 def getAddrs(self): return self.w3.eth.accounts
4. 返回指定账户余额
# 返回指定地址的余额 def getBalance(self, addr): balance = self.w3.fromWei(self.w3.eth.getBalance(addr), 'ether') return balance
5. 返回当前节点的 enode
此作用用来添加节点
# 返回当前节点的 enode 信息 def getEnode(self): return self.w3.geth.admin.node_info()['enode']
6. 返回节点个数
# 返回当前节点数 def peers(self): return self.w3.geth.admin.peers()
7. 添加节点
# 当前节点添加节点 def addPeer(self, enode): return self.w3.geth.admin.add_peer(enode)
8. 挖矿、停止挖矿
# 开始挖矿 def minerStart(self): self.w3.geth.miner.start(1) # 结束挖矿 def minerStop(self): self.w3.geth.miner.stop()
9. 部署智能合约
部署合约以及对智能合约的调用(改变合约状态时),都需要设置节点默认账户,并解锁该账户。此外还需要 引入 solc.exe 文件(放在同级目录)
from web3 import Web3
from solc import compile_standard
personal.unlockAccount(ins.getAddrs()[2], 'sophia', 300) # 参数分别为 账户地址、私匙、解锁时间(秒)
def contractCompile(ins): compiledSol = compile_standard({ 'language': 'Solidity', 'sources': {'UserInfo.sol': { 'content': ''' pragma solidity ^0.6.0; contract UserInfo { string name; uint age; bool gender = true; constructor() public{ name = 'junweiJun'; age = 18; gender = true; } function setAttr(string memory _name, uint _age, bool _gender) public{ name = _name; age = _age; gender = _gender; } function getAttr() public view returns (string memory, uint, bool) { return (name, age, gender); } } ''' } }, "settings": { "outputSelection": { "*": { "*": [ "metadata", "evm.bytecode" , "evm.bytecode.sourceMap" ] } } } }) # 设置默认账户 # ins.w3.eth.coinbase = ins.getAddrs()[1] # 获取 bytecode bytecode = compiledSol['contracts']['UserInfo.sol']['UserInfo']['evm']['bytecode']['object'] # 获取 abi abi = json.loads(compiledSol['contracts']['UserInfo.sol']['UserInfo']['metadata'])['output']['abi'] print("abi:", abi) # 生成合约 UserInfo = ins.w3.eth.contract(abi=abi, bytecode=bytecode) # # 部署合约 print(ins.w3.eth.defaultAccount) ins.w3.eth.defaultAccount = ins.getAddrs()[1] print(ins.w3.eth.defaultAccount) # 解锁账户 ins.w3.geth.personal.unlockAccount(ins.getAddrs()[1], 'xsmile', 300) # 设置 defaultAccount 并解锁账户,否则会出现 ValueError: {'code': -32000, 'message': 'unknown account'} txHash = UserInfo.constructor().transact() try: ins.minerStart() # # 等待合约被挖掘 txReceipt = ins.w3.eth.waitForTransactionReceipt(txHash) print('txReceipt:', txReceipt) # ins.minerStop() userInfo = ins.w3.eth.contract(address=txReceipt.contractAddress, abi=abi) user = userInfo.functions.getAttr().call() print('init: ', user) except Exception: pass finally: ins.minerStop() pass
10. 调用智能合约
def updateContract(ins): # 解锁账户 ins.w3.eth.defaultAccount = ins.getAddrs()[2] ins.w3.geth.personal.unlockAccount(ins.getAddrs()[2], 'sophia', 300) abi = [{'inputs': [], 'stateMutability': 'nonpayable', 'type': 'constructor'}, {'inputs': [], 'name': 'getAttr', 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}, {'internalType': 'uint256', 'name': '', 'type': 'uint256'}, {'internalType': 'bool', 'name': '', 'type': 'bool'}], 'stateMutability': 'view', 'type': 'function'}, {'inputs': [{'internalType': 'string', 'name': '_name', 'type': 'string'}, {'internalType': 'uint256', 'name': '_age', 'type': 'uint256'}, {'internalType': 'bool', 'name': '_gender', 'type': 'bool'}], 'name': 'setAttr', 'outputs': [], 'stateMutability': 'nonpayable', 'type': 'function'}] contractAddress = '0x9DBF7256f54Eefe99Aa1f9436921F0F0e13147Ff' userInfo = ins.w3.eth.contract(address=contractAddress, abi=abi) user = userInfo.functions.getAttr().call() print(user) try: ins.minerStart() uName = 'jerry' uAge = 20 uGender = True txHash = userInfo.functions.setAttr(uName, uAge, uGender).transact() print("txHash:", txHash) txReceipt = ins.w3.eth.waitForTransactionReceipt(txHash) print("******************************************") print('txReceipt:', txReceipt) user1 = userInfo.functions.getAttr().call() print('after: ', user1) except Exception: print(Exception) finally: ins.minerStop()
11. 查询区块中存储的信息
这里指调用智能合约,并改变合约状态后,存储到区块中合约内的信息。
打印信息时,如区块地址为类型为:Hexbytes 类型的,我们需要的是字符串类型的一串16进制字符。
参考:https://web3py.readthedocs.io/en/latest/contracts.html#web3.contract.ContractFunction.call
block.hash.hex() # 转换输出字符串地址
def searchContract(ins): abi = [{'inputs': [], 'name': 'getAttr', 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}, {'internalType': 'string', 'name': '', 'type': 'string'}, {'internalType': 'string', 'name': '', 'type': 'string'}], 'stateMutability': 'view', 'type': 'function'}, {'inputs': [{'internalType': 'string', 'name': '_number', 'type': 'string'}, {'internalType': 'string', 'name': '_batch', 'type': 'string'}, {'internalType': 'string', 'name': '_createTime', 'type': 'string'}], 'name': 'setAttr', 'outputs': [], 'stateMutability': 'nonpayable', 'type': 'function'}] contractAddress = '0xb27a8caeAeE69B17d377a889246DA5112c9e14b8' userInfo = ins.w3.eth.contract(address=contractAddress, abi=abi) print("****************区块 Hash 值查询******************") blockHash = '0x627b561fe9d60ec6e6b392a4361340ed009df2c37497d4a343e172c96da1552d' info = userInfo.functions.getAttr().call(block_identifier=blockHash) print(info)
原创不易,尊重版权。转载请注明出处:http://www.cnblogs.com/xsmile/