Как просмотреть журналы событий для контракта ethereum?

После чтения этого сообщения , похоже, я должен иметь доступ к журналам событий, которые были вызваны контрактом Ethereum. Раздел, который меня интересует, - это вариант 3, который использует журналы событий как более дешевую форму хранения.

Этот обмен стеками вопрос подчеркивает отличный способ сделать это.

Важная часть:

var filter = web3.eth.filter({
    'fromBlock': 0,
    'toBlock': 'latest',
    'address': contractAddress,
    'topics':[
        web3.sha3('newtest(string,uint256,string,string,uint256)')
    ]
});

filter.watch(function(error, result) {
   ...
})

Однако данные, которые я возвращаю, не являются массивом журналов в структуре моего события, которое я ожидал.

Удар - основной контракт, в котором я беру продукт и перемещаю его между адресами. Когда я это делаю, я создаю событие, чтобы выделить, кто его отправил, и кто взял на себя владение, а также количество. Это должно дать мне богатую историю каждого адреса, который принадлежал продукту и количествам при каждой транзакции.

Contract:

contract Product{
  address public owner;
  string public title;
  mapping (address => uint) quantity;

  event Transferred(address from, address to, uint quantity);

  // Constructor
  function Product(string _title, uint _quantity){
    owner = msg.sender;
    title = _title;
    quantity[msg.sender] = _quantity;
  }

  function getQuantity(address _user) constant returns (uint _quantity){
    return quantity[_user];
  }

  function changeQuantity(uint _quantity) returns (bool success){
    quantity[msg.sender] = _quantity;
    return true;
  }

  function transfer(address _to, uint _quantity) returns (bool success){
    if (quantity[msg.sender] < _quantity){
      return false;
    }

    owner = _to;
    quantity[msg.sender] -= _quantity;
    quantity[_to] += _quantity;
    Transferred(msg.sender, _to, _quantity);
    return true;
  }
}

Давайте начнем взаимодействовать с этим плохим мальчиком в консоли Truffle. Сначала давайте сделаем объекты нашей учетной записи.

var account1 = web3.eth.accounts[0]
var account2 = web3.eth.accounts[1]

Теперь разрешите доступ к развернутому контракту.

var product;
Product.deployed().then(function(i){ product = i });

Теперь давайте убедимся, что у учетной записи 1 есть 0 любого продукта, это

product.getQuantity(account1).then(function(ci){console.log(ci)})
// >>> { [String: '0'] s: 1, e: 0, c: [ 0 ] }

Сладкое. Давайте дадим ему 10 как количество.

product.changeQuantity(10).then(function(ci){console.log(ci)})
product.getQuantity(account1).then(function(ci){console.log(ci)})

// >>> { [String: '10'] s: 1, e: 1, c: [ 10 ] }

Теперь мы готовим! Давайте дадим один виджет учетной записи2. Это вызовет событие Transferred и, надеюсь, создаст журнал, который я смогу увидеть навсегда.

product.transfer(account2, 1).then(function(ci){console.log(ci)})
product.getQuantity(account2).then(function(ci){console.log(ci)})
// >>> { [String: '1'] s: 1, e: 0, c: [ 1 ] }

Awesome! Теперь давайте проверять эти журналы! Замените the_contract_address на адрес контракта String.

var filter = web3.eth.filter({
    fromBlock:0,
    toBlock: 'latest',
    address: ’the_contract_address',
    'topics':[
        web3.sha3('Transferred(address,address,uint)')
    ]
});

Печать объекта фильтра даст вам:

Filter {
  requestManager:
   RequestManager {
     provider: HttpProvider { host: 'http://localhost:8545', timeout: 0 },
     polls: {},
     timeout: null },
  options:
   { topics: [ '0x6f8b0853f4c56c6a9faec2151763bdc803a695c1ce09b45d3036186c5ae14c47' ],
     from: undefined,
     to: undefined,
     address: '0x570a704dded5379eb21b064cc7750741348e8860',
     fromBlock: '0x0',
     toBlock: 'latest' },
  implementation:
   { newFilter: { [Function: send] request: [Function: bound ], call: [Function: newFilterCall] },
     uninstallFilter: { [Function: send] request: [Function: bound ], call: 'eth_uninstallFilter' },
     getLogs: { [Function: send] request: [Function: bound ], call: 'eth_getFilterLogs' },
     poll: { [Function: send] request: [Function: bound ], call: 'eth_getFilterChanges' } },
  filterId: '0x0b',
  callbacks: [],
  getLogsCallbacks: [],
  pollFilters: [],
  formatter: [Function: outputLogFormatter]
}

