Ethereum 从前端订阅Solidity事件

Ethereum 从前端订阅Solidity事件,ethereum,Ethereum,我正在尝试从前端订阅Solidty中定义的PurchaseMade事件。我没有得到预期的结果,我做错了什么需要帮助 环境: export const getContractInstance = () => { let web3Provider if (typeof window.web3 !== 'undefined') { // if metamask is on, web3 is injected... web3Provider = web3.

我正在尝试从前端订阅Solidty中定义的
PurchaseMade
事件。我没有得到预期的结果,我做错了什么需要帮助

环境

export const getContractInstance = () => {
    let web3Provider

    if (typeof window.web3 !== 'undefined') {
        // if metamask is on, web3 is injected...
    web3Provider = web3.currentProvider
    } else {
        // otherwise, use ganache-cli...
    web3Provider = new Web3.providers.HttpProvider('http://localhost:8545')
    }

    web3 = new Web3(web3Provider)

    return new web3.eth.Contract(CryptoKpopAbi, CONTRACT_ADDRESS)
}
  • 甘纳切,松露
  • web3.js,React.js
初始化合同实例

export const getContractInstance = () => {
    let web3Provider

    if (typeof window.web3 !== 'undefined') {
        // if metamask is on, web3 is injected...
    web3Provider = web3.currentProvider
    } else {
        // otherwise, use ganache-cli...
    web3Provider = new Web3.providers.HttpProvider('http://localhost:8545')
    }

    web3 = new Web3(web3Provider)

    return new web3.eth.Contract(CryptoKpopAbi, CONTRACT_ADDRESS)
}
订阅PurchaseMake活动

onBuy = (obj) => {
    web3.eth.subscribe("PurchaseMade", {}, () => {
        debugger
    });

    this.ContractInstance.methods.buy(1).send({
        from: this.state.currentUserAddress,
        gas: GAS_LIMIT,
        value: web3.utils.toWei(price.toString(), "ether"),
    }).then((receipt) => {
        console.log(receipt)
    }).catch((err) => {
        console.log(err.message)
    })
}
我在调用
web3.eth.subscribe

Subscription "PurchaseMade" doesn't exist. Subscribing anyway.
我在发送接收时收到此错误(在发送()成功后)

Uncaught TypeError: Cannot read property 'subscriptionName' of undefined
我使用此官方文档设置订阅

提前谢谢你

更新:

Subscription "PurchaseMade" doesn't exist. Subscribing anyway.
合同中的事件声明

event PurchaseMade(uint objId, uint oldPrice, uint newPrice, string objName, address prevOwner, address newOwner);
function buy(uint _tokenId) payable public {
  address prevOwner = ownerOf(_tokenId);
  uint currentPrice = tokenIdToPrice[_tokenId];

  ...

  PurchaseMade(_tokenId, currentPrice, newPrice,
    tokens[_tokenId].name, prevOwner, msg.sender);
}
事件调用合同

event PurchaseMade(uint objId, uint oldPrice, uint newPrice, string objName, address prevOwner, address newOwner);
function buy(uint _tokenId) payable public {
  address prevOwner = ownerOf(_tokenId);
  uint currentPrice = tokenIdToPrice[_tokenId];

  ...

  PurchaseMade(_tokenId, currentPrice, newPrice,
    tokens[_tokenId].name, prevOwner, msg.sender);
}

您正在尝试订阅事件本身。API允许您订阅事件类型并添加筛选器。有效的事件类型包括:

  • pendingTransactions:接收发送到区块链的新交易子集(主要用于希望对其处理的交易进行选择的矿工)
  • newBlockHeaders:在向区块链添加新区块时接收通知
  • 同步:节点同步开始/停止时接收通知
  • 日志:接收区块链上日志更新的通知。这些是您感兴趣的事件
有关如何使用
订阅(“日志”)
的示例,请参阅

subscribe
API通常用于监听区块链上发生的事件。监听特定合约事件的更简单方法是对部署的合约使用
events
()。它与上面使用的
订阅
没有太大区别,但它已经有了合同地址和主题过滤器

this.ContractInstance.events.PurchaseMade({}, (error, data) => {
  if (error)
    console.log("Error: " + error);
  else 
    console.log("Log data: " + data);
});
不过有一个重要的注意事项,在web3 1.0中,您必须使用WebSocket或IPC

编辑-我忘了提到您还可以从交易凭证中获取事件:

contractInstance.events.eventName.returnValues;

您可以添加合同本身吗?或者至少显示PurchaseMake Event的声明谢谢!这非常有用。最后一个重要提示有点令人惊讶。这是否意味着如果我想订阅事件,我不能使用Metamask作为提供商?其他人是如何做的?有可能有两个提供商吗(一个websocket提供程序仅用于订阅事件,元掩码用于函数调用)?是的,Infura支持WS-connections()。是的,我将使用两个
web3
实例,一个用于订阅,一个用于HTTP。我不确定WS限制是否是永久性的(记住,web3 1.0仍然是beta版)…希望不会。谢谢你。我还发布了另一个问题,我想你可以对此有所启发;)