從 web3.py 執行合約函式
我在 Ropsten 上部署了一個合約,這個合約有一個函式名 testFunc(),我想從 python 腳本執行 testFunc()。
這就是我從 python 連接到契約的方式:
from web3 import Web3 def connect_to_contract(self): try: self.web3 = Web3( Web3.HTTPProvider( "https://" + self.network + ".infura.io/v3/" + os.getenv("WEB3_INFURA_PROJECT_ID"))) self.contract = self.web3.eth.contract( address=self.contract_address, abi=self.contract_abi) except Exception as e: raise e
然後,這就是我第一次嘗試執行合約功能但沒有發生任何事情的方式:
self.contract.functions.testFunc().call()
我已經閱讀了我必須簽署交易以使其正常工作的不同主題。這就是我想要知道的方式:
txn = self.contract.functions.testFunc().buildTransaction({ 'gas': 70000, 'gasPrice': self.web3.toWei('1', 'gwei'), 'from': self.contract_address, 'nonce': nonce }) private_key = "xxxxxxxxxx" signed_txn = self.web3.eth.account.signTransaction(txn, private_key=private_key) self.web3.eth.sendRawTransaction(signed_txn.rawTransaction)
但這也不起作用,我收到錯誤消息:
TypeError: from field must match key’s 0x25c77Axxxxxxxxxxxxxxxxxxxxxxxx, but it was 0x7d8e0ea7axxxxxxxxxxxxxxxxxxxxxx
這裡提到的 0x25c77Axxxxxxxxxxxxxxxxxxxxxxxxxxx 地址是我用來部署合約的公鑰,第二個 0x7d8e0ea7axxxxxxxxxxxxxxxxxxxxxx 是具有 testFunc() 函式的合約。
所以我的問題是,如何從 python 腳本委託呼叫,或者如何獲取已部署合約的私鑰?我應該怎麼做 ?
Chainstack的開發倡導者在這裡!
當你用於
web3.py
與智能合約互動時,可以將腳本分為三部分:
- 連接到網路。
- 初始化智能合約和賬戶以簽署交易。
- 呼叫函式和事務。
連接到網路
我總是使用這種語法將我的腳本連接到網路,您也可以使用環境變數,但對於測試腳本,我通常保持簡單。
from web3 import Web3 # Initialize endpoint URL node_url = "CHAINSTACK_NODE_URL" # Create the node connection web3 = Web3(Web3.HTTPProvider(node_url))
我通常添加一個 if 語句來在控制台上給出一條消息,以驗證連接是否成功(非必需但對使用者來說非常好)。
# Verify if the connection is successful if web3.isConnected(): print("-" * 50) print("Connection Successful") print("-" * 50) else: print("Connection Failed")
初始化智能合約和賬戶
要從智能合約呼叫函式,我們需要先指定其地址和 ABI。
# Initialize the address calling the functions/signing transactions caller = "YOUR_ADDRESS" private_key = "PRIVATE_KEY" # To sign the transaction # Initialize address nonce nonce = web3.eth.getTransactionCount(caller) # Initialize contract ABI and address abi = '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"balanceLeft","type":"uint256"}],"name":"balance","type":"event"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"}],"name":"destroy","outputs":[],"stateMutability":"nonpayable","type":"function"}' contract_address = "CONTRACT_ADDRESS" # Create smart contract instance contract = web3.eth.contract(address=contract_address, abi=abi)
呼叫函式和事務
現在我們可以開始呼叫函式了;我們可以通過兩種方式做到這一點:
.call
如果該函式僅從區塊鏈中讀取(如果它是一個view
或pure
函式)- 建構一個事務來呼叫一個修改網路狀態的函式。
我注意到在您的程式碼中,您使用合約地址來呼叫該函式,而不是從您的帳戶中呼叫它。
# initialize the chain id, we need it to build the transaction for replay protection Chain_id = web3.eth.chain_id # Call your function call_function = contract.functions.testFunc().buildTransaction({"chainId": Chain_id, "from": caller, "nonce": nonce}) # Sign transaction signed_tx = web3.eth.account.sign_transaction(call_function, private_key=private_key) # Send transaction send_tx = web3.eth.send_raw_transaction(signed_tx.rawTransaction) # Wait for transaction receipt tx_receipt = web3.eth.wait_for_transaction_receipt(send_tx) # print(tx_receipt) # Optional
然後,如果你想呼叫一個只從網路(
view
或pure
)讀取的函式,你只需要“呼叫”它,因為它不會進行實際交易。例如
totalSupply()
來自 ERC20 代幣合約的函式。totalSupply = contract.functions.totalSupply().call() # read the coin total supply - call means we are reading from the blockchain print(totalSupply)
您可以查看Chainstack 文件上的Node API 參考頁面
web3.py
以查看更多程式碼範例!我希望這可以幫助你!