Отсюда я не знаю, как получить данные журнала, которые я ищу. Даже вызов искусно названной функции eth_getFilterLogs возвращает []. Мне нужен способ увидеть красивый список журналов, который растет с течением времени с каждой транзакцией.

Любая помощь будет принята с благодарностью!

Edit:

var myEvent = product.Transferred({fromBlock: 0, toBlock: 'latest'});
myEvent.watch(function(error, result){console.log(result)});

Вышеупомянутое успешно дает мне последний журнал событий. Однако, похоже, это только возвращает. Например, выполнение:

product.transfer(account2, 3).then(function(ci){console.log(ci)})
product.transfer(account2, 2).then(function(ci){console.log(ci)})

дает только результаты второй транзакции.

{ logIndex: 0,
  transactionIndex: 0,
  transactionHash: '0xe2e44b73d67147fb9988dce58d7616da759660a7fde99b3068c6b92fdb9ad8d3',
  blockHash: '0x3a28c6909d44f380a2c64601ecbc3523551ed3840f3afd2549d72d0b710fbb2d',
  blockNumber: 38,
  address: '0x97c553ef6d28b88e19f47735c35369d71f891d76',
  type: 'mined',
  event: 'Transferred',
  args:
   { from: '0x00bd67f06685ad070579b95c2e19ec0022fc916e',
     to: '0x90144809cf261f271e9b7fd3d6d1d0b51d8426c2',
     quantity: {
       [String: '2'] s: 1, e: 0, c: [Object]
     }
   }
}

Как я могу получить оба (все) из них?

17 голосов | спросил user1911077 18 Maypm17 2017, 22:09:57

3 ответа


16

Чтобы получить журналы событий прошлого , вы можете создать экземпляр события с диапазоном диапазона и использовать функцию myEvent.get для извлечения событий.

В вашем примере мы могли бы сделать что-то минимальное:

let transferEvent = product.Transferred({}, {fromBlock: 0, toBlock: 'latest'})
transferEvent.get((error, logs) => {
  // we have the logs, now print them
  logs.forEach(log => console.log(log.args))
})

Примечание. . Первый аргумент {} может использоваться как фильтр , чтобы улавливать определенные события.

Выше кода записывает это в консоль:

{ from: '0xc7d748654199d3594239a244d806e51331ca14b5',                    
  to: '0x3c11b23b4d5adb2d534d262cf83cee773c9b1c0a',                                            
  quantity: { [String: '1'] s: 1, e: 0, c: [ 1 ] } }                                           
{ from: '0xc7d748654199d3594239a244d806e51331ca14b5',                                          
  to: '0x3c11b23b4d5adb2d534d262cf83cee773c9b1c0a',                                            
  quantity: { [String: '3'] s: 1, e: 0, c: [ 3 ] } }                                           

Как насчет событий all контракта?

Здесь экземпляр события будет выглядеть так (обратите внимание, что здесь мы используем только один параметр):

let events = product.allEvents({fromBlock: 0, toBlock: 'latest'})

И затем продолжайте, как и прежде, с помощью events.get().

event.get () vs event.watch ()

event.watch() используется для обработки новых событий, которые соответствуют фильтру, по мере их потока («просмотр» цепочки).

event.get() предназначен для захвата существующих событий, которые соответствуют некоторому фильтру.

Источники:

ответил Travis Jacobs 23 J000000Sunday17 2017, 21:50:28
2

Для тех, кто использует Web3 ^ 1.0.0, просмотр событий контракта несколько изменился.

Чтобы просмотреть события контракта из прошлого, теперь мы используем (из

ответил Zack McGinnis 11 PMpWed, 11 Apr 2018 21:56:57 +030056Wednesday 2018, 21:56:57
0

В качестве альтернативы вы можете заключить свой контракт в truffle-contract абстракция - если вы вызываете контрактные функции в форме js таким образом, вы возвращаете объект tx с включенными журналами. Посмотрите, как я это сделал: https://github.com/aleybovich/smart-contract-executor/blob/master/src/js/components/FuncForm.js

Или просто поместите:

Добавьте модуль:

const truffleContract = require("truffle-contract");

Создайте экземпляр абзаца контракта:

const contract = truffleContract({abi});
contract.setProvider(web3.currentProvider);
contract.defaults({ from: fromAddress});

Отправьте транзакцию:

contract.at(this.props.contractAddress)
    .then(instance => {
        return instance[funcName](...args);
    })
    .then(tx => {
        if (tx.logs.length) {
            ... Process the logs
        }
    })
    .catch(error => {
        console.error(error);
    });
ответил Andrey 8 FebruaryEurope/MoscowbThu, 08 Feb 2018 18:27:36 +0300000000pmThu, 08 Feb 2018 18:27:36 +030018 2018, 18:27:36

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132