Web3js
事件未在 web3js 中擷取
我有以下(非常簡單的)預言機合約。我想要它做的就是管理由開源 API 返回的鏈上的數據——我將在另一個合約中使用這些數據。我可以使用 web3js 毫無問題地呼叫契約的方法,但我無法監聽套接字上的事件。我應該看到
console.log('Event firing ', event)
輸出的東西,但我沒有。如果有幫助,我會在本地執行 ganache 和 truffle 來託管契約當我到達
http://localhost:3000/api/oracle
端點時,我得到以下內容(輸出下方的原始碼)。有人可以幫我理解為什麼我沒有正確捕捉事件嗎?[0] 9:36:44 AM - Found 0 errors. Watching for file changes. [1] Running on 3000 ⚡ [1] Endpoint called [1] Contract response Done
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; contract SnapshotOracle { // Contract owner address public owner; string[] public voters; // Callback function event CallbackGetVotes(address owner); constructor() { owner = msg.sender; } // This is called first, which emits an event // that fetches new data function updateVotes() public returns (string memory) { emit CallbackGetVotes(owner); return "Done"; } // Once the data is fatched by the service, // setVotes is called to set that data function setVotes(string[] memory _voters) public { require(msg.sender == owner); voters = _voters; } // Finally, getVotes is called to get the new data function getVotes() public view returns (string[] memory) { return voters; } }
// Simple Node oracle service to interact with oracle contract import express, { Express, Request, Response } from 'express'; import bodyParser from 'body-parser'; import helmet from 'helmet'; import dotenv from 'dotenv'; import Web3 from 'web3' import OracleContract from './contracts/SnapshotOracle.json' import { AbiItem } from 'web3-utils' dotenv.config(); const PORT = process.env.PORT || 3000; const app: Express = express(); app.use(helmet()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); // Web socket to contract const CHAIN_PORT = '7545' const ORACLE_ADDR = '0x05dbB4b1C895C593b66686b5234D3cD80D18E460' const web3 = new Web3(`ws://127.0.0.1:${CHAIN_PORT}`) const oracleContract = new web3.eth.Contract(OracleContract.abi as AbiItem[], ORACLE_ADDR) web3.eth.getAccounts((err, accounts) => { const a = oracleContract.events.CallbackGetVotes({owner: accounts[0]}) .on('data', (event: any) => { console.log('Event firing ', event) // TODO: Run API Request // TODO: Save result of API request to contract state }) }) app.get('/api/oracle', (req: Request, res: Response) => { const web3 = new Web3(`http://127.0.0.1:${CHAIN_PORT}`) const oracleContract = new web3.eth.Contract(OracleContract.abi as AbiItem[], ORACLE_ADDR) console.log('Endpoint called') web3.eth.getAccounts(async (err, accounts) => { const t = await oracleContract.methods.updateVotes().call({owner: accounts[0]}) console.log('Contract response', t) setTimeout(async () => { const votes = await oracleContract.methods.getVotes().call() res.send(votes) }, 3000) }) }); app.listen(PORT, () => console.log(`Running on ${PORT} ⚡`));
問題是您沒有創建事務
oracleContract.methods.updateVotes().call()
,而是呼叫 updateVotes 作為視圖函式。您必須改用 .send 。const t = await oracleContract.methods.updateVotes().send({owner: accounts[0]}) console.log("Transaction receipt: ", t)