以太坊 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/