не может получить событие?

Моя версия web3 — web3@1.0.0-beta.26, я развертываю контракт на локальном хосте: 8545.

Вот пример моего контракта.

pragma solidity ^0.4.18;
contract LocalEthereum {

    address public owner;
    event Created(bytes32 _tradeHash);
    function createEvent() onlyOwner external {
        Created(0x01);
    } 
}

и вот мой js-код

инициализировать экземпляр контракта

  var Contract = new this.web3.eth.Contract(abi_json,address);

события нажатия кнопки

  Created(account){
      Contract.methods.Created().send({from: account,gas:210000,gasPrice:5000000000})
                      .on('transactionHash', function(hash){
                          console.log('hash',hash);
                      })
                      .on('receipt', function(receipt){
                          console.log('receipt',receipt);
                      })
                      .on('confirmation', function(confirmationNumber, receipt){
                          console.log('confirmation',confirmationNumber);
                      })
                      .on('error', console.error);
  }

смотреть события

  this.Contract.events.Created({},{ fromBlock: 0, toBlock: 'latest' }, function(error, event){ console.log(event); })
                        .on('data', function(event){
                              console.log(event);
                        })
                        .on('changed', function(event){
                             console.log('on changed');
                        })
                        .on('error', console.error);

Приложение js может загрузить контракт и подключиться к сети ethereum, когда я нажму кнопку, Contract сгенерирует «созданный» вызов rpc для ethereum, транзакция может быть получена немедленно. В интерфейсе testrpc я также мог видеть транзакцию, как показано ниже.

  Transaction: 0x2469f2085c8f6f23ad8aa30bc6cf99ade40ea2f0368b9bb008496ba05d927d84
  Gas usage: 21272
  Block Number: 6
  Block Time: Thu Dec 28 2017 20:38:02 GMT+0000 (GMT)

Все работает хорошо, однако вызов события никогда не активируется после вызова метода. В инициализации приложения есть только один вызов события времени, но все же

  this.Contract.events.Created({},{ fromBlock: 0, toBlock: 'latest' }, function(error, event){ console.log(event); })
                        .on('data', function(event){
                              console.log(event);
                        })

консоль выводит ноль.

Интересно, в чем проблема?


интересно, это из-за провайдера web3? в настоящее время я использую веб-http, а не ws. И в настоящее время я тестирую на ganache-cli и testrpc.

this.web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));

http-провайдер не предоставляет событие?

Ответы (3)

На самом деле я обнаружил, что HttpProvider не поддерживает подписку на события в web3.js 1.0.0. Из https://web3js.readthedocs.io/en/1.0/web3.html#value :

Объект — HttpProvider: поставщик HTTP устарел, так как он не будет работать для подписок.

Поэтому мне действительно нужно будет использовать WebsocketProvider (или IpcProvider для локальных узлов).

Вы можете фильтровать события только по параметрам, которые являются частью события, и параметры, которые вы хотите использовать в фильтре, должны быть определены как indexedв определении события контракта. Итак, чтобы ваш код web3.js работал, вам нужно добавить _fromпараметр в определение события, сделать его indexedи установить параметр msg.sender всякий раз, когда вы запускаете событие:

pragma solidity ^0.4.18;
contract LocalEthereum {

    address public owner;
    event Created(adress indexed _from, bytes32 _tradeHash);
    function createEvent() onlyOwner external {
        Created(msg.sender, 0x01);
    } 
}

В событии может быть до трех indexedпараметров.

Однако, глядя на код вашего контракта, только владелец контракта может создать событие Created. Поэтому, если владелец не изменится, фильтрация _fromне будет иметь большого смысла. Так что если вам не нужна эта фильтрация, попробуйте

var event = instance.Created({},{fromBlock:0,toBlock:'latest'});

в вашем коде javascript это должно работать без внесения изменений в ваш контракт.

Спасибо, я знаю, как использовать indexed. но ваш код js все еще не работает. Даже когда я удалил onlyOwner в коде солидности. код js по-прежнему получает все прошлые события и не генерирует событие при выполнении createEvent()
Итак, ваш код js кажется правильным, это хорошо. Вы проверили, правильно ли отправляете События из своего контракта? Вы можете легко сделать это с помощью etherscan.io, посмотреть на одну транзакцию, которая правильно создала событие, и на более позднюю, которая этого не сделала, и сравнить записи на вкладке «Журналы событий».

Это напрямую взято из Web3 Docs . Это должно работать.

var event = myContractInstance.MyEvent({valueA: 23} [, additionalFilterObject])

// watch for changes
event.watch(function(error, result){
  if (!error)
    console.log(result);
});

// Or pass a callback to start watching immediately
var event = myContractInstance.MyEvent([{valueA: 23}] [, additionalFilterObject] , function(error, result){
  if (!error)
    console.log(result);
});

Кроме того, похоже, что это бета-версия. Может быть из-за этого, так как есть некоторые критические изменения.

ПРЕДВАРИТЕЛЬНАЯ ПРОВЕРКА Это предварительная бета-версия с критическими изменениями! Текущая стабильная версия — 0.20.0.

Если вы используете стабильную версию web3, т.е. 0.20.0, и попробуете приведенный выше код, он должен работать.

В качестве альтернативы, если вышеуказанный метод не работает, вы можете использовать метод JSON-RPC eth_getLogs. Ниже приведен пример того, как его использовать:

let request = require('request);
request.post({
                url: <geth_parity_client_IP_with_port>,
                form: JSON.stringify({
                    "jsonrpc":"2.0",
                    "method":"eth_getLogs",
                    "params":[
                        {
                            "topics": ["<get_your_Event_Hex_replace_this_string>"],
                            "address": <contractAddress>,
                            "fromBlock": "0x"+_fromBlock.toString(16),
                            "toBlock": "0x"+_toBlock.toString(16)
                        }
                    ],
                    "id":3 //Network To connect to (test/Main Net)
                }),
                headers: {
                    'Content-Type': 'application/json'
                }
            }, (error, response)=>{
                if(!error && response.statusCode == 200){
                    let result = JSON.parse(response.body).result;
                    console.log(result); //Prints the event details
                }
            });

Дайте мне знать, если вышеизложенное поможет.

ты знаешь как заставить его работать в web3 1.0
Нет. Еще не успел поработать с бета-версией. Но вы пробовали использовать альтернативный подход.