Skip to content
This repository was archived by the owner on Jun 30, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,31 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

<a name="0.0.62"></a>
## 0.0.62 (2018-02-28)


### Bug Fixes

* **getDeadlineForDispute:** fix wrong computation and return date object ([7ee05f5](https://github.com/kleros/kleros-api/commit/7ee05f5))
* skip broken test assertions ([d210c53](https://github.com/kleros/kleros-api/commit/d210c53))
* test suite ([98b777d](https://github.com/kleros/kleros-api/commit/98b777d))


### Features

* normalize token units ([d0d40f8](https://github.com/kleros/kleros-api/commit/d0d40f8))
* **disputes:** build voteCounters and PNKRepartitions from getters ([ba48e67](https://github.com/kleros/kleros-api/commit/ba48e67))
* **disputes:** change approach to getting netPNK and votesCounter ([366340f](https://github.com/kleros/kleros-api/commit/366340f))
* **disputes:** createdAt and ruledAt timestamps added in events ([8e9cafa](https://github.com/kleros/kleros-api/commit/8e9cafa))
* **disputes:** remove netPNK until events are fixed ([255bf03](https://github.com/kleros/kleros-api/commit/255bf03))
* **disputes:** return appealsRepartitioned ([1246968](https://github.com/kleros/kleros-api/commit/1246968))
* **disputes:** return deadline as epoch in ms instead of a date object ([90d4856](https://github.com/kleros/kleros-api/commit/90d4856))
* **disputes:** return dispute status ([32db45c](https://github.com/kleros/kleros-api/commit/32db45c))
* **disputes:** submittedAt timestamp for evidence ([3656d33](https://github.com/kleros/kleros-api/commit/3656d33))



<a name="0.0.61"></a>

## 0.0.61 (2018-02-27)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
</p>

<p align="center">
<a href="https://badge.fury.io/js/kleros-api"><img src="https://badge.fury.io/js/kleros-api.svg" alt="NPM Version"></a>
<a href="https://travis-ci.org/kleros/kleros-api"><img src="https://travis-ci.org/kleros/kleros-api.svg?branch=master" alt="Build Status"></a>
<a href="https://badge.fury.io/js/kleros-api"><img src="https://badge.fury.io/js/kleros-api.svg" alt="npm version" height="18"></a>
<a href="https://coveralls.io/github/kleros/kleros-api?branch=master"><img src="https://coveralls.io/repos/github/kleros/kleros-api/badge.svg?branch=master" alt="Coverage Status"></a>
<a href="https://david-dm.org/kleros/kleros-api"><img src="https://david-dm.org/kleros/kleros-api.svg" alt="Dependencies"></a>
<a href="https://david-dm.org/kleros/kleros-api?type=dev"><img src="https://david-dm.org/kleros/kleros-api/dev-status.svg" alt="Dev Dependencies"></a>
Expand Down
15 changes: 10 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
{
"name": "kleros-api",
"version": "0.0.61",
"description":
"A Javascript library that makes it easy to build relayers and other DApps that use the Kleros protocol.",
"keywords": ["Blockchain", "Ethereum", "Kleros"],
"version": "0.0.62",
"description": "A Javascript library that makes it easy to build relayers and other DApps that use the Kleros protocol.",
"keywords": [
"Blockchain",
"Ethereum",
"Kleros"
],
"homepage": "https://kleros.io",
"repository": "github:kleros/kleros-api",
"bugs": "https://github.com/kleros/kleros-api/issues",
Expand All @@ -28,7 +31,9 @@
"build": "webpack --env.NODE_ENV=production -p"
},
"commitlint": {
"extends": ["@commitlint/config-conventional"]
"extends": [
"@commitlint/config-conventional"
]
},
"devDependencies": {
"babel-core": "^6.26.0",
Expand Down
208 changes: 166 additions & 42 deletions src/abstractWrappers/Disputes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import _ from 'lodash'

import * as ethConstants from '../constants/eth'
import * as arbitratorConstants from '../constants/arbitrator'
import * as contractConstants from '../constants/contract'
import * as notificationConstants from '../constants/notification'

import AbstractWrapper from './AbstractWrapper'

Expand Down Expand Up @@ -36,7 +36,16 @@ class Disputes extends AbstractWrapper {
)
// if listener is a party in dispute add to store
if (disputeData.partyA === address || disputeData.partyB === address) {
await this._updateStoreForDispute(contractAddress, disputeId, address)
const blockNumber = event.blockNumber
const block = this._Arbitrator._Web3Wrapper.getBlock(blockNumber)

// add new dispute with timestamp
await this._updateStoreForDispute(
contractAddress,
disputeId,
address,
block.timestamp * 1000
)
}
}

Expand Down Expand Up @@ -97,6 +106,127 @@ class Disputes extends AbstractWrapper {
)
}

/**
* Event listener that sends notification when a dispute has been ruled on.
* @param {string} arbitratorAddress - The arbitrator contract's address.
* @param {string} account - The users eth account.
* @param {function} callback - <optional> function to be called when event is triggered.
*/
addDisputeRulingHandler = async (arbitratorAddress, account, callback) => {
if (!this._eventListener) return

const _disputeRulingHandler = async (
event,
contractAddress = arbitratorAddress,
address = account,
notificationCallback = callback
) => {
const newPeriod = event.args._period.toNumber()
const txHash = event.transactionHash
// send appeal possible notifications
if (newPeriod === arbitratorConstants.PERIOD.APPEAL) {
this._checkArbitratorWrappersSet()
const userProfile = await this._StoreProvider.getUserProfile(address)
// contract data
const arbitratorData = await this._Arbitrator.getData(
contractAddress,
address
)
let disputeId = 0
const currentSession = arbitratorData.session

let dispute
while (1) {
// iterate over all disputes (FIXME inefficient)
try {
dispute = await this._Arbitrator.getDispute(
contractAddress,
disputeId
)
if (dispute.arbitratedContract === ethConstants.NULL_ADDRESS) break
// session + number of appeals
const disputeSession =
dispute.firstSession + dispute.numberOfAppeals
// if dispute not in current session skip
if (disputeSession !== currentSession) {
disputeId++
dispute = await this._Arbitrator.getDispute(
contractAddress,
disputeId
)
continue
}

const ruling = await this._Arbitrator.currentRulingForDispute(
contractAddress,
disputeId
)

if (
_.findIndex(
userProfile.disputes,
dispute =>
dispute.disputeId === disputeId &&
dispute.arbitratorAddress === contractAddress
) >= 0
) {
await this._StoreProvider.newNotification(
address,
txHash,
disputeId, // use disputeId instead of logIndex since it doens't have its own event
notificationConstants.TYPE.APPEAL_POSSIBLE,
'A ruling has been made. Appeal is possible',
{
disputeId,
contractAddress,
ruling
}
)
// get ruledAt from block timestamp
const blockNumber = event.blockNumber
const block = this._Arbitrator._Web3Wrapper.getBlock(blockNumber)
// add ruledAt to store
await this._updateStoreForDispute(
contractAddress,
disputeId,
address,
null,
block.timestamp * 1000
)

if (notificationCallback) {
const userProfile = await this._StoreProvider.getUserProfile(
address
)
const notification = _.filter(
userProfile.notifications,
notification =>
notification.txHash === txHash &&
notification.logIndex === disputeId
)

if (notification) {
notificationCallback(notification[0])
}
}
}
// check next dispute
disputeId += 1
// eslint-disable-next-line no-unused-vars
} catch (err) {
// getDispute(n) throws an error if index out of range
break
}
}
}
}

await this._eventListener.registerArbitratorEvent(
'NewPeriod',
_disputeRulingHandler
)
}

// **************************** //
// * Public * //
// **************************** //
Expand All @@ -123,7 +253,6 @@ class Disputes extends AbstractWrapper {
)

if (!txHash) throw new Error('unable to pay arbitration fee for party A')
await this._storeNewDispute(arbitrableContractAddress, account)
return txHash
} catch (err) {
throw new Error(err)
Expand Down Expand Up @@ -151,39 +280,14 @@ class Disputes extends AbstractWrapper {
)

if (!txHash) throw new Error('unable to pay arbitration fee for party B')
await this._storeNewDispute(arbitrableContractAddress, account)
return txHash
}

/**
* If there is a dispute in contract update store.
* @param {string} arbitrableContractAddress - The arbitrable contract's address.
* @param {string} account - The account.
*/
_storeNewDispute = async (arbitrableContractAddress, account) => {
this._checkArbitratorWrappersSet()
this._checkArbitrableWrappersSet()

const arbitrableContractData = await this._ArbitrableContract.getData(
arbitrableContractAddress
)

if (
arbitrableContractData.status === contractConstants.STATUS.DISPUTE_CREATED
) {
await this._updateStoreForDispute(
arbitrableContractData.arbitrator,
arbitrableContractData.disputeId,
account
)
}
}

/**
* Get disputes for user with extra data from arbitrated transaction and store.
* @param {string} arbitratorAddress - Address of Kleros contract.
* @param {string} account - Address of user.
* @returns {object[]} - Dispute data objects for user.
* Get disputes for user with extra data from arbitrated transaction and store
* @param {string} arbitratorAddress address of Kleros contract
* @param {string} account address of user
* @returns {object[]} dispute data objects for user
*/
getDisputesForUser = async (arbitratorAddress, account) => {
// FIXME don't like having to call this every fnc
Expand Down Expand Up @@ -381,8 +485,8 @@ class Disputes extends AbstractWrapper {
/**
* Gets the deadline for an arbitrator's period, which is also the deadline for all its disputes.
* @param {string} arbitratorAddress - The address of the arbitrator contract.
* @param {number} [period=arbitratorConstants.PERIOD.VOTE] - The period to get the deadline for.
* @returns {Date} - A date object.
* @param {number} [period=PERIODS.VOTE] - The period to get the deadline for.
* @returns {number} - epoch timestamp
*/
getDeadlineForDispute = async (
arbitratorAddress,
Expand All @@ -404,19 +508,29 @@ class Disputes extends AbstractWrapper {
* @param {string} arbitratorAddress Address address of arbitrator contract
* @param {int} disputeId index of dispute
* @param {string} account address of party to update dispute or
* @param {number} createdAt <optional> epoch timestamp of when dispute was created
* @param {number} ruledAt <optional> epoch timestamp of when dispute was ruled on
* @returns {object} updated dispute object
*/
_updateStoreForDispute = async (arbitratorAddress, disputeId, account) => {
_updateStoreForDispute = async (
arbitratorAddress,
disputeId,
account,
createdAt,
ruledAt
) => {
const disputeData = await this.getDataForDispute(
arbitratorAddress,
disputeId,
account
)

// update dispute
await this._StoreProvider.updateDispute(
const dispute = await this._StoreProvider.updateDispute(
disputeData.disputeId,
disputeData.arbitratorAddress,
disputeData.hash,
disputeData.arbitrableContractAddress,
disputeData.partyA,
disputeData.partyB,
disputeData.title,
Expand All @@ -425,8 +539,10 @@ class Disputes extends AbstractWrapper {
disputeData.fee,
disputeData.information,
disputeData.justification,
disputeData.resolutionOptions
).body
disputeData.resolutionOptions,
createdAt || disputeData.createdAt,
ruledAt || disputeData.ruledAt
)

// update profile for account
await this._StoreProvider.updateDisputeProfile(
Expand All @@ -435,9 +551,11 @@ class Disputes extends AbstractWrapper {
disputeData.arbitratorAddress,
disputeData.disputeId,
disputeData.votes.length > 0,
false,
0
disputeData.hasRuled,
disputeData.netPNK ? disputeData.netPNK : 0
)

return dispute
}

/**
Expand Down Expand Up @@ -561,17 +679,21 @@ class Disputes extends AbstractWrapper {
let votes = []
let hasRuled = false
let netPNK = 0
let createdAt
let ruledAt
if (account) {
votes = await this.getVotesForJuror(arbitratorAddress, disputeId, account)
try {
const userData = await this.getUserDisputeFromStore(
const userData = await this._StoreProvider.getDisputeData(
arbitratorAddress,
disputeId,
account
)
isJuror = userData.isJuror
hasRuled = userData.hasRuled
netPNK = userData.netPNK
createdAt = userData.createdAt
ruledAt = userData.ruledAt
// eslint-disable-next-line no-unused-vars
} catch (err) {
// fetching dispute will fail if it hasn't been added to the store yet. this is ok we can just not return store data
Expand Down Expand Up @@ -622,7 +744,9 @@ class Disputes extends AbstractWrapper {
hasRuled,
ruling,
evidence,
netPNK
netPNK,
ruledAt,
createdAt
}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/abstractWrappers/Notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ class Notifications extends AbstractWrapper {
dispute.arbitratorAddress,
dispute.disputeId
)

if (
disputeData.firstSession + disputeData.numberOfAppeals ===
currentSession
Expand Down
Loading