added tests for once with on('data'..)

This commit is contained in:
Fabian Vogelsteller 2016-11-11 16:29:18 +01:00
parent c4c71b9145
commit a3373365d1
No known key found for this signature in database
GPG Key ID: E51EADA77F1A4124
5 changed files with 171 additions and 9 deletions

View File

@ -280,6 +280,9 @@ Parameters
* ``Array`` - **topics** (optional): This allows to manually set the topics for the event filter. If given the filter property and event signature (topic[0]) will not be set automatically.
2. ``Function`` - **callback** (optional): This callback will be fired with an array of event logs as the second argument, or an error as the first argument.
.. _contract-getPastEvents-return:
-------
Returns
-------
@ -331,3 +334,72 @@ Example
------------------------------------------------------------------------------
once
=====================
.. code-block:: javascript
myContract.once(event[, options][, callback])
Subscribes to an event, and unsubscribes immediately after the first event or error.
----------
Parameters
----------
1. ``String`` - **event**: The name of the event in the contract, or ``"allEvents"`` to get all events.
1. ``Object`` - **options** (optional): The options used for deployment.
* ``Object`` - **filter** (optional): Let you filter events by indexed parameters, e.g. ``{filter: {myNumber: [12,13]}}`` means all events where "myNumber" is 12 or 13.
* ``Array`` - **topics** (optional): This allows to manually set the topics for the event filter. If given the filter property and event signature (topic[0]) will not be set automatically.
2. ``Function`` - **callback** (optional): This callback will be fired for each event as the second argument, or an error as the first argument.
-------
Returns
-------
``EventEmitter``: The event emitter has the following events:
- ``"data"`` returns ``Object``: Fires on each incoming event with the event object as argument.
- ``"changed"`` returns ``Object``: Fires on each event which was removed from the blockchain. The event will have the additional property ``"removed: true"``.
- ``error`` returns ``Object``: Fires when an error in the subscription occours.
For the structure of a returned event ``Object`` see :ref:`getPastEvents return values <contract-getPastEvents-return>`.
-------
Example
-------
.. code-block:: javascript
myContract.once('MyEvent', {
filter: {myIndexedParam: [20,23], myOtherIndexedParam: '0x123456789...'}, // Using an array means OR: e.g. 20 or 23
fromBlock: 0
})
.on('data', function(event){
console.log(event)
})
.on('changed', function(event){
// remove event from local database
})
.on('error', console.error);
// console output of the event
> {
returnValues: {
myIndexedParam: 20,
myOtherIndexedParam: '0x123456789...',
myNonIndexParam: 'My String'
},
event: 'MyEvent',
logIndex: 0,
transactionIndex: 0,
transactionHash: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
blockHash: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
blockNumber: 1234,
address: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'
}
------------------------------------------------------------------------------

View File

@ -668,9 +668,13 @@ Contract.prototype.once = function(event, options, callback) {
// get the callback
callback = this._getCallback(args);
// don't allow fromBlock
if(options)
delete options.fromBlock;
return this._on(event, options, function (err, res, sub) {
if(utils.isFunction(callback)){
sub.unsubscribe();
if(utils.isFunction(callback)){
callback(err, res);
}
});

View File

@ -17,8 +17,8 @@
/** @file subscription.js
*
* @authors:
* Fabian Vogelsteller <fabian@ethdev.com>
* @date 2015
* Fabian Vogelsteller <fabian@ethereum.org>
* @date 2016
*/
var utils = require('../utils/utils');
@ -153,10 +153,10 @@ Subscription.prototype._toPayload = function (args) {
* @return {Object}
*/
Subscription.prototype.unsubscribe = function(callback) {
this.removeAllListeners();
clearInterval(this._reconnectIntervalId);
this.options.requestManager.removeSubscription(this.id, callback);
this.id = null;
this.removeAllListeners();
clearInterval(this._reconnectIntervalId);
};
/**
@ -218,8 +218,6 @@ Subscription.prototype.subscribe = function() {
var output = _this._formatOutput(result);
_this.callback(err, output, _this);
if (!err) {
if(output.removed)
_this.emit('changed', output);
@ -243,6 +241,8 @@ Subscription.prototype.subscribe = function() {
_this.emit('error', err);
}
// call the callback, last so that unsubscribe there won't affect the emit above
_this.callback(err, output, _this);
});
} else {
_this.callback(err, null, _this);

View File

@ -17,8 +17,8 @@
/** @file subscriptions.js
*
* @authors:
* Fabian Vogelsteller <fabian@ethdev.com>
* @date 2015
* Fabian Vogelsteller <fabian@ethereum.org>
* @date 2016
*/
var Subscription = require('./subscription.js');

View File

@ -787,6 +787,92 @@ describe('contract', function () {
});
});
it('should create event using the once function and unsubscribe after one log received using the event emitter', function (done) {
var provider = new FakeHttpProvider();
var web3 = new Web3(provider);
var signature = 'Changed(address,uint256,uint256,uint256)';
provider.injectValidation(function (payload) {
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, 'eth_subscribe');
assert.deepEqual(payload.params[1], {
topics: [
'0x' + sha3(signature),
'0x000000000000000000000000'+ address.replace('0x',''),
null
],
address: address
});
});
provider.injectResult('0x321');
provider.injectValidation(function (payload) {
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, 'eth_unsubscribe');
});
provider.injectResult(true);
provider.injectNotification({
method: 'eth_subscription',
params: {
subscription: '0x321',
result: {
address: address,
topics: [
'0x' + sha3(signature),
'0x000000000000000000000000'+ address.replace('0x',''),
'0x0000000000000000000000000000000000000000000000000000000000000001'
],
blockNumber: '0x3',
transactionHash: '0x1234',
blockHash: '0x1345',
logIndex: '0x4',
data: '0x0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000008'
}
}
});
provider.injectNotification({
method: 'eth_subscription',
params: {
subscription: '0x321',
result: {
address: address,
topics: [
'0x' + sha3(signature),
'0x000000000000000000000000'+ address.replace('0x',''),
'0x0000000000000000000000000000000000000000000000000000000000000001'
],
blockNumber: '0x3',
transactionHash: '0x1234',
blockHash: '0x1345',
logIndex: '0x4',
data: '0x0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000008'
}
}
});
var count = 1;
var contract = new web3.eth.contract(abi, address);
var event = contract.once('Changed', {filter: {from: address}})
.on('data', function (result) {
assert.equal(result.returnValues.from, address);
assert.equal(result.returnValues.amount, 1);
assert.equal(result.returnValues.t1, 1);
assert.equal(result.returnValues.t2, 8);
// cant test the below, as emitter events and unsubscribe is called at the same time
// assert.deepEqual(event.options.requestManager.subscriptions, {});
assert.equal(count, 1);
count++;
setTimeout(done, 600);
});
});
it('should create all event filter and receive two logs', function (done) {
var provider = new FakeHttpProvider();