-
Notifications
You must be signed in to change notification settings - Fork 66
Getting Smart Contract Events
A script that returns some filtered events from an Ethereum smart contract. Your contract will have a solidity event and it will need to be triggered at least once before you run the script.
Note: Use at your own risk.
For this example we're going to use the script located here.
var Web3 = require('web3');
web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/YOUR-API-TOKEN-HERE'));
Please read the Basic Required Setup page for this first bit, you'll see it a lot.
HOWEVER! Because we are going to use a Ropsten testnet smart contract (so you can actually play with the one I set up without paying transaction fees with real ether), the code above changes to look like this:
var Web3 = require('web3');
web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/YOUR-API-TOKEN-HERE'));
Not very different, but it does make a world of difference.
You will need a smart contract for this and one with some events pre-triggered. Thankfully, I have taken care of that for you. Here is the contract for the events we will be searching, it is on the Ropsten Testnet and you can find it at this address "0x38979119752B1891ae9B5cD6986285eA3190AE38" on Etherscan.io or another Ropsten Ethereum blockchain explorer.
pragma solidity ^0.4.17;
contract TestEvent {
// A statement we can modify.
bytes32 greeting;
// An event to trigger with values to index, an address and a string.
event Event1(address indexed _from, bytes32 indexed _greeting);
// Function that triggers the event.
function greet(bytes32 _msg) public {
greeting = _msg; // Set the greeting to a new message.
Event1(msg.sender, _msg); // Put the address and string into the event.
}
// Get the last greeting.
function getgreeting() constant public returns(bytes32) {
return greeting;
}
}
Basically, what we have here is a function that triggers an event. The event is composed of an address of the sender and a message that was defined when they sent the transaction; and that's about it. Don't worry about creating some events via the contract... I mean you can if you want to, but I've already put a few in there to test with.
The way we're going to pull events out of the contract is by searching for events triggered by an address. Each event saves the address and the message that was passed along with it. The first part of the code is where we specify that address, and we log it in the console for reference.
var addr = "ADDRESS-HERE";
console.log('Events by Address: ' + addr);
Next we have to define some of the smart contracts parameters by providing the ABI (Application Binary Interface), as well as the address where the contract is located.
// Define the contract ABI
var abi = [{"constant":true,"inputs":[],"name":"getgreeting","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_msg","type":"bytes32"}],"name":"greet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_greeting","type":"bytes32"}],"name":"Event1","type":"event"}]
// Define the contract ABI and Address
var contract = new web3.eth.Contract(abi, '0x38979119752B1891ae9B5cD6986285eA3190AE38');
My script also contains some console text that separates the results from the address that was logged before it. You can ignore this, its just for show.
Now we get into the fun part, searching for these events.
contract.getPastEvents('Event1', {
filter: {_from: addr},
fromBlock: 0,
toBlock: 'latest'
}, function(error, events){
for (i=0; i<events.length; i++) {
var eventObj = events[i];
console.log('Address: ' + eventObj.returnValues._from);
console.log('Greeting: ' + web3.utils.hexToAscii(eventObj.returnValues._greeting));
}
});
All we're doing here is first using the previously defined contract information (ABI, Address) and using it to get the past events. The filter:
makes sure we only get results that are from our previously defined address and fromBlock
and toBlock
ensures that we search the entire blockchain for these events.
Then we just clean up the results of this query to bring back only the address eventObj.returnValues._from
and the message, or greeting that was sent along with it, eventObj.returnValues._greeting
. However there is a small glitch in the matrix here.
For some reason I couldn't get strings to be returned, I'm not sure if that was a limitation of Infura's API or Geth, but the solution was to make the messages into bytes32 strings. The downside is we have to convert that back to human readable text so that is why the returned data is passed into web3.utils.hexToAscii
, as that converts it into text.
Before you try running the script, put this address as the addr value "0x78655b43b6998146127f78ffa94bc5696152d28a". And if all went according to plan you should see something like this in the terminal:
Events by Address: 0x78655b43b6998146127f78ffa94bc5696152d28a
-----------------------------------
Matching Smart Contract Events
-----------------------------------
Address: 0x78655B43B6998146127f78FFA94BC5696152D28A
Greeting: Oh Hai Mark
Cool right!?
Try writing your own message into the contract (you'll need Ropsten Ether to transact), and then search for it! You can also try narrowing down the results by adding block numbers to search between or if you're feeling really lucky try making and address array to search for as well!