diff --git a/src/contracts/AbstractContract.js b/src/contracts/AbstractContract.js index 38abf4b..7f8187e 100644 --- a/src/contracts/AbstractContract.js +++ b/src/contracts/AbstractContract.js @@ -9,23 +9,23 @@ class AbstractContract { * services such as an off chain store, as well as the functionality of the underlying * implementation. * @param {object} implementationInstance - Contract Implementation object to extend - * @param {object} storeProviderWrapperInstance - StoreProvider wrapper object. + * @param {object} storeProviderInstance - StoreProvider wrapper object. */ constructor( implementationInstance = isRequired('implementationInstance'), - storeProviderWrapperInstance = isRequired('storeProviderWrapperInstance') + storeProviderInstance = isRequired('storeProviderInstance') ) { - this._StoreProvider = storeProviderWrapperInstance + this._StoreProvider = storeProviderInstance this._contractImplementation = implementationInstance delegateCalls(this, implementationInstance) } /** - * Set the store wrapper - * @param {object} storeProviderWrapperInstance wrapper for store + * Set store provider instance. + * @param {object} storeProviderInstance - instance of store provider wrapper. */ - setStoreProvider = storeProviderWrapperInstance => { - this._StoreProvider = storeProviderWrapperInstance + setStoreProviderInstance = storeProviderInstance => { + this._StoreProvider = storeProviderInstance } } diff --git a/src/contracts/abstractions/index.js b/src/contracts/abstractions/index.js index 78ac05f..ed96342 100644 --- a/src/contracts/abstractions/index.js +++ b/src/contracts/abstractions/index.js @@ -1,4 +1,4 @@ import Arbitrator from './Arbitrator' -import ArbitrableContracts from './Arbitrable' +import Arbitrable from './Arbitrable' -export { Arbitrator, ArbitrableContracts } +export { Arbitrator, Arbitrable } diff --git a/src/kleros.js b/src/kleros.js index 0db7e24..42a2ef4 100644 --- a/src/kleros.js +++ b/src/kleros.js @@ -10,6 +10,8 @@ class Kleros { storeWrapper = {} + eventListener = null + /** * Instantiates a new Kelros instance that provides the public interface * to Kleros contracts and library. All params are required. To use an individual @@ -57,23 +59,16 @@ class Kleros { _arbitrableTransaction, this.storeWrapper ) - // EVENT LISTENER - this.eventListener = new EventListener([ - this.arbitrator._contractImplementation.contractInstance, - this.arbitrable._contractImplementation.contractInstance - ]) // DISPUTES this.disputes = new resources.Disputes( this.arbitrator, this.arbitrableContracts, - this.eventListener, this.storeWrapper ) // NOTIFICATIONS this.notifications = new resources.Notifications( this.arbitrator, this.arbitrableContracts, - this.eventListener, this.storeWrapper ) } @@ -90,16 +85,26 @@ class Kleros { account, callback // for notification callback ) => { - this.eventListener.clearArbitratorHandlers() - await this.disputes.addNewDisputeEventListener() - await this.disputes.addTokenShiftToJurorProfileEventListener( + // stop current event listeners + if (this.eventListener) { + this.eventListener.stopWatchingForEvents() + } + // reinitialize with current arbitrator contract instance + this.eventListener = new EventListener([ + this.arbitrator.getContractInstance() + ]) + // add handlers for notifications + this.notifications.registerArbitratorNotifications( account, + this.eventListener, callback ) - await this.disputes.addDisputeDeadlineHandler(account) - await this.disputes.addDisputeRulingHandler(account, callback) - await this.notifications.registerNotificationListeners(account, callback) - await this.eventListener.watchForArbitratorEvents(account) + // add handlers for event driven store updates + this.disputes.registerStoreUpdateEventListeners(account, this.eventListener) + // fetch last block for user + const fromBlock = await this.storeWrapper.getLastBlock(account) + // start event listener + this.eventListener.watchForEvents(fromBlock) } /** @@ -109,11 +114,10 @@ class Kleros { setStoreProvider = storeUri => { this.storeWrapper = new StoreProviderWrapper(storeUri) - this.eventListener.setStoreProvider(this.storeWrapper) - this.disputes.setStoreProvider(this.storeWrapper) - this.arbitrableContract.setStoreProvider(this.storeWrapper) - this.arbitrator.setStoreProvider(this.storeWrapper) - this.notifications.setStoreProvider(this.storeWrapper) + this.disputes.setStoreProviderInstance(this.storeWrapper) + this.arbitrableContract.setStoreProviderInstance(this.storeWrapper) + this.arbitrator.setStoreProviderInstance(this.storeWrapper) + this.notifications.setStoreProviderInstance(this.storeWrapper) } } diff --git a/src/resources/Disputes.js b/src/resources/Disputes.js index 984e14b..d1387cd 100644 --- a/src/resources/Disputes.js +++ b/src/resources/Disputes.js @@ -18,6 +18,27 @@ class Disputes { this._ArbitrableInstance = arbitrableInstance this._StoreProviderInstance = storeProviderInstance } + /** + * Set arbitrator instance. + * @param {object} arbitratorInstance - instance of an arbitrator contract. + */ + setArbitratorInstance = arbitratorInstance => { + this._ArbitratorInstance = arbitratorInstance + } + /** + * Set arbitrable instance. + * @param {object} arbitrableInstance - instance of an arbitrable contract. + */ + setArbitrableInstance = arbitrableInstance => { + this._ArbitrableInstance = arbitrableInstance + } + /** + * Set store provider instance. + * @param {object} storeProviderInstance - instance of store provider wrapper. + */ + setStoreProviderInstance = storeProviderInstance => { + this._StoreProviderInstance = storeProviderInstance + } // **************************** // // * Events * // diff --git a/src/resources/Notifications.js b/src/resources/Notifications.js index 327e9ea..855041a 100644 --- a/src/resources/Notifications.js +++ b/src/resources/Notifications.js @@ -51,7 +51,7 @@ class Notifications { * @param {object} eventListener - Event Listener that will fetch logs and call callbacks * @param {function} callback - If we want notifications to be "pushed" provide a callback function to call when a new notification is created. */ - registerArbitratorNotifications = async ( + registerArbitratorNotifications = ( account = isRequired('account'), eventListener = isRequired('eventListener'), callback diff --git a/src/utils/EventListener.js b/src/utils/EventListener.js index 0209787..d1d1b5a 100644 --- a/src/utils/EventListener.js +++ b/src/utils/EventListener.js @@ -7,13 +7,20 @@ import * as errorConstants from '../constants/error' class EventListener { /** * Listen for events in contract and handles callbacks with registered event handlers. - * @param {object[]} contractInstances - truffle-contract instances to fetch event logs for. + * @param {object[]} _contractInstances - truffle-contract instances to fetch event logs for. */ - constructor(contractInstances = []) { - this.contractInstances = contractInstances + constructor(_contractInstances = []) { + this.contractInstances = [] + // map address -> { event: [handlers], ... } this.contractEventHandlerMap = {} + // map address -> watcher instance + this.watcherInstances = {} // event handler queue this.eventHandlerQueue = new PromiseQueue() + // initialize class variables for new contract instances + _contractInstances.forEach(instance => { + this.addContractInstance(instance) + }) } /** @@ -86,13 +93,15 @@ class EventListener { // remove instance from this.contractInstances const removedInstance = _.remove( this.contractInstances, - instance => instance.contractAddress === contractAddress + instance => instance.address === contractAddress ) // if we didn't remove anything throw error if (removedInstance.length === 0) throw new Error(errorConstants.MISSING_CONTRACT_INSTANCE(contractAddress)) // stop watching on these instances - removedInstance.forEach(instance => instance.stopWatching()) + removedInstance.forEach(instance => + this.stopWatchingForEvents(instance.address) + ) // remove handlers for contract instance delete this.contractEventHandlerMap[contractAddress] } @@ -118,34 +127,43 @@ class EventListener { * @param {number} fromBlock - A block number can be passed to catch up on missed logs */ watchForEvents = (fromBlock = 'latest') => { - Promise.all( - this.contractInstances.forEach(instance => { - instance - .allEvents({ - fromBlock: fromBlock, - lastBlock: 'latest' - }) - .watch((error, result) => { - if (!error) { - const handlers = this.contractEventHandlerMap[instance.address][ - result.event - ] - if (handlers) { - handlers.forEach(handler => { - this._queueEvent(handler, result) - }) - } - } - }) + this.contractInstances.forEach(instance => { + const newWatcherInstance = instance.allEvents({ + fromBlock: fromBlock, + lastBlock: 'latest' }) - ) + + // NOTE: should we allow more than one listener per contract instance? + if (this.watcherInstances[instance.address]) + this.watcherInstances[instance.address].stopWatching() + + this.watcherInstances[instance.address] = newWatcherInstance + + newWatcherInstance.watch((error, result) => { + if (!error) { + const handlers = this.contractEventHandlerMap[instance.address][ + result.event + ] + if (handlers) { + handlers.forEach(handler => { + this._queueEvent(handler, result) + }) + } + } + }) + }) } /** - * Stop listening on contract. + * Stop listening on contract. If no contractAddress supplied it stops all listeners + * @param {string} contractAddress - Address of the contract to stop watching */ - stopWatchingForEvents = () => { - this.contractInstances.forEach(instance => instance.stopWatching()) + stopWatchingForEvents = contractAddress => { + if (contractAddress) this.watcherInstances[contractAddress].stopWatching() + else + this.contractInstances.forEach(instance => { + this.watcherInstances[instance.address].stopWatching() + }) } /** diff --git a/tests/integration/EventListener.test.js b/tests/integration/EventListener.test.js new file mode 100644 index 0000000..310eeee --- /dev/null +++ b/tests/integration/EventListener.test.js @@ -0,0 +1,158 @@ +import Web3 from 'web3' + +import KlerosPOC from '../../src/contracts/implementations/arbitrator/KlerosPOC' +import EventListener from '../../src/utils/EventListener' +import * as ethConstants from '../../src/constants/eth' +import setUpContracts from '../helpers/setUpContracts' +import waitNotifications from '../helpers/waitNotifications' +import delaySecond from '../helpers/delaySecond' + +describe('Event Listener', () => { + let partyA + let partyB + let other + let web3 + let eventCallback + let eventLogs = [] + let klerosPOCData + let arbitrableContractData + let provider + + beforeAll(async () => { + // use testRPC + provider = await new Web3.providers.HttpProvider( + ethConstants.LOCALHOST_ETH_PROVIDER + ) + + web3 = await new Web3(provider) + + partyA = web3.eth.accounts[1] + partyB = web3.eth.accounts[2] + other = web3.eth.accounts[5] + + klerosPOCData = { + timesPerPeriod: [1, 1, 1, 1, 1], + account: other, + value: 0 + } + + arbitrableContractData = { + partyA, + partyB, + value: 1, + hash: 'test', + timeout: 1, + extraData: '', + title: 'test title', + description: 'test description', + email: 'test@test.test' + } + + eventCallback = log => { + eventLogs.push(log) + } + }) + + it( + 'registers handler for event and successfully fires callback on log', + async () => { + const [ + klerosPOCAddress, + arbitrableContractAddress, + rngAddress, + pnkAddress + ] = await setUpContracts(provider, klerosPOCData, arbitrableContractData) + + expect(klerosPOCAddress).toBeDefined() + expect(arbitrableContractAddress).toBeDefined() + expect(rngAddress).toBeDefined() + expect(pnkAddress).toBeDefined() + + const KlerosPOCInstance = new KlerosPOC(provider, klerosPOCAddress) + // load contract + await KlerosPOCInstance.loadContract() + + const EventListenerInstance = new EventListener([ + KlerosPOCInstance.getContractInstance() + ]) + // set up callback + let { promise: waitPromise, callback: waitCallback } = waitNotifications( + 1, + eventCallback + ) + // add event handler + const eventName = 'NewPeriod' + EventListenerInstance.addEventHandler( + KlerosPOCInstance.getContractAddress(), + eventName, + waitCallback + ) + EventListenerInstance.watchForEvents() + + await delaySecond() + KlerosPOCInstance.passPeriod() + // we will wait for 2 seconds for promise to resolve or else throw + let throwError = true + setTimeout(() => { + if (throwError) { + EventListenerInstance.stopWatchingForEvents( + KlerosPOCInstance.getContractAddress() + ) + throw new Error('Callback Promise did not resolve') + } + }, 1000 * 2) + + await waitPromise + throwError = false + + expect(eventLogs.length).toEqual(1) + const log = eventLogs[0] + expect(log.event).toEqual(eventName) + + EventListenerInstance.stopWatchingForEvents( + KlerosPOCInstance.getContractAddress() + ) + }, + 50000 + ) + it('can stop and remove contract instance', async () => { + const [ + klerosPOCAddress, + arbitrableContractAddress, + rngAddress, + pnkAddress + ] = await setUpContracts(provider, klerosPOCData, arbitrableContractData) + + expect(klerosPOCAddress).toBeDefined() + expect(arbitrableContractAddress).toBeDefined() + expect(rngAddress).toBeDefined() + expect(pnkAddress).toBeDefined() + + const KlerosPOCInstance = new KlerosPOC(provider, klerosPOCAddress) + // load contract + await KlerosPOCInstance.loadContract() + + // add conract instance with event handler + const EventListenerInstance = new EventListener([ + KlerosPOCInstance.getContractInstance() + ]) + EventListenerInstance.addEventHandler( + KlerosPOCInstance.getContractAddress(), + 'FakeEvent', + () => {} + ) + + EventListenerInstance.watchForEvents() + + EventListenerInstance.removeContractInstance( + KlerosPOCInstance.getContractAddress() + ) + + expect(EventListenerInstance.contractInstances.length).toEqual(0) + expect( + EventListenerInstance.contractEventHandlerMap[ + KlerosPOCInstance.getContractAddress() + ] + ).toBeUndefined() + }) +}) diff --git a/tests/integration/disputeResolution.test.js b/tests/integration/disputeResolution.test.js index ba10a0b..fc19127 100644 --- a/tests/integration/disputeResolution.test.js +++ b/tests/integration/disputeResolution.test.js @@ -2,7 +2,9 @@ import Web3 from 'web3' import KlerosPOC from '../../src/contracts/implementations/arbitrator/KlerosPOC' import ArbitrableTransaction from '../../src/contracts/implementations/arbitrable/ArbitrableTransaction' +import Notifications from '../../src/resources/Notifications' import * as ethConstants from '../../src/constants/eth' +import * as notificationConstants from '../../src/constants/notification' import setUpContracts from '../helpers/setUpContracts' import delaySecond from '../helpers/delaySecond' @@ -69,6 +71,20 @@ describe('Dispute Resolution', () => { provider, arbitrableContractAddress ) + // Notifications instance for testing stateful notifications + const NotificationsInstance = new Notifications( + KlerosPOCInstance, + ArbitrableTransactionInstance + ) + // stateful notifications juror1 + let juror1StatefullNotifications = await NotificationsInstance.getStatefulNotifications( + juror1, + true + ) + expect(juror1StatefullNotifications.length).toEqual(1) + expect(juror1StatefullNotifications[0].notificationType).toEqual( + notificationConstants.TYPE.CAN_ACTIVATE + ) // juror1 should have no balance to start with const initialBalance = await KlerosPOCInstance.getPNKBalance(juror1) expect(initialBalance.tokenBalance).toEqual(0) @@ -89,6 +105,13 @@ describe('Dispute Resolution', () => { ) expect(balance.tokenBalance).toEqual(1) expect(balance.activatedTokens).toEqual(0.5) + + // stateful notifications juror1 + juror1StatefullNotifications = await NotificationsInstance.getStatefulNotifications( + juror1, + true + ) + expect(juror1StatefullNotifications.length).toEqual(0) // activate PNK juror2 await KlerosPOCInstance.activatePNK(activatedTokenAmount, juror2) @@ -221,6 +244,17 @@ describe('Dispute Resolution', () => { arbitrableContractAddress ) + const jurorForNotifications = + drawA.length > drawB.length ? juror1 : juror2 + // stateful notifications juror1 + let jurorStatefullNotifications = await NotificationsInstance.getStatefulNotifications( + jurorForNotifications, + true + ) + expect(jurorStatefullNotifications.length).toEqual(1) + expect(jurorStatefullNotifications[0].notificationType).toEqual( + notificationConstants.TYPE.CAN_VOTE + ) // submit rulings const rulingJuror1 = 1 await KlerosPOCInstance.submitVotes(0, rulingJuror1, drawA, juror1) @@ -238,13 +272,45 @@ describe('Dispute Resolution', () => { await delaySecond() await KlerosPOCInstance.passPeriod(other) + // stateful notifications + jurorStatefullNotifications = await NotificationsInstance.getStatefulNotifications( + jurorForNotifications, + true + ) + expect(jurorStatefullNotifications.length).toEqual(1) + expect(jurorStatefullNotifications[0].notificationType).toEqual( + notificationConstants.TYPE.CAN_REPARTITION + ) + // balances before ruling is executed const partyABalance = web3.eth.getBalance(partyA).toNumber() const partyBBalance = web3.eth.getBalance(partyB).toNumber() // repartition tokens await KlerosPOCInstance.repartitionJurorTokens(0, other) + + // stateful notifications + jurorStatefullNotifications = await NotificationsInstance.getStatefulNotifications( + jurorForNotifications, + true + ) + expect(jurorStatefullNotifications.length).toEqual(1) + expect(jurorStatefullNotifications[0].notificationType).toEqual( + notificationConstants.TYPE.CAN_EXECUTE + ) + // execute ruling await KlerosPOCInstance.executeRuling(0, other) + + juror1StatefullNotifications = await NotificationsInstance.getStatefulNotifications( + juror1, + true + ) + expect(juror1StatefullNotifications.length).toEqual(0) + let partyAStatefullNotifications = await NotificationsInstance.getStatefulNotifications( + partyA, + false + ) + expect(partyAStatefullNotifications.length).toEqual(0) // balances after ruling // partyA wins so they should recieve their arbitration fee as well as the value locked in contract diff --git a/tests/integration/notifications.test.js b/tests/integration/notifications.test.js deleted file mode 100644 index 36cfa9a..0000000 --- a/tests/integration/notifications.test.js +++ /dev/null @@ -1,303 +0,0 @@ -import Web3 from 'web3' - -import KlerosPOC from '../../src/contracts/implementations/arbitrator/KlerosPOC' -import ArbitrableTransaction from '../../src/contracts/implementations/arbitrable/ArbitrableTransaction' -import Notifications from '../../src/resourceWrappers/Notifications' -import EventListeners from '../../src/utils/EventListener' -import * as ethConstants from '../../src/constants/eth' -import * as notificationConstants from '../../src/constants/notification' -import setUpContracts from '../helpers/setUpContracts' -import waitNotifications from '../helpers/waitNotifications' -import delaySecond from '../helpers/delaySecond' - -describe('Notifications and Event Listeners', () => { - let partyA - let partyB - let juror1 - let juror2 - let other - let web3 - let notificationCallback - let notifications = [] - let klerosPOCData - let arbitrableContractData - let provider - - beforeAll(async () => { - // use testRPC - provider = await new Web3.providers.HttpProvider( - ethConstants.LOCALHOST_ETH_PROVIDER - ) - - web3 = await new Web3(provider) - - partyA = web3.eth.accounts[1] - partyB = web3.eth.accounts[2] - juror1 = web3.eth.accounts[3] - juror2 = web3.eth.accounts[4] - other = web3.eth.accounts[5] - - klerosPOCData = { - timesPerPeriod: [1, 1, 1, 1, 1], - account: other, - value: 0 - } - - arbitrableContractData = { - partyA, - partyB, - value: 1, - hash: 'test', - timeout: 1, - extraData: '', - title: 'test title', - description: 'test description', - email: 'test@test.test' - } - - notificationCallback = notification => { - notifications.push(notification) - } - }) - - it( - 'notifications in dispute resolution', - async () => { - const [ - klerosPOCAddress, - arbitrableContractAddress, - rngAddress, - pnkAddress - ] = await setUpContracts(provider, klerosPOCData, arbitrableContractData) - - expect(klerosPOCAddress).toBeDefined() - expect(arbitrableContractAddress).toBeDefined() - expect(rngAddress).toBeDefined() - expect(pnkAddress).toBeDefined() - - // EVENT LISTENER - const KlerosPOCInstance = new KlerosPOC(provider, klerosPOCAddress) - const ArbitrableTransactionInstance = new ArbitrableTransaction( - provider, - arbitrableContractAddress - ) - const EventListenerInstance = new EventListeners( - KlerosPOCInstance, - ArbitrableTransactionInstance - ) - const NotificationsInstance = new Notifications( - KlerosPOCInstance, - ArbitrableTransactionInstance, - EventListenerInstance - ) - - // stateful notifications juror1 - let juror1StatefullNotifications = await NotificationsInstance.getStatefulNotifications( - juror1, - true - ) - expect(juror1StatefullNotifications.length).toEqual(1) - expect(juror1StatefullNotifications[0].notificationType).toEqual( - notificationConstants.TYPE.CAN_ACTIVATE - ) - // buy 1 PNK juror1 - await KlerosPOCInstance.buyPNK(1, juror1) - // buy PNK for juror2 - await KlerosPOCInstance.buyPNK(1, juror2) - - // activate PNK juror1 - const activatedTokenAmount = 0.5 - KlerosPOCInstance.activatePNK(activatedTokenAmount, juror1) - // activate PNK juror2 - await KlerosPOCInstance.activatePNK(activatedTokenAmount, juror2) - - // stateful notifications juror1 - juror1StatefullNotifications = await NotificationsInstance.getStatefulNotifications( - juror1, - true - ) - expect(juror1StatefullNotifications.length).toEqual(0) - // return a bigint - // FIXME use arbitrableTransaction - const arbitrableContractInstance = await ArbitrableTransactionInstance.loadContract() - const partyAFeeContractInstance = await arbitrableContractInstance.partyAFee() - - // return bytes - // FIXME use arbitrableTransaction - let extraDataContractInstance = await arbitrableContractInstance.arbitratorExtraData() - - // return a bigint with the default value : 10000 wei fees in ether - const arbitrationCost = await KlerosPOCInstance.getArbitrationCost( - extraDataContractInstance - ) - // raise dispute party A - await ArbitrableTransactionInstance.payArbitrationFeeByPartyA( - partyA, - arbitrationCost - - KlerosPOCInstance._Web3Wrapper.fromWei( - partyAFeeContractInstance, - 'ether' - ) - ) - - const partyBFeeContractInstance = await arbitrableContractInstance.partyBFee() - - await ArbitrableTransactionInstance.payArbitrationFeeByPartyB( - partyB, - arbitrationCost - - KlerosPOCInstance._Web3Wrapper.fromWei( - partyBFeeContractInstance, - 'ether' - ) - ) - - // wait for dispute raised notification - let { - promise: waitPromisePartyA, - callback: waitCallbackPartyA - } = waitNotifications(1, notificationCallback) - await NotificationsInstance.registerNotificationListeners( - partyA, - waitCallbackPartyA - ) - await EventListenerInstance.watchForArbitratorEvents(partyA) - - await waitPromisePartyA - expect(notifications.length).toEqual(1) - expect(notifications[0].notificationType).toEqual( - notificationConstants.TYPE.DISPUTE_CREATED - ) - - EventListenerInstance.stopWatchingArbitratorEvents() - // pass state so jurors are selected - for (let i = 1; i < 3; i++) { - // NOTE we need to make another block before we can generate the random number. Should not be an issue on main nets where avg block time < period length - if (i === 2) - web3.eth.sendTransaction({ - from: partyA, - to: partyB, - value: 10000, - data: '0x' - }) - await delaySecond() - await KlerosPOCInstance.passPeriod(other) - } - - let drawA = [] - let drawB = [] - for (let i = 1; i <= 3; i++) { - if (await KlerosPOCInstance.isJurorDrawnForDispute(0, i, juror1)) { - drawA.push(i) - } else { - drawB.push(i) - } - } - expect(drawA.length > 0 || drawB.length > 0).toBeTruthy() - - const jurorForNotifications = - drawA.length > drawB.length ? juror1 : juror2 - // stateful notifications juror1 - let jurorStatefullNotifications = await NotificationsInstance.getStatefulNotifications( - jurorForNotifications, - true - ) - expect(jurorStatefullNotifications.length).toEqual(1) - expect(jurorStatefullNotifications[0].notificationType).toEqual( - notificationConstants.TYPE.CAN_VOTE - ) - // submit rulings - const rulingJuror1 = 1 - await KlerosPOCInstance.submitVotes(0, rulingJuror1, drawA, juror1) - const rulingJuror2 = 2 - await KlerosPOCInstance.submitVotes(0, rulingJuror2, drawB, juror2) - - await delaySecond() - await KlerosPOCInstance.passPeriod(other) - - await delaySecond() - await KlerosPOCInstance.passPeriod(other) - // stateful notifications - jurorStatefullNotifications = await NotificationsInstance.getStatefulNotifications( - jurorForNotifications, - true - ) - expect(jurorStatefullNotifications.length).toEqual(1) - expect(jurorStatefullNotifications[0].notificationType).toEqual( - notificationConstants.TYPE.CAN_REPARTITION - ) - - // repartition tokens - await KlerosPOCInstance.repartitionJurorTokens(0, other) - - // stateful notifications - jurorStatefullNotifications = await NotificationsInstance.getStatefulNotifications( - jurorForNotifications, - true - ) - expect(jurorStatefullNotifications.length).toEqual(1) - expect(jurorStatefullNotifications[0].notificationType).toEqual( - notificationConstants.TYPE.CAN_EXECUTE - ) - // execute ruling - await KlerosPOCInstance.executeRuling(0, other) - - juror1StatefullNotifications = await NotificationsInstance.getStatefulNotifications( - juror1, - true - ) - expect(juror1StatefullNotifications.length).toEqual(0) - let partyAStatefullNotifications = await NotificationsInstance.getStatefulNotifications( - partyA, - false - ) - expect(partyAStatefullNotifications.length).toEqual(0) - - expect(notifications.length).toBeTruthy() - - let notificationTypesExpected = [ - notificationConstants.TYPE.DISPUTE_CREATED - ] - let notificationTypes = notifications.map( - notification => notification.notificationType - ) - expect(notificationTypes.sort()).toEqual(notificationTypesExpected.sort()) - - EventListenerInstance.stopWatchingArbitratorEvents() - - // spin up juror1 notifications listener. should populate missed notifications - const numberOfNotifications = drawA.length + 2 - - notifications = [] - let { - promise: waitPromiseJuror, - callback: waitCallbackJuror - } = waitNotifications(numberOfNotifications, notificationCallback) - await NotificationsInstance.registerNotificationListeners( - juror1, - waitCallbackJuror - ) - await EventListenerInstance.watchForArbitratorEvents(juror1) - - await waitPromiseJuror - - expect(notifications.length).toBeTruthy() - - notificationTypesExpected = [ - notificationConstants.TYPE.ARBITRATION_REWARD, - notificationConstants.TYPE.APPEAL_POSSIBLE - ] - drawA.forEach(() => - notificationTypesExpected.push(notificationConstants.TYPE.TOKEN_SHIFT) - ) - - notificationTypes = notifications.map( - notification => notification.notificationType - ) - expect(notificationTypes.sort()).toEqual(notificationTypesExpected.sort()) - - EventListenerInstance.stopWatchingArbitratorEvents() - // TODO find way to check timestamps and other non-callback notifications - }, - 250000 - ) -}) diff --git a/tests/unit/contracts/abstractions/Arbitrable.test.js b/tests/unit/contracts/abstractions/Arbitrable.test.js index f314613..9e7be1b 100644 --- a/tests/unit/contracts/abstractions/Arbitrable.test.js +++ b/tests/unit/contracts/abstractions/Arbitrable.test.js @@ -47,7 +47,7 @@ describe('ArbitrableContract', async () => { getContractByAddress: mockGetContractByAddress } - arbitrableContractInstance.setStoreProvider(mockStore) + arbitrableContractInstance.setStoreProviderInstance(mockStore) const evidence = await arbitrableContractInstance.getEvidenceForArbitrableContract() @@ -82,7 +82,7 @@ describe('ArbitrableContract', async () => { getContractByAddress: mockGetContractByAddress } - arbitrableContractInstance.setStoreProvider(mockStore) + arbitrableContractInstance.setStoreProviderInstance(mockStore) const evidence = await arbitrableContractInstance.getEvidenceForArbitrableContract() diff --git a/tests/unit/contracts/abstractions/Arbitrator.test.js b/tests/unit/contracts/abstractions/Arbitrator.test.js index f878c96..04ba45a 100644 --- a/tests/unit/contracts/abstractions/Arbitrator.test.js +++ b/tests/unit/contracts/abstractions/Arbitrator.test.js @@ -25,7 +25,7 @@ describe('Arbitrator', () => { setUpUserProfile: mockShouldNotCall } - arbitratorInstance.setStoreProvider(mockStoreProvider) + arbitratorInstance.setStoreProviderInstance(mockStoreProvider) const mockArbitrator = { getPeriod: jest.fn().mockReturnValue(_asyncMockResponse(0)), @@ -61,7 +61,7 @@ describe('Arbitrator', () => { ) } - arbitratorInstance.setStoreProvider(mockStoreProvider) + arbitratorInstance.setStoreProviderInstance(mockStoreProvider) const mockArbitrator = { getPeriod: jest.fn().mockReturnValue(_asyncMockResponse(2)), @@ -103,7 +103,7 @@ describe('Arbitrator', () => { updateDisputeProfile: mockUpdateDisputeProfile } - arbitratorInstance.setStoreProvider(mockStoreProvider) + arbitratorInstance.setStoreProviderInstance(mockStoreProvider) const mockArbitrator = { getPeriod: jest.fn().mockReturnValue(_asyncMockResponse(2)), diff --git a/tests/unit/resourceWrappers/Disputes.test.js b/tests/unit/resources/Disputes.test.js similarity index 93% rename from tests/unit/resourceWrappers/Disputes.test.js rename to tests/unit/resources/Disputes.test.js index 3c8a77c..0013ca2 100644 --- a/tests/unit/resourceWrappers/Disputes.test.js +++ b/tests/unit/resources/Disputes.test.js @@ -1,4 +1,4 @@ -import DisputesApi from '../../../src/resourceWrappers/Disputes' +import DisputesApi from '../../../src/resources/Disputes' import _asyncMockResponse from '../../helpers/asyncMockResponse' describe('Disputes', () => { @@ -66,7 +66,7 @@ describe('Disputes', () => { canRuleDispute: jest.fn().mockReturnValue(false), getContractAddress: jest.fn().mockReturnValue(arbitratorAddress) } - disputesInstance._Arbitrator = mockArbitrator + disputesInstance._ArbitratorInstance = mockArbitrator const mockArbitrableContractData = { partyA, @@ -75,9 +75,10 @@ describe('Disputes', () => { } const mockArbitrableContract = { getData: jest.fn().mockReturnValue(mockArbitrableContractData), - getEvidenceForArbitrableContract: jest.fn().mockReturnValue([]) + getEvidenceForArbitrableContract: jest.fn().mockReturnValue([]), + setContractInstance: jest.fn() } - disputesInstance._ArbitrableContract = mockArbitrableContract + disputesInstance._ArbitrableInstance = mockArbitrableContract const mockContract = { description: 'testdesc', @@ -86,7 +87,7 @@ describe('Disputes', () => { const mockStoreProvider = { getContractByAddress: jest.fn().mockReturnValue(mockContract) } - disputesInstance.setStoreProvider(mockStoreProvider) + disputesInstance.setStoreProviderInstance(mockStoreProvider) const disputeData = await disputesInstance.getDataForDispute( disputeId, @@ -150,7 +151,7 @@ describe('Disputes', () => { canRuleDispute: jest.fn().mockReturnValue(true), getContractAddress: jest.fn().mockReturnValue(arbitratorAddress) } - disputesInstance._Arbitrator = mockArbitrator + disputesInstance._ArbitratorInstance = mockArbitrator const mockArbitrableContractData = { partyA, @@ -159,9 +160,10 @@ describe('Disputes', () => { } const mockArbitrableContract = { getData: jest.fn().mockReturnValue(mockArbitrableContractData), - getEvidenceForArbitrableContract: jest.fn().mockReturnValue([]) + getEvidenceForArbitrableContract: jest.fn().mockReturnValue([]), + setContractInstance: jest.fn() } - disputesInstance._ArbitrableContract = mockArbitrableContract + disputesInstance._ArbitrableInstance = mockArbitrableContract const mockContract = { description: 'testdesc', @@ -178,7 +180,7 @@ describe('Disputes', () => { getContractByAddress: jest.fn().mockReturnValue(mockContract), getDisputeData: jest.fn().mockReturnValue(mockUserData) } - disputesInstance.setStoreProvider(mockStoreProvider) + disputesInstance.setStoreProviderInstance(mockStoreProvider) const disputeData = await disputesInstance.getDataForDispute( disputeId, @@ -264,7 +266,7 @@ describe('Disputes', () => { canRuleDispute: jest.fn().mockReturnValue(false), getContractAddress: jest.fn().mockReturnValue(arbitratorAddress) } - disputesInstance._Arbitrator = mockArbitrator + disputesInstance._ArbitratorInstance = mockArbitrator const mockArbitrableContractData = { partyA, @@ -273,9 +275,10 @@ describe('Disputes', () => { } const mockArbitrableContract = { getData: jest.fn().mockReturnValue(mockArbitrableContractData), - getEvidenceForArbitrableContract: jest.fn().mockReturnValue([]) + getEvidenceForArbitrableContract: jest.fn().mockReturnValue([]), + setContractInstance: jest.fn() } - disputesInstance._ArbitrableContract = mockArbitrableContract + disputesInstance._ArbitrableInstance = mockArbitrableContract const mockContract = { description: 'testdesc', @@ -292,7 +295,7 @@ describe('Disputes', () => { getContractByAddress: jest.fn().mockReturnValue(mockContract), getDisputeData: jest.fn().mockReturnValue(mockUserData) } - disputesInstance.setStoreProvider(mockStoreProvider) + disputesInstance.setStoreProviderInstance(mockStoreProvider) const disputeData = await disputesInstance.getDataForDispute( disputeId, @@ -380,7 +383,7 @@ describe('Disputes', () => { canRuleDispute: jest.fn().mockReturnValue(false), getContractAddress: jest.fn().mockReturnValue(arbitratorAddress) } - disputesInstance._Arbitrator = mockArbitrator + disputesInstance._ArbitratorInstance = mockArbitrator const mockArbitrableContractData = { partyA, @@ -389,9 +392,10 @@ describe('Disputes', () => { } const mockArbitrableContract = { getData: jest.fn().mockReturnValue(mockArbitrableContractData), - getEvidenceForArbitrableContract: jest.fn().mockReturnValue([]) + getEvidenceForArbitrableContract: jest.fn().mockReturnValue([]), + setContractInstance: jest.fn() } - disputesInstance._ArbitrableContract = mockArbitrableContract + disputesInstance._ArbitrableInstance = mockArbitrableContract const mockContract = { description: 'testdesc', @@ -408,7 +412,7 @@ describe('Disputes', () => { getContractByAddress: jest.fn().mockReturnValue(mockContract), getDisputeData: jest.fn().mockReturnValue(mockUserData) } - disputesInstance.setStoreProvider(mockStoreProvider) + disputesInstance.setStoreProviderInstance(mockStoreProvider) const disputeData = await disputesInstance.getDataForDispute( disputeId,