イーサリアム: Web3 を介したスマート コントラクト インタラクション
1. 環境の準備
1.1 関連する依存関係をインストールする
pip3をインストールする
sudo apt install python3-pip -y
pip3 を使用して web3 python パッケージをインストールします
pip3 install web3
ipython3 をインストールする
sudo apt install ipython3 -y
1.2 ガナッシュのインストール
ガナッシュをダウンロード
次のコマンドを入力してガナッシュを実行します (./ 以降の内容はバージョンによって異なります)。
./ganache-2.5.4-linux-x86_64.AppImage &
1.3 テスト
Python インタラクティブ環境に入る
ipython3
次のコードを入力して接続をテストします
from web3 import Web3
w3 = Web3(Web3.HTTPProvider("http://localhost:7545"))
w3.isConnected()
2. 新しい学生契約を作成する
2.1 契約情報の設定
contracts
新しいフォルダーを作成しStudent.sol
、次の内容を入力します。
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.16 <0.9.0;
contract Student{
string name;
constructor() {
// name = _name;
name = "Tom";
}
function getName() public view returns (string memory) {
return name;
}
}
2.2 web3 スクリプトの作成
2.2.1 新しい Student.py ファイルを作成する
インポートライブラリ
from web3 import Web3
import os
import sys
import getopt
import uuid
いくつかのグローバル変数を宣言する
url = "http://localhost:7545" # 以太坊测试链 rpc 连接端口
contract_address_file = 'contract_student.txt' # 合约地址保存文件
abi_file = "Student/Student.abi" # abi 文件
bytecode_file = "Student/Student.bin" # 字节码文件
account_id = 0 # 默认账户
テストチェーンを接続する
# 连接测试链
w3 = Web3(Web3.HTTPProvider(url))
eth = w3.eth
print("eth connect:", w3.isConnected())
デフォルトのアカウントを設定する
def set_default_account():
"""
设置调用合约、发送交易的账户
"""
global account_id
eth.defaultAccount = eth.accounts[account_id]
abiとバイトコードを取得する
def get_abi_from_file(file):
"""
从文件中获取abi
"""
with open(file, 'r') as f:
return f.read()
def get_bytecode_from_file(file):
"""
从文件中获取字节码
"""
with open(file, 'r') as f:
return "0x" + f.read()
コントラクトをデプロイし、コントラクト アドレスを取得する
def deploy_contract(abi, bytecode):
"""
部署合约
"""
contract = eth.contract(abi=abi, bytecode=bytecode) # 创建合约
tx_hash = contract.constructor().transact() # 部署合约(发送构造函数的交易,需相对应合约中的参数)
tx_receipt = eth.waitForTransactionReceipt(tx_hash) # 等待交易回执
print("contract address:", tx_receipt.contractAddress) # 合约地址
# 保存合约
global contract_address_file
with open(contract_address_file, "w") as f:
f.write(tx_receipt.contractAddress)
# 通过地址获取已部署合约
deployed_contract = eth.contract(address=tx_receipt.contractAddress, abi=abi)
return deployed_contract
def get_deployed_contract(abi, bytecode):
"""
获取部署合约,如果本地已保存合约地址,则调用该地址的合约,否则重新创建一个新的合约
"""
try:
# 尝试获取已有合约
with open(contract_address_file, "r") as f:
contract_address = f.read()
print("contract address:", contract_address)
deployed_contract = eth.contract(address=contract_address, abi=abi)
return deployed_contract
except IOError:
# 获取已有合约失败则重新部署新合约
return deploy_contract(abi, bytecode)
主な方法
if __name__ == '__main__':
set_default_account()
abi = get_abi_from_file(abi_file)
bytecode = get_bytecode_from_file(bytecode_file)
deployed_contract = get_deployed_contract(abi, bytecode)
print(deployed_contract.functions.getName().call())
2.2.2 コントラクトをコンパイルして実行する
コンパイルする
solc --abi --bin --overwrite -o Student Student.sol
走る
python3 Student.py