From 1d5af49a9595fe8b9aaa4c45bf1560c22f6ba0bb Mon Sep 17 00:00:00 2001 From: Sam Vitello Date: Tue, 5 Jun 2018 14:55:01 -0700 Subject: [PATCH] fix: bugs in fetching timestamps --- src/contracts/abstractions/Arbitrator.js | 20 ++++- .../implementations/arbitrator/KlerosPOC.js | 15 ++-- src/resources/Disputes.js | 75 ++++++++++++++----- src/utils/EventListener.js | 2 +- src/utils/StoreProviderWrapper.js | 2 +- 5 files changed, 82 insertions(+), 32 deletions(-) diff --git a/src/contracts/abstractions/Arbitrator.js b/src/contracts/abstractions/Arbitrator.js index 33a5702..121fd17 100644 --- a/src/contracts/abstractions/Arbitrator.js +++ b/src/contracts/abstractions/Arbitrator.js @@ -2,6 +2,7 @@ import _ from 'lodash' import * as arbitratorConstants from '../../constants/arbitrator' import AbstractContract from '../AbstractContract' +import EventListener from '../../utils/EventListener' /** * Arbitrator Abstract Contarct API. This wraps an arbitrator contract. It provides @@ -44,21 +45,32 @@ class Arbitrator extends AbstractContract { // update user profile for each dispute await Promise.all( myDisputes.map(async dispute => { + const disputeCreationLog = (await EventListener.getEventLogs( + this._contractImplementation, + 'DisputeCreation', + 0, + 'latest', + { "_disputeID": dispute.disputeId} + ))[0] + if (!disputeCreationLog) + throw new Error('Could not fetch dispute creation event log') // update profile for account await this._StoreProvider.updateDisputeProfile( account, dispute.arbitratorAddress, dispute.disputeId, { - appealDraws: dispute.appealDraws + appealDraws: dispute.appealDraws, + blockNumber: disputeCreationLog.blockNumber } ) }) ) - this._StoreProvider.updateUserProfile(account, { - session: currentSession - }) + // FIXME do we want to store session? + // this._StoreProvider.updateUserProfile(account, { + // session: currentSession + // }) } return _getDisputesForUserFromStore(account) diff --git a/src/contracts/implementations/arbitrator/KlerosPOC.js b/src/contracts/implementations/arbitrator/KlerosPOC.js index f61b7aa..3dbac45 100644 --- a/src/contracts/implementations/arbitrator/KlerosPOC.js +++ b/src/contracts/implementations/arbitrator/KlerosPOC.js @@ -642,7 +642,10 @@ class KlerosPOC extends ContractImplementation { numberOfAppeals + 1 ) - const eventLogTimestamps = [startBlock] + const creationTimestamp = await this._getTimestampForBlock( + startBlock + ) + const eventLogTimestamps = [(creationTimestamp * 1000)] // skip first execute phase as this is the original ruling for (let i = 1; i < eventLogs.length; i++) { @@ -662,7 +665,7 @@ class KlerosPOC extends ContractImplementation { * @returns {object} dispute creation event log. */ getDisputeCreationEvent = async disputeId => { - const eventLogs = await EventListener.getNextEventLogs( + const eventLogs = await EventListener.getEventLogs( this, 'DisputeCreation', 0 @@ -671,7 +674,7 @@ class KlerosPOC extends ContractImplementation { for (let i = 0; i < eventLogs.length; i++) { const log = eventLogs[i] - if (log.args.disputeID.toNumber() === disputeId) return log + if (log.args._disputeID.toNumber() === disputeId) return log } return null @@ -684,7 +687,7 @@ class KlerosPOC extends ContractImplementation { * @returns {number} The net total PNK */ getNetTokensForDispute = async (disputeId, account) => { - const eventLogs = await EventListener.getNextEventLogs( + const eventLogs = await EventListener.getEventLogs( this, 'TokenShift', 0, @@ -695,7 +698,7 @@ class KlerosPOC extends ContractImplementation { let netPNK = 0 for (let i = 0; i < eventLogs.length; i++) { const event = eventLogs[i] - if (event.args.disputeID.toNumber() === disputeId) + if (event.args._disputeID.toNumber() === disputeId) netPNK += event.args._amount.toNumber() } @@ -718,7 +721,7 @@ class KlerosPOC extends ContractImplementation { * @returns {object[]} an array of event logs. */ _getNewPeriodEventLogs = async (blockNumber, periodNumber, appeals = 0) => { - const logs = await EventListener.getNextEventLogs( + const logs = await EventListener.getEventLogs( this, 'NewPeriod', blockNumber diff --git a/src/resources/Disputes.js b/src/resources/Disputes.js index 721f197..dcbc7a0 100644 --- a/src/resources/Disputes.js +++ b/src/resources/Disputes.js @@ -109,6 +109,34 @@ class Disputes { } } + _getDisputeStartBlock = async (disputeId, account) => { + const arbitratorAddress = this._ArbitratorInstance.getContractAddress() + + let blockNumber + + try { + const userData = await this._StoreProviderInstance.getDispute( + account, + arbitratorAddress, + disputeId + ) + blockNumber = userData.blockNumber + // eslint-disable-next-line no-unused-vars + } catch (err) {} + // if block number is not stored we can look it up + if (!blockNumber) { + // Fetching a dispute will fail if it hasn't been added to the store yet. This is ok, we can just not return store data + // see if we can get dispute start block from events + const disputeCreationEvent = await this._ArbitratorInstance.getDisputeCreationEvent( + disputeId + ) + if (disputeCreationEvent) { + blockNumber = disputeCreationEvent.blockNumber + } + } + return blockNumber + } + // **************************** // // * Public * // // **************************** // @@ -118,7 +146,7 @@ class Disputes { * @param {string} disputeId - The index of the dispute. * @returns {Promise} The dispute data in the store. */ - getDisputeFromStore = (account, disputeId) => { + getDisputeFromStore = async (account, disputeId) => { const arbitratorAddress = this._ArbitratorInstance.getContractAddress() return this._StoreProviderInstance.getDispute( account, @@ -127,6 +155,17 @@ class Disputes { ) } + getDisputeDeadline = async (disputeId, account, appeal=0) => { + const startBlock = await this._getDisputeStartBlock(disputeId, account) + // if there is no start block that means that dispute has not been created yet. + if (!startBlock) return [] + + return this._ArbitratorInstance.getDisputeDeadlineTimestamps( + startBlock, + appeal + ) + } + /** * Get data for a dispute. This method provides data from the store as well as both * arbitrator and arbitrable contracts. Used to get all relevant data on a dispute. @@ -164,27 +203,23 @@ class Disputes { let appealCreatedAt = [] let appealDeadlines = [] let appealRuledAt = [] - let startBlock - try { - const userData = await this._StoreProviderInstance.getDispute( - account, - arbitratorAddress, - disputeId - ) - if (userData.appealDraws) appealDraws = userData.appealDraws || [] - startBlock = userData.blockNumber - // eslint-disable-next-line no-unused-vars - } catch (err) { - // Fetching a dispute will fail if it hasn't been added to the store yet. This is ok, we can just not return store data - // see if we can get dispute start block from events - const disputeCreationEvent = this._ArbitratorInstance.getDisputeCreationEvent( - disputeId - ) - if (disputeCreationEvent) startBlock = disputeCreationEvent.blockNumber - } + const startBlock = await this._getDisputeStartBlock(disputeId, account) + // dispute exists if (startBlock) { - // get timestamps + try { + const userData = await this._StoreProviderInstance.getDispute( + account, + arbitratorAddress, + disputeId + ) + if (userData.appealDraws) appealDraws = userData.appealDraws || [] + // eslint-disable-next-line no-unused-vars + } catch (err) { + // Dispute exists on chain but not in store. We have lost draws for past disputes. + console.error("Dispute does not exist in store.") + } + appealDeadlines = await this._ArbitratorInstance.getDisputeDeadlineTimestamps( startBlock, dispute.numberOfAppeals diff --git a/src/utils/EventListener.js b/src/utils/EventListener.js index 3f1d56c..875208f 100644 --- a/src/utils/EventListener.js +++ b/src/utils/EventListener.js @@ -65,7 +65,7 @@ class EventListener { * @param {object} filters - Extra filters * @returns {Promise} All events in block range. */ - static getNextEventLogs = async ( + static getEventLogs = async ( contractImplementationInstance = isRequired( 'contractImplementationInstance' ), diff --git a/src/utils/StoreProviderWrapper.js b/src/utils/StoreProviderWrapper.js index 3d8c5e8..2ad7049 100644 --- a/src/utils/StoreProviderWrapper.js +++ b/src/utils/StoreProviderWrapper.js @@ -102,7 +102,7 @@ class StoreProviderWrapper { getContractByAddress = async (userAddress, addressContract) => { const userProfile = await this.getUserProfile(userAddress) if (!userProfile) - throw new Error(errorConstants.PROFILE_NOT_FOUND(userAddress)) + return {} let contract = _.filter( userProfile.contracts,