First off, my setup.
System: ArchLinux
Ganache: v2.0.0 (correction, v1.3.1)
Solidity: 0.5.8
web3: 1.0.0-beta.37 (anything higher than 37, contract wont deploy)
Node: 'latest'
Some background and context info
I have a simple smart contract as shown below:
pragma solidity ^0.5.7;
contract CommerceChain {
// ------------------------------------------------------
// generic object events
event onNewCategory(uint productId);
// ------------------------------------------------------
// Blockchain variables
address owner;
mapping (uint => Category) categoryMapping;
uint[] categoryIndex;
struct Category {
uint id;
uint name;
uint description;
}
// ------------------------------------------------------
// Function modifier
modifier isOwner(){
require(msg.sender == owner, "You are not the owner");
_;
}
modifier notExistsCategory(uint id) {
require(categoryMapping[id].id != id, "Category already exists");
_;
}
// ------------------------------------------------------
// Default methods
constructor() public payable {
owner = msg.sender;
}
function() external payable {
}
function addCategory(uint id, uint _name, uint _description) public isOwner notExistsCategory(id) {
categoryMapping[id] = Category(id, _name, _description);
categoryIndex.push(id);
emit onNewCategory(id);
}
}
this is part of a larger contract
1. To start off, I get the contract instance by:
const Web3 = require('web3);
const web3 = new Web3(new Web3.providers.WebsocketProvider(_config.provider.url));
//assuming the contract already exists
let contract = new web3.eth.Contract(abi, address, {
data: '0x' + byteCode,
gas: gasLimit,
gasPrice: gasPrice
});
2. then I subscribe to the contract event by:
(I have up till not tested 3 ways of subscribing to the event)
Method 1 from eth event
contract.events.onNewCategory({
fromBlock: 0
},(error, event) => {
if (error) {
console.log(error);
}
if (event) {
console.log(event);
}
}).on('data', (event) => {
console.log(event); // same results as the optional callback above
}).on('changed', (event) => {
console.log(event);
}).on('error', (error) => {
console.error(error);
});
Method 2 from all events
contract.events.allEvents({
fromBlock: 0
}, (error, event) => {
if (error) {
console.error(error);
}
if (event) {
console.log(event);
}
});
Method 3 from eth subscriptions
const web3 = _web3Helper.getWeb3Instance();
let eventName = eventType.toString();
const eventJsonInterface = web3.utils._.find(contract._jsonInterface, o => o.name === eventName && o.type === 'event');
subscribedEvents[eventName] = web3.eth.subscribe('logs', {
address: config.wallet.address
}, (error, result) => {
if (!error) {
const eventObj = web3.eth.abi.decodeLog(eventJsonInterface.inputs, result.data, result.topics.slice(1));
callback(eventObj);
}
}).on("data", (log) => {
console.log(log);
}).on("changed", (log) => {
console.log(log);
});
3. then I call:
contract.methods.addCategory(1, 2, 3).send({from: walletAddress}, callback)
to add a category to the contract.
Problem:
TL;DR
function addCategory(uint id, uint name, uint description);
event onNewCategory(uint id);
I can see the transaction is processed, in remix.ethereum.org and when testing with localhost Ganache RPC, and I do get a transaction receipt.
However, the event for the transaction never fires, ever! No error gets thrown from event callbacks.
Why does my event never fire?
Update
I tested with npm web3 versions. Please note that for each transaction/send call, (and where it is available), I implement all event handlers, calls and promises excluding the callback as a parameter. Reason being, when this is implemented, further calls to .on()
are never triggered.
Thus I will have a format like:
contract.deploy({
data: '0x' + byteCode
}).send({
from: fromAddress
}).on('error', (error) => {
if (error) {
console.error(error)
}
}).on('transactionHash', (transactionHash) => {
if (transactionHash) {
console.log("Contract deployment completed [" + transactionHash + "]")
}
}).on('receipt', (receipt) => {
if (receipt) {
console.log(receipt);
}
}).on('confirmation', (confirmationNumber, receipt) => {
if (confirmationNumber) {
console.log(confirmationNumber);
}
if (receipt) {
console.log(receipt);
}
}).then(_newContract => {
if (_newContract) {
callback(_newContract);
}
}, reason => {
if (reason) {
console.error(reason);
}
});
- 1.0.0-beta.37
The output for the above function is Contract deployment completed [...]
including the transactionReceipt
. Ganache reflects the transaction.
All callbacks, events are triggered as expected.
- 1.0.0-beta.54
The output for the above function is Contract deployment completed [...]
. No further output is recieved.
However, Ganache reflects the transaction (or contract creation):
[11:18:32 PM] eth_sendTransaction
[11:18:32 PM] Transaction: 0x5bdcb28761e82dec84cec1b11faae8baef9a7595a4b537fd5a333de396c56ec5
[11:18:32 PM] Gas usage: 21000
[11:18:32 PM] Block Number: 1
[11:18:32 PM] Block Time: Tue May 07 2019 23:18:32 GMT+0200 (South Africa Standard Time)
and also performing a transaction between 2 wallets, either an error or transaction hash is caught, no other even fires.
Maybe 54 is broken? I experienced the same issues with 50 - 53 where transationHash
es or error
s are received, and events do not fire.