以太坊 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 文件(放在同级目录)

以太坊入门三 Web3j.py 与节点交互

from web3 import Web3
from solc import compile_standard

personal.unlockAccount(ins.getAddrs()[2], 'sophia', 300) # 参数分别为 账户地址、私匙、解锁时间(秒)
以太坊入门三 Web3j.py 与节点交互
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
合约部署

相关文章: