Web3js

事件未在 web3js 中擷取

  • December 29, 2021

我有以下(非常簡單的)預言機合約。我想要它做的就是管理由開源 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)

引用自:https://ethereum.stackexchange.com/questions/117398