From be74fd72a912fc044f32a0f704183a7c43846b5a Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Mon, 9 Mar 2020 11:13:35 -0300 Subject: [PATCH 01/18] Draft: Initial query mock data implementation --- package.json | 6 ++- src/environment.js | 3 ++ src/hooks/query-hooks.js | 2 + src/hooks/useCourtContracts.js | 4 ++ src/index.js | 4 +- src/mock/customFetchExchange.js | 74 +++++++++++++++++++++++++++++++++ src/mock/mock-data.js | 8 ++++ src/queries/balances.js | 2 +- 8 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 src/mock/customFetchExchange.js create mode 100644 src/mock/mock-data.js diff --git a/package.json b/package.json index fe6e5b5c..86ca9826 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,8 @@ "styled-components": "^4.4.1", "subscriptions-transport-ws": "^0.9.16", "urql": "^1.6.3", - "use-wallet": "^0.4.1" + "use-wallet": "^0.4.1", + "wonka": "^4.0.7" }, "scripts": { "start": "npm run sync-assets && REACT_APP_BUILD=$(git log --pretty=format:'%h' -n 1) react-app-rewired start", @@ -44,6 +45,9 @@ "build:mainnet": "REACT_APP_CHAIN_ID=1 npm run build", "build:ropsten": "REACT_APP_CHAIN_ID=3 npm run build", "build:rinkeby": "REACT_APP_CHAIN_ID=4 npm run build", + "mock:rpc": "REACT_APP_MOCK_TEST=1 npm run start:rpc", + "mock:mainnet": "REACT_APP_MOCK_TEST=1 npm run start:mainnet", + "mock:rinkeby": "REACT_APP_MOCK_TEST=1 npm run start:rinkeby", "lint": "eslint ./src", "test": "react-app-rewired test", "eject": "react-scripts eject", diff --git a/src/environment.js b/src/environment.js index 5879c6ad..7894def7 100644 --- a/src/environment.js +++ b/src/environment.js @@ -28,6 +28,9 @@ const ENV_VARS = { ENABLE_SENTRY() { return process.env.REACT_APP_ENABLE_SENTRY === '1' }, + MOCK_TEST() { + return process.env.REACT_APP_MOCK_TEST === '1' + }, } export default function env(name) { diff --git a/src/hooks/query-hooks.js b/src/hooks/query-hooks.js index 44fd2226..67231347 100644 --- a/src/hooks/query-hooks.js +++ b/src/hooks/query-hooks.js @@ -45,6 +45,8 @@ export function useFirstANJActivationQuery(jurorId, { pause = false }) { pause, }) + console.log('query result', result) + const { juror } = result.data || {} return juror ? juror.movements[0] : null diff --git a/src/hooks/useCourtContracts.js b/src/hooks/useCourtContracts.js index 1bf32956..20f1a0a6 100644 --- a/src/hooks/useCourtContracts.js +++ b/src/hooks/useCourtContracts.js @@ -361,6 +361,10 @@ export function useTotalActiveBalancePolling(termId) { const timeoutId = useRef(null) const fetchTotalActiveBalance = useCallback(() => { + if (!jurorRegistryContract) { + return + } + timeoutId.current = setTimeout(() => { return jurorRegistryContract .totalActiveBalanceAt(termId) diff --git a/src/index.js b/src/index.js index f8a18df8..b63165a6 100644 --- a/src/index.js +++ b/src/index.js @@ -5,9 +5,9 @@ import { Provider as UrqlProvider, cacheExchange, debugExchange, - fetchExchange, subscriptionExchange, } from 'urql' +import customFetchExchange from './mock/customFetchExchange' import { SubscriptionClient } from 'subscriptions-transport-ws' import { devtoolsExchange } from '@urql/devtools' import * as Sentry from '@sentry/browser' @@ -29,7 +29,7 @@ const client = createClient({ debugExchange, devtoolsExchange, cacheExchange, - fetchExchange, + customFetchExchange, subscriptionExchange({ forwardSubscription: operation => subscriptionClient.request(operation), }), diff --git a/src/mock/customFetchExchange.js b/src/mock/customFetchExchange.js new file mode 100644 index 00000000..46db0a6c --- /dev/null +++ b/src/mock/customFetchExchange.js @@ -0,0 +1,74 @@ +import { fetchExchange, makeResult } from 'urql' +import { filter, make, merge, mergeMap, pipe, share, takeUntil } from 'wonka' +import env from '../environment' +import mockedData from './mock-data' + +const OPERATION_DEFINITION = 'OperationDefinition' + +export default function customFetchExchange(ref) { + if (!env('MOCK_TEST')) { + return fetchExchange(ref) + } + + const { forward } = ref + + const isOperationQuery = operation => { + const { operationName } = operation + return operationName === 'query' + } + + return ops$ => { + const sharedOps$ = share(ops$) + const fetchResults$ = pipe( + sharedOps$, + filter(isOperationQuery), + mergeMap(operation => { + const { key } = operation + const teardown$ = pipe( + sharedOps$, + filter(op => op.operationName === 'teardown' && op.key === key) + ) + + return pipe(mockData(operation), takeUntil(teardown$)) + }) + ) + + const forward$ = pipe( + sharedOps$, + filter(op => !isOperationQuery(op)), + forward + ) + + return merge([fetchResults$, forward$]) + } +} + +// const getOperationName = query => { +// const node = query.definitions.find(node => { +// return node.kind === Kind.OPERATION_DEFINITION && node.name +// }) + +// return node !== undefined && node.name ? node.name.value : null +// } + +const mockData = operation => { + return make(({ next, complete }) => { + const { name: queryName } = operation.query.definitions.find( + node => node.kind === OPERATION_DEFINITION && node.name + ) + + const convertedData = mockedData[queryName.value] + + console.log('convertedData', convertedData) + console.log('next', next) + console.log('complete', complete) + + if (convertedData) { + const result = makeResult(operation, { data: convertedData }) + console.log('result', result) + next(result) + } + + return complete() + }) +} diff --git a/src/mock/mock-data.js b/src/mock/mock-data.js new file mode 100644 index 00000000..f4a7cc68 --- /dev/null +++ b/src/mock/mock-data.js @@ -0,0 +1,8 @@ +export default { + JurorFirstANJActivationMovement: { + amount: '0', + effectiveTermId: '3', + createdAt: '903033', + type: '', + }, +} diff --git a/src/queries/balances.js b/src/queries/balances.js index 481e1f2d..9d978a6d 100644 --- a/src/queries/balances.js +++ b/src/queries/balances.js @@ -40,7 +40,7 @@ export const Juror = gql` ` export const FirstANJActivationMovement = gql` - query Juror($id: ID!) { + query JurorFirstANJActivationMovement($id: ID!) { juror(id: $id) { movements( where: { type: "Activation" } From 6f994df3239f0a9bfc2ba107abe897e340fa4c10 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Tue, 10 Mar 2020 18:03:17 -0300 Subject: [PATCH 02/18] Implement initial subscription exchange --- src/hooks/query-hooks.js | 2 - src/index.js | 21 ++--- .../{ => exchanges}/customFetchExchange.js | 41 ++++---- .../exchanges/customSubscriptionExchange.js | 93 +++++++++++++++++++ src/mock/mock-data.js | 64 ++++++++++++- 5 files changed, 183 insertions(+), 38 deletions(-) rename src/mock/{ => exchanges}/customFetchExchange.js (68%) create mode 100644 src/mock/exchanges/customSubscriptionExchange.js diff --git a/src/hooks/query-hooks.js b/src/hooks/query-hooks.js index 67231347..44fd2226 100644 --- a/src/hooks/query-hooks.js +++ b/src/hooks/query-hooks.js @@ -45,8 +45,6 @@ export function useFirstANJActivationQuery(jurorId, { pause = false }) { pause, }) - console.log('query result', result) - const { juror } = result.data || {} return juror ? juror.movements[0] : null diff --git a/src/index.js b/src/index.js index b63165a6..c30292b0 100644 --- a/src/index.js +++ b/src/index.js @@ -5,10 +5,12 @@ import { Provider as UrqlProvider, cacheExchange, debugExchange, - subscriptionExchange, } from 'urql' -import customFetchExchange from './mock/customFetchExchange' -import { SubscriptionClient } from 'subscriptions-transport-ws' +import fetchExchange from './mock/exchanges/customFetchExchange' +import subscriptionExchange, { + subscriptionClient, +} from './mock/exchanges/customSubscriptionExchange' + import { devtoolsExchange } from '@urql/devtools' import * as Sentry from '@sentry/browser' import App from './App' @@ -16,12 +18,7 @@ import endpoints from './endpoints' import env from './environment' import { getNetworkName } from './lib/web3-utils' -const [GRAPH_API_ENDPOINT_HTTP, GRAPH_API_ENDPOINT_WS] = endpoints() - -const subscriptionClient = new SubscriptionClient(GRAPH_API_ENDPOINT_WS, { - reconnect: true, - reconnectionAttempts: 10, -}) +const [GRAPH_API_ENDPOINT_HTTP] = endpoints() const client = createClient({ url: GRAPH_API_ENDPOINT_HTTP, @@ -29,10 +26,8 @@ const client = createClient({ debugExchange, devtoolsExchange, cacheExchange, - customFetchExchange, - subscriptionExchange({ - forwardSubscription: operation => subscriptionClient.request(operation), - }), + fetchExchange, + subscriptionExchange, ], }) diff --git a/src/mock/customFetchExchange.js b/src/mock/exchanges/customFetchExchange.js similarity index 68% rename from src/mock/customFetchExchange.js rename to src/mock/exchanges/customFetchExchange.js index 46db0a6c..0357ed74 100644 --- a/src/mock/customFetchExchange.js +++ b/src/mock/exchanges/customFetchExchange.js @@ -1,7 +1,7 @@ import { fetchExchange, makeResult } from 'urql' import { filter, make, merge, mergeMap, pipe, share, takeUntil } from 'wonka' -import env from '../environment' -import mockedData from './mock-data' +import env from '../../environment' +import mockedData from '../mock-data' const OPERATION_DEFINITION = 'OperationDefinition' @@ -43,32 +43,35 @@ export default function customFetchExchange(ref) { } } -// const getOperationName = query => { -// const node = query.definitions.find(node => { -// return node.kind === Kind.OPERATION_DEFINITION && node.name -// }) - -// return node !== undefined && node.name ? node.name.value : null -// } - const mockData = operation => { return make(({ next, complete }) => { const { name: queryName } = operation.query.definitions.find( node => node.kind === OPERATION_DEFINITION && node.name ) + const abortController = + typeof AbortController !== 'undefined' ? new AbortController() : undefined const convertedData = mockedData[queryName.value] - console.log('convertedData', convertedData) - console.log('next', next) - console.log('complete', complete) + Promise.resolve() + .then(() => + makeResult( + operation, + { + data: convertedData, + }, + null + ) + ) + .then(result => { + next(result) + complete() + }) - if (convertedData) { - const result = makeResult(operation, { data: convertedData }) - console.log('result', result) - next(result) + return () => { + if (abortController !== undefined) { + abortController.abort() + } } - - return complete() }) } diff --git a/src/mock/exchanges/customSubscriptionExchange.js b/src/mock/exchanges/customSubscriptionExchange.js new file mode 100644 index 00000000..e10050cc --- /dev/null +++ b/src/mock/exchanges/customSubscriptionExchange.js @@ -0,0 +1,93 @@ +import { makeResult, subscriptionExchange } from 'urql' +import { SubscriptionClient } from 'subscriptions-transport-ws' +import { filter, make, merge, mergeMap, pipe, share, takeUntil } from 'wonka' + +import env from '../../environment' +import mockedData from '../mock-data' +import endpoints from '../../endpoints' + +const OPERATION_DEFINITION = 'OperationDefinition' +const GRAPH_API_ENDPOINTS = endpoints() + +export const subscriptionClient = new SubscriptionClient( + GRAPH_API_ENDPOINTS[1], + { + reconnect: true, + reconnectionAttempts: 10, + } +) + +const DEFAULT_SUBSCRIPTION_EXCHANGE = subscriptionExchange({ + forwardSubscription: operation => subscriptionClient.request(operation), +}) + +const customSubscriptionExchange = ({ forward }) => { + const isSubscriptionOperation = operation => { + const { operationName } = operation + return operationName === 'subscription' + } + + return ops$ => { + const sharedOps$ = share(ops$) + const subscriptionResults$ = pipe( + sharedOps$, + filter(isSubscriptionOperation), + mergeMap(operation => { + const { key } = operation + const teardown$ = pipe( + sharedOps$, + filter(op => op.operationName === 'teardown' && op.key === key) + ) + + return pipe(mockData(operation), takeUntil(teardown$)) + }) + ) + + const forward$ = pipe( + sharedOps$, + filter(op => !isSubscriptionOperation(op)), + forward + ) + + return merge([subscriptionResults$, forward$]) + } +} + +const mockData = operation => { + return make(({ next, complete }) => { + console.log('subscription mock operation', operation) + + const { name: queryName } = operation.query.definitions.find( + node => node.kind === OPERATION_DEFINITION && node.name + ) + + const abortController = + typeof AbortController !== 'undefined' ? new AbortController() : undefined + const convertedData = mockedData[queryName.value] + + Promise.resolve() + .then(() => + makeResult( + operation, + { + data: convertedData, + }, + null + ) + ) + .then(result => { + next(result) + complete() + }) + + return () => { + if (abortController !== undefined) { + abortController.abort() + } + } + }) +} + +export default env('MOCK_TEST') + ? customSubscriptionExchange + : DEFAULT_SUBSCRIPTION_EXCHANGE diff --git a/src/mock/mock-data.js b/src/mock/mock-data.js index f4a7cc68..47425ffe 100644 --- a/src/mock/mock-data.js +++ b/src/mock/mock-data.js @@ -1,8 +1,64 @@ export default { + CourtConfig: { + courtConfig: { + id + currentTerm + termDuration + feeToken { + id + name + symbol + decimals + } + anjToken { + id + name + symbol + decimals + } + jurorFee + draftFee + settleFee + + evidenceTerms + commitTerms + revealTerms + appealTerms + appealConfirmationTerms + terms { + id + startTime + } + finalRoundReduction + firstRoundJurorsNumber + appealStepFactor + maxRegularAppealRounds + appealCollateralFactor + appealConfirmCollateralFactor + minActiveBalance + penaltyPct + modules { + type + address + } + terms { + id + startTime + } + } + } + } + JurorFirstANJActivationMovement: { - amount: '0', - effectiveTermId: '3', - createdAt: '903033', - type: '', + juror: { + movements: [ + { + amount: '0', + effectiveTermId: '111', + createdAt: '903033', + type: 'Activation', + }, + ], + }, }, } From 89a1e0f9386ec8667c23328d5ae0b2282971e033 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Wed, 11 Mar 2020 11:09:56 -0300 Subject: [PATCH 03/18] Add first dashboard mock states --- src/mock/mock-data.js | 106 +++++++++++++++++++---------------- src/networks.js | 5 ++ src/providers/CourtConfig.js | 7 +-- src/queries/appeals.js | 4 +- src/queries/balances.js | 4 +- src/queries/jurorDrafts.js | 2 +- 6 files changed, 70 insertions(+), 58 deletions(-) diff --git a/src/mock/mock-data.js b/src/mock/mock-data.js index 47425ffe..0f6c771e 100644 --- a/src/mock/mock-data.js +++ b/src/mock/mock-data.js @@ -1,54 +1,53 @@ +import { getCourtAddress } from '../networks' +import dayjs from 'dayjs' + export default { + // Court configuration CourtConfig: { courtConfig: { - id - currentTerm - termDuration - feeToken { - id - name - symbol - decimals - } - anjToken { - id - name - symbol - decimals - } - jurorFee - draftFee - settleFee - - evidenceTerms - commitTerms - revealTerms - appealTerms - appealConfirmationTerms - terms { - id - startTime - } - finalRoundReduction - firstRoundJurorsNumber - appealStepFactor - maxRegularAppealRounds - appealCollateralFactor - appealConfirmCollateralFactor - minActiveBalance - penaltyPct - modules { - type - address - } - terms { - id - startTime - } - } - } - } - + id: getCourtAddress(), + currentTerm: '20', + termDuration: 240, // 4 minutes + feeToken: { + id: '', + name: 'Dai stablecoin', + symbol: 'DAI', + decimals: 18, + }, + anjToken: { + id: '', + name: 'Aragon Network Juror Token', + symbol: 'ANJ', + decimals: 18, + }, + jurorFee: '1000000000000000000', + draftFee: '180000000000000000', + settleFee: '110000000000000000', + evidenceTerms: 21, + commitTerms: '6', + revealTerms: '6', + appealTerms: '6', + appealConfirmationTerms: '6', + terms: [ + { + startTime: dayjs().unix(), + }, + ], + finalRoundReduction: '5000', + firstRoundJurorsNumber: '3', + appealStepFactor: '3', + maxRegularAppealRounds: '4', + appealCollateralFactor: '30000', + appealConfirmCollateralFactor: '20000', + minActiveBalance: '100000000000000000000', + penaltyPct: '1000', + modules: [ + // type + // address + ], + }, + }, + // First ANJ activation movement JurorFirstANJActivationMovement: { juror: { movements: [ @@ -61,4 +60,15 @@ export default { ], }, }, + Balances: { juror: undefined }, + ANJWalletBalance: { anjbalance: '0' }, + AppealsByMaker: { + appeals: [], + }, + AppealsByTaker: { + appeals: [], + }, + JurorDraftsNotRewarded: { + juror: undefined, + }, } diff --git a/src/networks.js b/src/networks.js index 48d0d5a7..29cd2572 100644 --- a/src/networks.js +++ b/src/networks.js @@ -1,4 +1,5 @@ import environment from './environment' +import { getNetworkType } from './lib/web3-utils' const SUBGRAPH_NAME = environment('SUBGRAPH_NAME') @@ -16,3 +17,7 @@ export const networks = { }, main: { court: '0xee4650cBe7a2B23701D416f58b41D8B76b617797' }, } + +export const getCourtAddress = () => { + return networks[getNetworkType()].court +} diff --git a/src/providers/CourtConfig.js b/src/providers/CourtConfig.js index 405ee095..4e46fc39 100644 --- a/src/providers/CourtConfig.js +++ b/src/providers/CourtConfig.js @@ -1,16 +1,13 @@ import React, { useContext } from 'react' import PropTypes from 'prop-types' -import environment from '../environment' import { useCourtConfigSubscription } from '../hooks/subscription-hooks' -import { getNetworkType } from '../lib/web3-utils' -import { networks } from '../networks' +import { getCourtAddress } from '../networks' import { bigNum } from '../lib/math-utils' -const CHAIN_ID = environment('CHAIN_ID') const CourtConfigContext = React.createContext() function CourtConfigProvider({ children }) { - const courtAddress = networks[getNetworkType(CHAIN_ID)].court + const courtAddress = getCourtAddress() const courtConfig = useCourtConfigSubscription(courtAddress) const convertedCourtConfig = courtConfig diff --git a/src/queries/appeals.js b/src/queries/appeals.js index 44b8a432..07977516 100644 --- a/src/queries/appeals.js +++ b/src/queries/appeals.js @@ -1,7 +1,7 @@ import gql from 'graphql-tag' export const AppealsByMaker = gql` - subscription($maker: Bytes!, $settled: Boolean!) { + subscription AppealsByMaker($maker: Bytes!, $settled: Boolean!) { appeals(where: { maker: $maker, settled: $settled }) { id round { @@ -26,7 +26,7 @@ export const AppealsByMaker = gql` ` export const AppealsByTaker = gql` - subscription($taker: Bytes!, $settled: Boolean!) { + subscription AppealsByTaker($taker: Bytes!, $settled: Boolean!) { appeals(where: { taker: $taker, settled: $settled }) { id round { diff --git a/src/queries/balances.js b/src/queries/balances.js index 9d978a6d..842596b6 100644 --- a/src/queries/balances.js +++ b/src/queries/balances.js @@ -1,7 +1,7 @@ import gql from 'graphql-tag' export const ANJBalance = gql` - subscription ANJBalance($id: ID!) { + subscription ANJWalletBalance($id: ID!) { anjbalance(id: $id) { amount } @@ -9,7 +9,7 @@ export const ANJBalance = gql` ` export const Juror = gql` - subscription Juror($id: ID!, $from: BigInt!) { + subscription Balances($id: ID!, $from: BigInt!) { juror(id: $id) { activeBalance lockedBalance diff --git a/src/queries/jurorDrafts.js b/src/queries/jurorDrafts.js index 8730b657..ddb8b933 100644 --- a/src/queries/jurorDrafts.js +++ b/src/queries/jurorDrafts.js @@ -2,7 +2,7 @@ import gql from 'graphql-tag' // All juror drafts by `id` not yet rewarded export const JurorDraftsNotRewarded = gql` - subscription JurorDraft($id: ID!) { + subscription JurorDraftsNotRewarded($id: ID!) { juror(id: $id) { id drafts(where: { rewarded: false }) { From 16b04385d3acda5b92040657eb9c606ea1e298e7 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Mon, 16 Mar 2020 12:02:13 -0300 Subject: [PATCH 04/18] Add first dispute data --- src/App.js | 8 +- .../Dashboard/DashboardStateProvider.js | 2 + src/{ => components}/GlobalErrorHandler.js | 12 +- src/exchanges.js | 30 ++++ src/index.js | 11 +- src/mock-data.js | 58 ------- src/mock/data/Balances.js | 34 +++++ src/mock/data/CourtConfig.js | 58 +++++++ src/mock/data/Disputes.js | 144 ++++++++++++++++++ src/mock/data/index.js | 78 ++++++++++ .../exchanges/customSubscriptionExchange.js | 93 ----------- .../{customFetchExchange.js => index.js} | 38 ++--- src/mock/helper.js | 10 ++ src/mock/mock-data.js | 74 --------- src/mock/types.js | 26 ++++ src/queries/disputes.js | 24 +-- src/queries/jurorDrafts.js | 7 +- src/utils/dispute-utils.js | 1 + 18 files changed, 425 insertions(+), 283 deletions(-) rename src/{ => components}/GlobalErrorHandler.js (85%) create mode 100644 src/exchanges.js delete mode 100644 src/mock-data.js create mode 100644 src/mock/data/Balances.js create mode 100644 src/mock/data/CourtConfig.js create mode 100644 src/mock/data/Disputes.js create mode 100644 src/mock/data/index.js delete mode 100644 src/mock/exchanges/customSubscriptionExchange.js rename src/mock/exchanges/{customFetchExchange.js => index.js} (59%) create mode 100644 src/mock/helper.js delete mode 100644 src/mock/mock-data.js create mode 100644 src/mock/types.js diff --git a/src/App.js b/src/App.js index 89822d4e..20124010 100644 --- a/src/App.js +++ b/src/App.js @@ -2,15 +2,15 @@ import React from 'react' import { BrowserRouter } from 'react-router-dom' import { Main, ToastHub } from '@aragon/ui' import theme from './theme-court' +import AppLoader from './components/AppLoader' +import GlobalErrorHandler from './components/GlobalErrorHandler' import MainView from './components/MainView' +import OnboardingLoader from './components/OnboardingLoader' +import Routes from './Routes' import { ActivityProvider } from './components/Activity/ActivityProvider' import { CourtClockProvider } from './providers/CourtClock' import { CourtConfigProvider } from './providers/CourtConfig' import { WalletProvider } from './providers/Wallet' -import AppLoader from './components/AppLoader' -import OnboardingLoader from './components/OnboardingLoader' -import Routes from './Routes' -import GlobalErrorHandler from './GlobalErrorHandler' function App() { return ( diff --git a/src/components/Dashboard/DashboardStateProvider.js b/src/components/Dashboard/DashboardStateProvider.js index 44039bf4..4a4e60b5 100644 --- a/src/components/Dashboard/DashboardStateProvider.js +++ b/src/components/Dashboard/DashboardStateProvider.js @@ -38,6 +38,8 @@ function WithSubscription({ Provider, connectedAccount, children }) { errors: balanceErrors, } = useJurorBalancesSubscription(connectedAccount) + console.log('balances', balances?.activeBalance.toString()) + // Appeals const { appeals, diff --git a/src/GlobalErrorHandler.js b/src/components/GlobalErrorHandler.js similarity index 85% rename from src/GlobalErrorHandler.js rename to src/components/GlobalErrorHandler.js index 08ab613d..0d896b89 100644 --- a/src/GlobalErrorHandler.js +++ b/src/components/GlobalErrorHandler.js @@ -1,13 +1,13 @@ import React from 'react' import PropTypes from 'prop-types' import * as Sentry from '@sentry/browser' -import GenericError from './components/Errors/GenericError' -import GlobalErrorScreen from './components/Errors/GlobalErrorScreen' -import DisputeNotFoundError from './components/Disputes/DisputeNotFoundError' +import GenericError from './Errors/GenericError' +import GlobalErrorScreen from './Errors/GlobalErrorScreen' +import DisputeNotFoundError from './Disputes/DisputeNotFoundError' -import env from './environment' -import { DisputeNotFound } from './errors' -import { getNetworkType } from './lib/web3-utils' +import env from '../environment' +import { DisputeNotFound } from '../errors' +import { getNetworkType } from '../lib/web3-utils' const SENTRY_DSN = env('SENTRY_DNS') diff --git a/src/exchanges.js b/src/exchanges.js new file mode 100644 index 00000000..b2285873 --- /dev/null +++ b/src/exchanges.js @@ -0,0 +1,30 @@ +import { fetchExchange, subscriptionExchange } from 'urql' +import { SubscriptionClient } from 'subscriptions-transport-ws' + +import env from './environment' +import endpoints from './endpoints' +import { mockFetchExchange, mockSubscriptionExchange } from './mock/exchanges/' + +const DEFAULT_FETCH_EXCHANGE = fetchExchange +const DEFAULT_SUBSCRIPTION_EXCHANGE = subscriptionExchange({ + forwardSubscription: operation => subscriptionClient.request(operation), +}) +const GRAPH_API_ENDPOINTS = endpoints() + +export const subscriptionClient = new SubscriptionClient( + GRAPH_API_ENDPOINTS[1], + { + reconnect: true, + reconnectionAttempts: 10, + } +) + +export function getFetchExchange() { + return env('MOCK_TEST') ? mockFetchExchange : DEFAULT_FETCH_EXCHANGE +} + +export function getSubscriptionExchange() { + return env('MOCK_TEST') + ? mockSubscriptionExchange + : DEFAULT_SUBSCRIPTION_EXCHANGE +} diff --git a/src/index.js b/src/index.js index 577d7d82..f8365204 100644 --- a/src/index.js +++ b/src/index.js @@ -6,10 +6,11 @@ import { cacheExchange, debugExchange, } from 'urql' -import fetchExchange from './mock/exchanges/customFetchExchange' -import subscriptionExchange, { +import { + getFetchExchange, + getSubscriptionExchange, subscriptionClient, -} from './mock/exchanges/customSubscriptionExchange' +} from './exchanges' import { devtoolsExchange } from '@urql/devtools' import * as Sentry from '@sentry/browser' @@ -26,8 +27,8 @@ const client = createClient({ debugExchange, devtoolsExchange, cacheExchange, - fetchExchange, - subscriptionExchange, + getFetchExchange(), + getSubscriptionExchange(), ], }) diff --git a/src/mock-data.js b/src/mock-data.js deleted file mode 100644 index 2955df0e..00000000 --- a/src/mock-data.js +++ /dev/null @@ -1,58 +0,0 @@ -export const balances = { - wallet: { amount: '3.304,76', value: '3.300' }, - inactive: { amount: '3.304,76', tokenSymbol: 'ANJ', value: '3.300' }, - active: { amount: '3.304,76', value: '3.300' }, - rewards: { amount: '3.304,76', value: '3.300' }, -} - -export const latestActivity = [ - { - account: '0x8401Eb5ff34cc943f096A32EF3d5113FEbE8D4Eb', - action: 'Started', - target: { label: 'review evidence', link: 'url' }, - date: '26/11/19 AT 16:00', - }, - { - account: '0xb4124cEB3451635DAcedd11767f004d8a28c6eE7', - action: 'Comitted their', - target: { label: 'vote', link: 'url' }, - date: '26/11/19 AT 16:00', - }, - { - account: '0x49C01b61Aa3e4cD4C4763c78EcFE75888b49ef50', - action: 'Executed', - target: { label: 'ruling', link: 'url' }, - date: '26/11/19 AT 16:00', - }, -] - -export const tasks = [ - { - taskName: 'Commit Vote', - disputeId: 12, - status: 'open', - juror: '0x593e1F9809658d0c92e9f092cF01Aad7D0d734f3', - dueDate: 1578928467000, - }, - { - taskName: 'Reveal vote', - disputeId: 15, - status: 'open', - juror: '0x099278297012066d61c9505132b3Aa71F625E414', - dueDate: 1578928467000, - }, - { - taskName: 'Commit Vote', - disputeId: 20, - status: 'open', - juror: '0x593e1F9809658d0c92e9f092cF01Aad7D0d734f3', - dueDate: 1578928467000, - }, - { - taskName: 'Commit vote', - disputeId: 14, - status: 'open', - juror: '0x099278297012066d61c9505132b3Aa71F625E414', - dueDate: 1578928467000, - }, -] diff --git a/src/mock/data/Balances.js b/src/mock/data/Balances.js new file mode 100644 index 00000000..432646da --- /dev/null +++ b/src/mock/data/Balances.js @@ -0,0 +1,34 @@ +import { bigExp } from '../helper' +import { ANJMovementType } from '../types' + +export const jurorMovements = [ + { + amount: bigExp('20'), + effectiveTermId: 3, + createdAt: '1', + type: ANJMovementType.Activation, + }, + { + amount: bigExp('20'), + effectiveTermId: 3, + createdAt: '1', + type: ANJMovementType.Stake, + }, +] + +export const jurorBalances = { + activeBalance: bigExp('4030'), + lockedBalance: bigExp('400'), + availableBalance: bigExp('5403'), + deactivationBalance: bigExp('2453'), + treasuryTokens: [], + movements: jurorMovements, +} + +export const jurorWalletBalance = { amount: bigExp('1000') } + +function generateJurorsData() { + +} + +export const drafts = diff --git a/src/mock/data/CourtConfig.js b/src/mock/data/CourtConfig.js new file mode 100644 index 00000000..ebf2a74d --- /dev/null +++ b/src/mock/data/CourtConfig.js @@ -0,0 +1,58 @@ +import { getCourtAddress } from '../../networks' +import { bigExp } from '../helper' +import dayjs from 'dayjs' + +const TERM_DURATION = 240 // 4 minutes +const CURRENT_TERM = 10 +const COURT_START = dayjs() // Court started 10 terms ago + .subtract(TERM_DURATION * CURRENT_TERM, 'second') + .unix() + +const anjToken = { + id: '', + name: 'Aragon Network Juror Token', + symbol: 'ANJ', + decimals: 18, +} + +const feeToken = { + id: '', + name: 'Dai stablecoin', + symbol: 'DAI', + decimals: 18, +} + +const courtConfig = { + id: getCourtAddress(), + currentTerm: CURRENT_TERM, + termDuration: TERM_DURATION, // 4 minutes + anjToken, + feeToken, + jurorFee: bigExp('10'), + draftFee: bigExp('18', 16), + settleFee: bigExp('1', 17), + evidenceTerms: 21, + commitTerms: '6', + revealTerms: '6', + appealTerms: '6', + appealConfirmationTerms: '6', + terms: [ + { + startTime: COURT_START, + }, + ], + finalRoundReduction: '5000', + firstRoundJurorsNumber: '3', + appealStepFactor: '3', + maxRegularAppealRounds: '3', + appealCollateralFactor: '30000', + appealConfirmCollateralFactor: '20000', + minActiveBalance: bigExp('100'), + penaltyPct: '1000', + modules: [ + // type + // address + ], +} + +export default courtConfig diff --git a/src/mock/data/Disputes.js b/src/mock/data/Disputes.js new file mode 100644 index 00000000..c7dab386 --- /dev/null +++ b/src/mock/data/Disputes.js @@ -0,0 +1,144 @@ +import { hash256 } from '../../lib/web3-utils' +import { DisputeState, AdjudicationState } from '../types' +import courtConfig from './CourtConfig' +import dayjs from 'dayjs' +import { accounts } from '../helper' +import { PCT_BASE } from '../../utils/dispute-utils' +import { bigNum } from '../../lib/math-utils' + +const NUMBER_OF_DISPUTES = 5 +const CREATE_TERM_ID = courtConfig.currentTerm + +const PAST_DRAFT_TERM_ID = courtConfig.currentTerm - 4 +const DRAFT_TERM_ID = CREATE_TERM_ID + 4 + +const ROUNDS = { + FIRST_NOT_DRAFTED: { + id: '0', + state: AdjudicationState.Invalid, + number: '0', + draftTermId: DRAFT_TERM_ID, + jurorsNumber: 0, + settledPenalties: false, + delayedTerms: 0, + selectedJurors: 0, + coherentJurors: 0, + collectedTokens: 0, + createdAt: 0, + jurors: [], + vote: null, + appeal: null, + }, + FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL: { + id: '0', + state: AdjudicationState.Committing, + number: '0', + draftTermId: PAST_DRAFT_TERM_ID, + jurorsNumber: 3, + settledPenalties: false, + jurorFees: courtConfig.jurorFee, + delayedTerms: 3, + selectedJurors: 3, + coherentJurors: 0, + collectedTokens: 0, + createdAt: 0, + jurors: accounts.slice(0, 3).map(account => ({ + juror: { id: account, vote: { commitment: '', outcome: 0 } }, + weight: 1, + locked: bigNum(courtConfig.minActiveBalance) + .mul(courtConfig.penaltyPct) + .div(PCT_BASE), + })), + vote: null, + appeal: null, + }, +} + +const DISPUTES_SPECIFIC_DATA = [ + { + state: DisputeState.Ruled, + metadata: 'Dispute finished', + rounds: [ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL], + }, + { + state: DisputeState.Adjudicating, + metadata: 'Dispute appealed', + rounds: [ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL], + }, + { + state: DisputeState.Adjudicating, + metadata: 'Dispute in last round', + rounds: [ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL], + }, + { + state: DisputeState.Adjudicating, + metadata: 'Dispute in first adjudication round (jurors already drafted)', + rounds: [ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL], + }, + { + state: DisputeState.Evidence, + metadata: 'Dispute in evidence submission', + rounds: [ROUNDS.FIRST_NOT_DRAFTED], + }, +] + +function generateDisputes() { + const disputes = [] + for (let i = 0; i < NUMBER_OF_DISPUTES; i++) { + const { state, metadata, rounds } = DISPUTES_SPECIFIC_DATA[i] + const dispute = { + id: String(i), + txHash: hash256(i), + createTermId: courtConfig.currentTerm, + createdAt: dayjs().unix(), + possibleRulings: 2, + state, + metadata, + rounds, + lastRoundId: rounds.length - 1, + } + + disputes.push(dispute) + } + + return disputes.reverse() +} + +// lastRoundId +// createdAt +// rounds { +// id +// state +// number +// draftTermId +// jurorsNumber +// settledPenalties +// jurorFees +// delayedTerms +// selectedJurors +// coherentJurors +// collectedTokens +// createdAt +// jurors { +// juror { +// id +// } +// commitment +// outcome +// } +// vote { +// id +// winningOutcome +// } +// appeal { +// id +// maker +// appealedRuling +// taker +// opposedRuling +// settled +// createdAt +// } +// } + +export default generateDisputes() diff --git a/src/mock/data/index.js b/src/mock/data/index.js new file mode 100644 index 00000000..4a48fe6f --- /dev/null +++ b/src/mock/data/index.js @@ -0,0 +1,78 @@ +import { bigExp } from '../helper' +import courtConfig from './CourtConfig' +import disputes from './Disputes' +import { jurorMovements, jurorBalances, jurorWalletBalance } from './Balances' + +export default { + // Court configuration + CourtConfig: () => ({ + courtConfig, + }), + // Dashboard state + JurorFirstANJActivationMovement: () => ({ + juror: { + movements: jurorMovements[0], + }, + }), + Balances: ({ id }) => ({ + juror: jurorBalances, + }), + ANJWalletBalance: ({ id }) => ({ anjbalance: jurorWalletBalance }), + CurrentTermJurorDrafts: ({ id }) => ({ + drafts: [], + }), + AppealsByMaker: ({ maker }) => ({ + appeals: [], + }), + AppealsByTaker: ({ taker }) => ({ + appeals: [], + }), + JurorDraftsNotRewarded: ({ id }) => ({ + juror: { + id: '', + drafts: [ + { + weight: 3, + outcome: 4, + round: { + number: '1', + coherentJurors: '1', + collectedTokens: bigExp('20'), + jurorFees: bigExp('10'), + settledPenalties: true, + dispute: { + id: '1', + finalRuling: 4, + }, + }, + }, + ], + }, + }), + JurorDraftRewarded: ({ id }) => ({ + juror: { + id: '', + drafts: [], + }, + }), + // Disputes + AllDisputes: () => ({ + disputes, + }), + SingleDispute: ({ id }) => { + const dispute = disputes.find(d => d.id === id) + return { + dispute, + } + }, + JurorDrafts: ({ id }) => ({ + juror: { + id: '', + drafts: [], + }, + }), + // Tasks + OpenTasks: () => ({ + adjudicationRounds: [], + }), +} diff --git a/src/mock/exchanges/customSubscriptionExchange.js b/src/mock/exchanges/customSubscriptionExchange.js deleted file mode 100644 index e10050cc..00000000 --- a/src/mock/exchanges/customSubscriptionExchange.js +++ /dev/null @@ -1,93 +0,0 @@ -import { makeResult, subscriptionExchange } from 'urql' -import { SubscriptionClient } from 'subscriptions-transport-ws' -import { filter, make, merge, mergeMap, pipe, share, takeUntil } from 'wonka' - -import env from '../../environment' -import mockedData from '../mock-data' -import endpoints from '../../endpoints' - -const OPERATION_DEFINITION = 'OperationDefinition' -const GRAPH_API_ENDPOINTS = endpoints() - -export const subscriptionClient = new SubscriptionClient( - GRAPH_API_ENDPOINTS[1], - { - reconnect: true, - reconnectionAttempts: 10, - } -) - -const DEFAULT_SUBSCRIPTION_EXCHANGE = subscriptionExchange({ - forwardSubscription: operation => subscriptionClient.request(operation), -}) - -const customSubscriptionExchange = ({ forward }) => { - const isSubscriptionOperation = operation => { - const { operationName } = operation - return operationName === 'subscription' - } - - return ops$ => { - const sharedOps$ = share(ops$) - const subscriptionResults$ = pipe( - sharedOps$, - filter(isSubscriptionOperation), - mergeMap(operation => { - const { key } = operation - const teardown$ = pipe( - sharedOps$, - filter(op => op.operationName === 'teardown' && op.key === key) - ) - - return pipe(mockData(operation), takeUntil(teardown$)) - }) - ) - - const forward$ = pipe( - sharedOps$, - filter(op => !isSubscriptionOperation(op)), - forward - ) - - return merge([subscriptionResults$, forward$]) - } -} - -const mockData = operation => { - return make(({ next, complete }) => { - console.log('subscription mock operation', operation) - - const { name: queryName } = operation.query.definitions.find( - node => node.kind === OPERATION_DEFINITION && node.name - ) - - const abortController = - typeof AbortController !== 'undefined' ? new AbortController() : undefined - const convertedData = mockedData[queryName.value] - - Promise.resolve() - .then(() => - makeResult( - operation, - { - data: convertedData, - }, - null - ) - ) - .then(result => { - next(result) - complete() - }) - - return () => { - if (abortController !== undefined) { - abortController.abort() - } - } - }) -} - -export default env('MOCK_TEST') - ? customSubscriptionExchange - : DEFAULT_SUBSCRIPTION_EXCHANGE diff --git a/src/mock/exchanges/customFetchExchange.js b/src/mock/exchanges/index.js similarity index 59% rename from src/mock/exchanges/customFetchExchange.js rename to src/mock/exchanges/index.js index 0357ed74..39bf8feb 100644 --- a/src/mock/exchanges/customFetchExchange.js +++ b/src/mock/exchanges/index.js @@ -1,27 +1,30 @@ -import { fetchExchange, makeResult } from 'urql' +import { makeResult } from 'urql' import { filter, make, merge, mergeMap, pipe, share, takeUntil } from 'wonka' -import env from '../../environment' -import mockedData from '../mock-data' +import mockData from '../data' const OPERATION_DEFINITION = 'OperationDefinition' -export default function customFetchExchange(ref) { - if (!env('MOCK_TEST')) { - return fetchExchange(ref) - } +// Fetch exchange +export const mockFetchExchange = ({ forward }) => { + return handleOperation('query', forward) +} - const { forward } = ref +// Subscription exchange +export const mockSubscriptionExchange = ({ forward }) => { + return handleOperation('subscription', forward) +} - const isOperationQuery = operation => { +function handleOperation(operationType, forward) { + const isDesiredOperation = operation => { const { operationName } = operation - return operationName === 'query' + return operationName === operationType } return ops$ => { const sharedOps$ = share(ops$) - const fetchResults$ = pipe( + const subscriptionResults$ = pipe( sharedOps$, - filter(isOperationQuery), + filter(isDesiredOperation), mergeMap(operation => { const { key } = operation const teardown$ = pipe( @@ -29,21 +32,21 @@ export default function customFetchExchange(ref) { filter(op => op.operationName === 'teardown' && op.key === key) ) - return pipe(mockData(operation), takeUntil(teardown$)) + return pipe(convertMockedData(operation), takeUntil(teardown$)) }) ) const forward$ = pipe( sharedOps$, - filter(op => !isOperationQuery(op)), + filter(op => !isDesiredOperation(op)), forward ) - return merge([fetchResults$, forward$]) + return merge([subscriptionResults$, forward$]) } } -const mockData = operation => { +const convertMockedData = operation => { return make(({ next, complete }) => { const { name: queryName } = operation.query.definitions.find( node => node.kind === OPERATION_DEFINITION && node.name @@ -51,7 +54,8 @@ const mockData = operation => { const abortController = typeof AbortController !== 'undefined' ? new AbortController() : undefined - const convertedData = mockedData[queryName.value] + + const convertedData = mockData[queryName.value](operation.variables) Promise.resolve() .then(() => diff --git a/src/mock/helper.js b/src/mock/helper.js new file mode 100644 index 00000000..ae18edca --- /dev/null +++ b/src/mock/helper.js @@ -0,0 +1,10 @@ +export const bigExp = (x, y = 18) => `${x}${''.padEnd(y, '0')}` + +export const accounts = [ + '0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1', + '0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0', + '0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b', + '0xE11BA2b4D45Eaed5996Cd0823791E0C93114882d', + '0xd03ea8624C8C5987235048901fB614fDcA89b117', + '0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC', +] diff --git a/src/mock/mock-data.js b/src/mock/mock-data.js deleted file mode 100644 index 0f6c771e..00000000 --- a/src/mock/mock-data.js +++ /dev/null @@ -1,74 +0,0 @@ -import { getCourtAddress } from '../networks' -import dayjs from 'dayjs' - -export default { - // Court configuration - CourtConfig: { - courtConfig: { - id: getCourtAddress(), - currentTerm: '20', - termDuration: 240, // 4 minutes - feeToken: { - id: '', - name: 'Dai stablecoin', - symbol: 'DAI', - decimals: 18, - }, - anjToken: { - id: '', - name: 'Aragon Network Juror Token', - symbol: 'ANJ', - decimals: 18, - }, - jurorFee: '1000000000000000000', - draftFee: '180000000000000000', - settleFee: '110000000000000000', - evidenceTerms: 21, - commitTerms: '6', - revealTerms: '6', - appealTerms: '6', - appealConfirmationTerms: '6', - terms: [ - { - startTime: dayjs().unix(), - }, - ], - finalRoundReduction: '5000', - firstRoundJurorsNumber: '3', - appealStepFactor: '3', - maxRegularAppealRounds: '4', - appealCollateralFactor: '30000', - appealConfirmCollateralFactor: '20000', - minActiveBalance: '100000000000000000000', - penaltyPct: '1000', - modules: [ - // type - // address - ], - }, - }, - // First ANJ activation movement - JurorFirstANJActivationMovement: { - juror: { - movements: [ - { - amount: '0', - effectiveTermId: '111', - createdAt: '903033', - type: 'Activation', - }, - ], - }, - }, - Balances: { juror: undefined }, - ANJWalletBalance: { anjbalance: '0' }, - AppealsByMaker: { - appeals: [], - }, - AppealsByTaker: { - appeals: [], - }, - JurorDraftsNotRewarded: { - juror: undefined, - }, -} diff --git a/src/mock/types.js b/src/mock/types.js new file mode 100644 index 00000000..4542289c --- /dev/null +++ b/src/mock/types.js @@ -0,0 +1,26 @@ +export const ANJMovementType = { + Stake: 'Stake', + Unstake: 'Unstake', + Activation: 'Activation', + Deactivation: 'Deactivation', + Lock: 'Lock', + Unlock: 'Unlock', + Reward: 'Reward', + Slash: 'Slash', +} + +export const DisputeState = { + Evidence: 'Evidence', + Drafting: 'Drafting', + Adjudicating: 'Adjudicating', + Ruled: 'Ruled', +} + +export const AdjudicationState = { + Invalid: 'Invalid', + Committing: 'Committing', + Revealing: 'Revealing', + Appealing: 'Appealing', + ConfirmingAppeal: 'ConfirmingAppeal', + Ended: 'Ended', +} diff --git a/src/queries/disputes.js b/src/queries/disputes.js index 6264df2b..6b4f0dcc 100644 --- a/src/queries/disputes.js +++ b/src/queries/disputes.js @@ -4,27 +4,16 @@ export const AllDisputes = gql` subscription AllDisputes($limit: Int) { disputes(first: $limit, orderBy: createdAt, orderDirection: desc) { id - txHash - createTermId - possibleRulings finalRuling lastRoundId state metadata - createdAt rounds { id state number draftTermId - jurorsNumber - settledPenalties - jurorFees delayedTerms - selectedJurors - coherentJurors - collectedTokens - createdAt jurors { juror { id @@ -32,18 +21,9 @@ export const AllDisputes = gql` commitment outcome } - vote { - id - winningOutcome - } + appeal { id - maker - appealedRuling - taker - opposedRuling - settled - createdAt } } } @@ -51,7 +31,7 @@ export const AllDisputes = gql` ` export const SingleDispute = gql` - subscription Dispute($id: ID!) { + subscription SingleDispute($id: ID!) { dispute(id: $id) { id txHash diff --git a/src/queries/jurorDrafts.js b/src/queries/jurorDrafts.js index ddb8b933..0786d307 100644 --- a/src/queries/jurorDrafts.js +++ b/src/queries/jurorDrafts.js @@ -8,8 +8,6 @@ export const JurorDraftsNotRewarded = gql` drafts(where: { rewarded: false }) { id weight - locked - rewarded outcome round { number @@ -30,7 +28,7 @@ export const JurorDraftsNotRewarded = gql` // First juror draft already rewarded export const JurorDraftRewarded = gql` - query JurorDraft($id: ID!) { + query JurorDraftRewarded($id: ID!) { juror(id: $id) { id drafts(where: { rewarded: true }, first: 1) { @@ -42,7 +40,7 @@ export const JurorDraftRewarded = gql` // Jurors drafts by `id` for current term export const CurrentTermJurorDrafts = gql` - subscription JurorDrafts($id: ID!, $from: BigInt!) { + subscription CurrentTermJurorDrafts($id: ID!, $from: BigInt!) { juror(id: $id) { id drafts(where: { createdAt_gt: $from }) { @@ -54,6 +52,7 @@ export const CurrentTermJurorDrafts = gql` ` // All juror drafts by `id` +// Useful query to know all disputes that the juror by `$id` is part of export const JurorDrafts = gql` query JurorDrafts($id: ID!) { juror(id: $id) { diff --git a/src/utils/dispute-utils.js b/src/utils/dispute-utils.js index 621ee3a6..6fab466c 100644 --- a/src/utils/dispute-utils.js +++ b/src/utils/dispute-utils.js @@ -9,6 +9,7 @@ export const FINAL_ROUND_WEIGHT_PRECISION = bigNum(1000) export const PCT_BASE = bigNum(10000) export const transformResponseDisputeAttributes = dispute => { + console.log('transforming dispute:', dispute) const transformedDispute = { ...dispute, createdAt: parseInt(dispute.createdAt, 10) * 1000, From 850c0e8df3efaaaee851c5fcf8e4064c1ba0b6c2 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Mon, 23 Mar 2020 13:22:43 -0300 Subject: [PATCH 05/18] Draft jurors --- package.json | 7 ++- src/hooks/query-hooks.js | 8 +-- src/hooks/subscription-hooks.js | 29 ++++----- src/mock/data/Balances.js | 34 ---------- src/mock/data/Disputes.js | 39 +++++------- src/mock/data/Jurors.js | 45 ++++++++++++++ src/mock/data/index.js | 106 +++++++++++++++++++++++--------- src/mock/helper.js | 14 +++-- src/mock/models/Court.js | 73 ++++++++++++++++++++++ src/queries/balances.js | 10 +-- src/queries/jurorDrafts.js | 12 ++-- 11 files changed, 253 insertions(+), 124 deletions(-) delete mode 100644 src/mock/data/Balances.js create mode 100644 src/mock/data/Jurors.js create mode 100644 src/mock/models/Court.js diff --git a/package.json b/package.json index a6dabfa0..ed29a126 100644 --- a/package.json +++ b/package.json @@ -37,17 +37,18 @@ "scripts": { "start": "npm run sync-assets && REACT_APP_BUILD=$(git log --pretty=format:'%h' -n 1) react-app-rewired start", "start:rpc": "REACT_APP_CHAIN_ID=1337 npm run start ", + "start:rpc:mock": "REACT_APP_MOCK_TEST=1 npm run start:rpc", "start:mainnet": "REACT_APP_CHAIN_ID=1 npm run start", + "start:mainnet:mock": "REACT_APP_MOCK_TEST=1 npm run start:mainnet", "start:ropsten": "REACT_APP_CHAIN_ID=3 npm run start", + "start:ropsten:mock": "REACT_APP_MOCK_TEST=1 npm run start:ropsten", "start:rinkeby": "REACT_APP_CHAIN_ID=4 npm run start", + "start:rinkeby:mock": "REACT_APP_MOCK_TEST=1 npm run start:rinkeby", "build": "./scripts/build.sh", "build:rpc": "REACT_APP_CHAIN_ID=1337 npm run build", "build:mainnet": "REACT_APP_CHAIN_ID=1 npm run build", "build:ropsten": "REACT_APP_CHAIN_ID=3 npm run build", "build:rinkeby": "REACT_APP_CHAIN_ID=4 npm run build", - "mock:rpc": "REACT_APP_MOCK_TEST=1 npm run start:rpc", - "mock:mainnet": "REACT_APP_MOCK_TEST=1 npm run start:mainnet", - "mock:rinkeby": "REACT_APP_MOCK_TEST=1 npm run start:rinkeby", "lint": "eslint ./src", "test": "react-app-rewired test", "eject": "react-scripts eject", diff --git a/src/hooks/query-hooks.js b/src/hooks/query-hooks.js index 44fd2226..36d000d0 100644 --- a/src/hooks/query-hooks.js +++ b/src/hooks/query-hooks.js @@ -1,7 +1,7 @@ import { useQuery } from 'urql' -import { JurorDrafts, JurorDraftRewarded } from '../queries/jurorDrafts' -import { FirstANJActivationMovement } from '../queries/balances' +import { JurorFirstANJActivationMovement } from '../queries/balances' +import { JurorDrafts, JurorDraftsRewarded } from '../queries/jurorDrafts' export function useJurorDraftQuery(jurorId) { const [result] = useQuery({ @@ -27,7 +27,7 @@ export function useJurorDraftQuery(jurorId) { */ export function useJurorDraftRewardedQuery(jurorId) { const [{ data }] = useQuery({ - query: JurorDraftRewarded, + query: JurorDraftsRewarded, variables: { id: jurorId.toLowerCase() }, }) @@ -40,7 +40,7 @@ export function useJurorDraftRewardedQuery(jurorId) { export function useFirstANJActivationQuery(jurorId, { pause = false }) { const [result] = useQuery({ - query: FirstANJActivationMovement, + query: JurorFirstANJActivationMovement, variables: { id: jurorId.toLowerCase() }, pause, }) diff --git a/src/hooks/subscription-hooks.js b/src/hooks/subscription-hooks.js index edf1e544..d00508ef 100644 --- a/src/hooks/subscription-hooks.js +++ b/src/hooks/subscription-hooks.js @@ -1,28 +1,29 @@ import { useMemo } from 'react' import { useSubscription } from 'urql' -import { dayjs } from '../utils/date-utils' import { useCourtConfig } from '../providers/CourtConfig' -import { ANJBalance, Juror } from '../queries/balances' + +// queries +import { OpenTasks } from '../queries/tasks' import { CourtConfig } from '../queries/court' +import { AllDisputes, SingleDispute } from '../queries/disputes' import { AppealsByMaker, AppealsByTaker } from '../queries/appeals' -import { - JurorDraftsNotRewarded, - CurrentTermJurorDrafts, -} from '../queries/jurorDrafts' -import { SingleDispute, AllDisputes } from '../queries/disputes' -import { OpenTasks } from '../queries/tasks' -import { transformResponseDisputeAttributes } from '../utils/dispute-utils' +import { JurorANJBalances, JurorANJWalletBalance } from '../queries/balances' +import { JurorDraftsFrom, JurorDraftsNotRewarded } from '../queries/jurorDrafts' + +// utils import { bigNum } from '../lib/math-utils' -import { transformJurorDataAttributes } from '../utils/juror-draft-utils' -import { transformAppealDataAttributes } from '../utils/appeal-utils' +import { dayjs } from '../utils/date-utils' import { groupMovements } from '../utils/anj-movement-utils' +import { transformAppealDataAttributes } from '../utils/appeal-utils' +import { transformJurorDataAttributes } from '../utils/juror-draft-utils' +import { transformResponseDisputeAttributes } from '../utils/dispute-utils' const NO_AMOUNT = bigNum(0) // Subscription to get juror's wallet balance function useANJBalance(jurorId) { const [{ data, error }] = useSubscription({ - query: ANJBalance, + query: JurorANJWalletBalance, variables: { id: jurorId.toLowerCase() }, }) @@ -38,7 +39,7 @@ function useJuror(jurorId) { .unix() const [{ data, error }] = useSubscription({ - query: Juror, + query: JurorANJBalances, variables: { id: jurorId.toLowerCase(), from: yesterday }, }) @@ -184,7 +185,7 @@ export function useCurrentTermJurorDraftsSubscription( pause ) { const [result] = useSubscription({ - query: CurrentTermJurorDrafts, + query: JurorDraftsFrom, variables: { id: jurorId.toLowerCase(), from: termStartTime }, pause, }) diff --git a/src/mock/data/Balances.js b/src/mock/data/Balances.js deleted file mode 100644 index 432646da..00000000 --- a/src/mock/data/Balances.js +++ /dev/null @@ -1,34 +0,0 @@ -import { bigExp } from '../helper' -import { ANJMovementType } from '../types' - -export const jurorMovements = [ - { - amount: bigExp('20'), - effectiveTermId: 3, - createdAt: '1', - type: ANJMovementType.Activation, - }, - { - amount: bigExp('20'), - effectiveTermId: 3, - createdAt: '1', - type: ANJMovementType.Stake, - }, -] - -export const jurorBalances = { - activeBalance: bigExp('4030'), - lockedBalance: bigExp('400'), - availableBalance: bigExp('5403'), - deactivationBalance: bigExp('2453'), - treasuryTokens: [], - movements: jurorMovements, -} - -export const jurorWalletBalance = { amount: bigExp('1000') } - -function generateJurorsData() { - -} - -export const drafts = diff --git a/src/mock/data/Disputes.js b/src/mock/data/Disputes.js index c7dab386..c062a066 100644 --- a/src/mock/data/Disputes.js +++ b/src/mock/data/Disputes.js @@ -1,14 +1,10 @@ +import courtConfig from './CourtConfig' + import { hash256 } from '../../lib/web3-utils' +import { dayjs } from '../../utils/date-utils' import { DisputeState, AdjudicationState } from '../types' -import courtConfig from './CourtConfig' -import dayjs from 'dayjs' -import { accounts } from '../helper' -import { PCT_BASE } from '../../utils/dispute-utils' -import { bigNum } from '../../lib/math-utils' -const NUMBER_OF_DISPUTES = 5 const CREATE_TERM_ID = courtConfig.currentTerm - const PAST_DRAFT_TERM_ID = courtConfig.currentTerm - 4 const DRAFT_TERM_ID = CREATE_TERM_ID + 4 @@ -42,50 +38,45 @@ const ROUNDS = { coherentJurors: 0, collectedTokens: 0, createdAt: 0, - jurors: accounts.slice(0, 3).map(account => ({ - juror: { id: account, vote: { commitment: '', outcome: 0 } }, - weight: 1, - locked: bigNum(courtConfig.minActiveBalance) - .mul(courtConfig.penaltyPct) - .div(PCT_BASE), - })), vote: null, appeal: null, }, } -const DISPUTES_SPECIFIC_DATA = [ +const DISPUTES_DATA = [ { state: DisputeState.Ruled, metadata: 'Dispute finished', - rounds: [ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL], + rounds: [{ ...ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL }], }, { state: DisputeState.Adjudicating, metadata: 'Dispute appealed', - rounds: [ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL], + rounds: [{ ...ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL }], }, { state: DisputeState.Adjudicating, metadata: 'Dispute in last round', - rounds: [ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL], + rounds: [{ ...ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL }], }, { state: DisputeState.Adjudicating, metadata: 'Dispute in first adjudication round (jurors already drafted)', - rounds: [ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL], + rounds: [{ ...ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL }], }, { state: DisputeState.Evidence, metadata: 'Dispute in evidence submission', - rounds: [ROUNDS.FIRST_NOT_DRAFTED], + rounds: [{ ...ROUNDS.FIRST_NOT_DRAFTED }], }, ] function generateDisputes() { const disputes = [] - for (let i = 0; i < NUMBER_OF_DISPUTES; i++) { - const { state, metadata, rounds } = DISPUTES_SPECIFIC_DATA[i] + + for (let i = 0; i < DISPUTES_DATA.length; i++) { + const { state, metadata, rounds } = DISPUTES_DATA[i] + const dispute = { id: String(i), txHash: hash256(i), @@ -98,10 +89,10 @@ function generateDisputes() { lastRoundId: rounds.length - 1, } - disputes.push(dispute) + disputes.unshift(dispute) } - return disputes.reverse() + return disputes } // lastRoundId diff --git a/src/mock/data/Jurors.js b/src/mock/data/Jurors.js new file mode 100644 index 00000000..28cbfa28 --- /dev/null +++ b/src/mock/data/Jurors.js @@ -0,0 +1,45 @@ +import { accounts, bigExp } from '../helper' +import { ANJMovementType } from '../types' + +const ACTIVE_BASE_BALANCE = '10000' + +function generateJurors() { + return accounts.map((account, index) => { + const activeBalance = bigExp(`${ACTIVE_BASE_BALANCE * (index + 1)}`) + console.log('activeBalance', activeBalance) + + return { + id: account, + + // Wallet balance (from the subgraph we actually don't get this amount from the juror entity itself + // but in this case since we are mocking data doesn't really matter) + walletBalance: '0', + + activeBalance, + lockedBalance: '0', + availableBalance: '0', + deactivationBalance: '0', + treasuryTokens: [], + + // Mimicking ANJ activation from wallet + movements: [ + { + amount: activeBalance, + effectiveTermId: 3, + createdAt: '1', + type: ANJMovementType.Activation, + }, + { + amount: activeBalance, + effectiveTermId: 3, + createdAt: '1', + type: ANJMovementType.Stake, + }, + ], + + drafts: [], + } + }) +} + +export default generateJurors() diff --git a/src/mock/data/index.js b/src/mock/data/index.js index 4a48fe6f..af5dda20 100644 --- a/src/mock/data/index.js +++ b/src/mock/data/index.js @@ -1,32 +1,80 @@ import { bigExp } from '../helper' -import courtConfig from './CourtConfig' -import disputes from './Disputes' -import { jurorMovements, jurorBalances, jurorWalletBalance } from './Balances' +import Court from '../models/Court' +import { ANJMovementType } from '../types' +const court = new Court() + +// Each key of this Object is the name of the respective query that we have declared (see all query names at ./queries folder) +// And the value is the function that resolves said query (by resolving we mean returns the respective mocked data) export default { - // Court configuration + /** **** COURT CONFIG *****/ + CourtConfig: () => ({ - courtConfig, - }), - // Dashboard state - JurorFirstANJActivationMovement: () => ({ - juror: { - movements: jurorMovements[0], - }, - }), - Balances: ({ id }) => ({ - juror: jurorBalances, - }), - ANJWalletBalance: ({ id }) => ({ anjbalance: jurorWalletBalance }), - CurrentTermJurorDrafts: ({ id }) => ({ - drafts: [], + courtConfig: court.config, }), + + /** **** DASHBOARD STATE *****/ + + // Get first activation movements for juror with id `id` + JurorFirstANJActivationMovement: ({ id }) => { + const { movements } = court.getJuror(id) || {} + const firstActivationMovement = movements?.find( + movement => movement.type === ANJMovementType.Activation + ) + + return { + juror: { + movements: firstActivationMovement ? [firstActivationMovement] : [], + }, + } + }, + + // Get active, inactive, locked and deactivation balances along with movements for juror with id `id` + JurorANJBalances: ({ id }) => { + const juror = court.getJuror(id) + const { + activeBalance, + lockedBalance, + availableBalance, + deactivationBalance, + treasuryTokens, + movements, + } = juror || {} + + return { + juror: juror + ? { + activeBalance, + lockedBalance, + availableBalance, + deactivationBalance, + treasuryTokens, + movements, + } + : null, + } + }, + + // Get wallet balance for juror with id `id` + JurorANJWalletBalance: ({ id }) => { + const { walletBalance } = court.getJuror(id) || {} + return { anjbalance: walletBalance } + }, AppealsByMaker: ({ maker }) => ({ appeals: [], }), AppealsByTaker: ({ taker }) => ({ appeals: [], }), + JurorDraftsFrom: ({ id, from }) => ({ + drafts: [], + }), + JurorDraftsRewarded: ({ id }) => ({ + juror: { + id: '', + drafts: [], + }, + }), JurorDraftsNotRewarded: ({ id }) => ({ juror: { id: '', @@ -49,29 +97,31 @@ export default { ], }, }), - JurorDraftRewarded: ({ id }) => ({ - juror: { - id: '', - drafts: [], - }, - }), - // Disputes + + /** **** DASHBOARD STATE *****/ + + // Get all disputes AllDisputes: () => ({ - disputes, + disputes: court.disputes, }), + + // Get dispute with id `id` SingleDispute: ({ id }) => { - const dispute = disputes.find(d => d.id === id) + const dispute = court.getDispute(id) return { dispute, } }, + + // Get all juror drafts for juror with id `id` JurorDrafts: ({ id }) => ({ juror: { id: '', drafts: [], }, }), - // Tasks + + // Get all open tasks OpenTasks: () => ({ adjudicationRounds: [], }), diff --git a/src/mock/helper.js b/src/mock/helper.js index ae18edca..5bffc46d 100644 --- a/src/mock/helper.js +++ b/src/mock/helper.js @@ -1,10 +1,12 @@ export const bigExp = (x, y = 18) => `${x}${''.padEnd(y, '0')}` export const accounts = [ - '0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1', - '0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0', - '0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b', - '0xE11BA2b4D45Eaed5996Cd0823791E0C93114882d', - '0xd03ea8624C8C5987235048901fB614fDcA89b117', - '0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC', + '0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1', + '0xffcf8fdee72ac11b5c542428b35eef5769c409f0', + '0x22d491bde2303f2f43325b2108d26f1eaba1e32b', + '0xe11ba2b4d45eaed5996cd0823791e0c93114882d', + '0xd03ea8624c8c5987235048901fb614fdca89b117', ] + +export const getRandomNumber = (min, max) => + Math.floor(Math.random() * (max - min + 1) + min) diff --git a/src/mock/models/Court.js b/src/mock/models/Court.js new file mode 100644 index 00000000..a0f797bb --- /dev/null +++ b/src/mock/models/Court.js @@ -0,0 +1,73 @@ +import Jurors from '../data/Jurors' +import Disputes from '../data/Disputes' +import courtConfig from '../data/CourtConfig' + +import { bigNum } from '../../lib/math-utils' +import { PCT_BASE } from '../../utils/dispute-utils' +import { accounts, getRandomNumber } from '../helper' + +export default class { + constructor() { + this.config = courtConfig + + this.disputes = Disputes + this.jurors = Jurors + + this.draftJurors() + + console.log('disputes', this.disputes) + } + + getDispute(id) { + return this.disputes.find(dispute => dispute.id === id) + } + + getJuror(id) { + return this.jurors.find(juror => juror.id === id) + } + + draftJurors() { + for (let i = 0; i < this.disputes.length; i++) { + const dispute = this.disputes[i] + console.log('Drafting for dispute', dispute, i) + // We will only "draft" jurors for last round since we don't really care for previos rounds data + const lastRoundId = dispute.rounds.length - 1 + const lastRound = dispute.rounds[lastRoundId] + lastRound.jurors = [] + + let selectedJurors = 0 + const jurorsNumber = lastRound.jurorsNumber + while (selectedJurors < jurorsNumber) { + console.log('entered while selectedJurors', selectedJurors) + // We select a juror betwwen the 5 available accounts + const selectedAccountIndex = getRandomNumber(0, accounts.length - 1) + const selectedAccount = accounts[selectedAccountIndex] + + const selectedJuror = this.getJuror(selectedAccount) + + const jurorWeight = getRandomNumber(1, jurorsNumber - selectedJurors) + const jurorDraft = { + id: '0x', + round: lastRound, + juror: selectedJuror, + weight: jurorWeight, + locked: bigNum(this.config.minActiveBalance) + .mul(this.config.penaltyPct) + .div(PCT_BASE), + } + + // We associate respective entities. + // Note that we prevent storing circular references when setting null values + // since they would error when querying them and we won't be using them anyways + selectedJuror.drafts.push({ ...jurorDraft, juror: null }) + lastRound.jurors.push({ + ...jurorDraft, + juror: { id: selectedJuror.id }, + round: null, + }) + + selectedJurors += jurorWeight + } + } + } +} diff --git a/src/queries/balances.js b/src/queries/balances.js index 842596b6..7838859b 100644 --- a/src/queries/balances.js +++ b/src/queries/balances.js @@ -1,15 +1,15 @@ import gql from 'graphql-tag' -export const ANJBalance = gql` - subscription ANJWalletBalance($id: ID!) { +export const JurorANJWalletBalance = gql` + subscription JurorANJWalletBalance($id: ID!) { anjbalance(id: $id) { amount } } ` -export const Juror = gql` - subscription Balances($id: ID!, $from: BigInt!) { +export const JurorANJBalances = gql` + subscription JurorANJBalances($id: ID!, $from: BigInt!) { juror(id: $id) { activeBalance lockedBalance @@ -39,7 +39,7 @@ export const Juror = gql` } ` -export const FirstANJActivationMovement = gql` +export const JurorFirstANJActivationMovement = gql` query JurorFirstANJActivationMovement($id: ID!) { juror(id: $id) { movements( diff --git a/src/queries/jurorDrafts.js b/src/queries/jurorDrafts.js index 0786d307..f2ad1a6c 100644 --- a/src/queries/jurorDrafts.js +++ b/src/queries/jurorDrafts.js @@ -27,8 +27,8 @@ export const JurorDraftsNotRewarded = gql` ` // First juror draft already rewarded -export const JurorDraftRewarded = gql` - query JurorDraftRewarded($id: ID!) { +export const JurorDraftsRewarded = gql` + query JurorDraftsRewarded($id: ID!) { juror(id: $id) { id drafts(where: { rewarded: true }, first: 1) { @@ -38,9 +38,9 @@ export const JurorDraftRewarded = gql` } ` -// Jurors drafts by `id` for current term -export const CurrentTermJurorDrafts = gql` - subscription CurrentTermJurorDrafts($id: ID!, $from: BigInt!) { +// Jurors drafts for juror with id `$id` created from `$from` +export const JurorDraftsFrom = gql` + subscription JurorDraftsFrom($id: ID!, $from: BigInt!) { juror(id: $id) { id drafts(where: { createdAt_gt: $from }) { @@ -51,7 +51,7 @@ export const CurrentTermJurorDrafts = gql` } ` -// All juror drafts by `id` +// All juror drafts for juror with id `id` // Useful query to know all disputes that the juror by `$id` is part of export const JurorDrafts = gql` query JurorDrafts($id: ID!) { From 79afdf69e823db684ab68fb7cd85892eded934a0 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Fri, 27 Mar 2020 16:02:50 -0300 Subject: [PATCH 06/18] Adapt to new changes --- 1 | 20 ++++++++++++++++++++ package.json | 2 +- src/mock/data/CourtConfig.js | 6 ++++++ src/mock/data/Modules.js | 6 ++++++ src/mock/data/index.js | 5 +++++ src/mock/models/Court.js | 2 ++ src/queries/balances.js | 2 +- 7 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 1 create mode 100644 src/mock/data/Modules.js diff --git a/1 b/1 new file mode 100644 index 00000000..ca13d6cb --- /dev/null +++ b/1 @@ -0,0 +1,20 @@ +Merge branch 'development' into mock-data + +# Conflicts: +# package.json +# +# It looks like you may be committing a merge. +# If this is not correct, please remove the file +# .git/MERGE_HEAD +# and try again. + + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# +# On branch mock-data +# All conflicts fixed but you are still merging. +# +# Changes to be committed: +# modified: package.json +# diff --git a/package.json b/package.json index cff88430..bcb0d47a 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,8 @@ }, "scripts": { "start": "npm run sync-assets && REACT_APP_BUILD=$(git log --pretty=format:'%h' -n 1) react-app-rewired start", - "start:local:mock": "REACT_APP_MOCK_TEST=1 npm run start:rpc", "start:local": "REACT_APP_CHAIN_ID=1337 npm run start ", + "start:local:mock": "REACT_APP_MOCK_TEST=1 npm run start:local", "start:mainnet": "REACT_APP_CHAIN_ID=1 npm run start", "start:mainnet:mock": "REACT_APP_MOCK_TEST=1 npm run start:mainnet", "start:ropsten": "REACT_APP_CHAIN_ID=3 npm run start", diff --git a/src/mock/data/CourtConfig.js b/src/mock/data/CourtConfig.js index cfd015c2..e70e82ee 100644 --- a/src/mock/data/CourtConfig.js +++ b/src/mock/data/CourtConfig.js @@ -53,6 +53,12 @@ const courtConfig = { // type // address ], + subscriptions: { + currentPeriod: '0', + feeAmount: bigExp('10'), + periodDuration: '600', + periods: [], + }, } export default courtConfig diff --git a/src/mock/data/Modules.js b/src/mock/data/Modules.js new file mode 100644 index 00000000..4c122de7 --- /dev/null +++ b/src/mock/data/Modules.js @@ -0,0 +1,6 @@ +import { bigExp } from '../helper' + +export const JurorRegistry = { + totalStaked: bigExp('0'), + totalActive: bigExp('0'), +} diff --git a/src/mock/data/index.js b/src/mock/data/index.js index af5dda20..d25fee4a 100644 --- a/src/mock/data/index.js +++ b/src/mock/data/index.js @@ -15,6 +15,11 @@ export default { /** **** DASHBOARD STATE *****/ + // Get Court JurorRegistry module + JurorsRegistryModule: ({ id }) => ({ + jurorsRegistryModule: court.jurorsRegistryModule, + }), + // Get first activation movements for juror with id `id` JurorFirstANJActivationMovement: ({ id }) => { const { movements } = court.getJuror(id) || {} diff --git a/src/mock/models/Court.js b/src/mock/models/Court.js index a0f797bb..fbc6ea56 100644 --- a/src/mock/models/Court.js +++ b/src/mock/models/Court.js @@ -1,6 +1,7 @@ import Jurors from '../data/Jurors' import Disputes from '../data/Disputes' import courtConfig from '../data/CourtConfig' +import { JurorRegistry } from '../data/Modules' import { bigNum } from '../../lib/math-utils' import { PCT_BASE } from '../../utils/dispute-utils' @@ -9,6 +10,7 @@ import { accounts, getRandomNumber } from '../helper' export default class { constructor() { this.config = courtConfig + this.jurorRegistryModule = JurorRegistry this.disputes = Disputes this.jurors = Jurors diff --git a/src/queries/balances.js b/src/queries/balances.js index 07aecc21..7d78254f 100644 --- a/src/queries/balances.js +++ b/src/queries/balances.js @@ -65,7 +65,7 @@ export const JurorFirstANJActivationMovement = gql` } ` export const ActiveJurors = gql` - query Jurors { + query ActiveJurors { jurors(first: 1000, where: { activeBalance_gt: 0 }) { id } From 1f37b92bab5b5b65c6772bfd726cb3f5a9a8cf0d Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Sat, 28 Mar 2020 21:58:21 -0300 Subject: [PATCH 07/18] Support all new queries --- 1 | 20 -------------------- package.json | 8 ++++---- src/environment.js | 4 ++-- src/exchanges.js | 4 ++-- src/index.js | 7 ++++++- src/mock/data/Disputes.js | 26 +++++++++++++++++++++----- src/mock/data/Jurors.js | 1 - src/mock/data/index.js | 12 ++++++++++-- src/mock/models/Court.js | 6 +----- 9 files changed, 46 insertions(+), 42 deletions(-) delete mode 100644 1 diff --git a/1 b/1 deleted file mode 100644 index ca13d6cb..00000000 --- a/1 +++ /dev/null @@ -1,20 +0,0 @@ -Merge branch 'development' into mock-data - -# Conflicts: -# package.json -# -# It looks like you may be committing a merge. -# If this is not correct, please remove the file -# .git/MERGE_HEAD -# and try again. - - -# Please enter the commit message for your changes. Lines starting -# with '#' will be ignored, and an empty message aborts the commit. -# -# On branch mock-data -# All conflicts fixed but you are still merging. -# -# Changes to be committed: -# modified: package.json -# diff --git a/package.json b/package.json index bcb0d47a..355bf93e 100644 --- a/package.json +++ b/package.json @@ -37,13 +37,13 @@ "scripts": { "start": "npm run sync-assets && REACT_APP_BUILD=$(git log --pretty=format:'%h' -n 1) react-app-rewired start", "start:local": "REACT_APP_CHAIN_ID=1337 npm run start ", - "start:local:mock": "REACT_APP_MOCK_TEST=1 npm run start:local", + "start:local:mock": "REACT_APP_MOCK_DATA=1 npm run start:local", "start:mainnet": "REACT_APP_CHAIN_ID=1 npm run start", - "start:mainnet:mock": "REACT_APP_MOCK_TEST=1 npm run start:mainnet", + "start:mainnet:mock": "REACT_APP_MOCK_DATA=1 npm run start:mainnet", "start:ropsten": "REACT_APP_CHAIN_ID=3 npm run start", - "start:ropsten:mock": "REACT_APP_MOCK_TEST=1 npm run start:ropsten", + "start:ropsten:mock": "REACT_APP_MOCK_DATA=1 npm run start:ropsten", "start:rinkeby": "REACT_APP_CHAIN_ID=4 npm run start", - "start:rinkeby:mock": "REACT_APP_MOCK_TEST=1 npm run start:rinkeby", + "start:rinkeby:mock": "REACT_APP_MOCK_DATA=1 npm run start:rinkeby", "build": "./scripts/build.sh", "build:local": "REACT_APP_CHAIN_ID=1337 npm run build", "build:mainnet": "REACT_APP_CHAIN_ID=1 npm run build", diff --git a/src/environment.js b/src/environment.js index 7894def7..e3d2aef9 100644 --- a/src/environment.js +++ b/src/environment.js @@ -28,8 +28,8 @@ const ENV_VARS = { ENABLE_SENTRY() { return process.env.REACT_APP_ENABLE_SENTRY === '1' }, - MOCK_TEST() { - return process.env.REACT_APP_MOCK_TEST === '1' + MOCK_DATA() { + return process.env.REACT_APP_MOCK_DATA === '1' }, } diff --git a/src/exchanges.js b/src/exchanges.js index b2285873..f7e5d361 100644 --- a/src/exchanges.js +++ b/src/exchanges.js @@ -20,11 +20,11 @@ export const subscriptionClient = new SubscriptionClient( ) export function getFetchExchange() { - return env('MOCK_TEST') ? mockFetchExchange : DEFAULT_FETCH_EXCHANGE + return env('MOCK_DATA') ? mockFetchExchange : DEFAULT_FETCH_EXCHANGE } export function getSubscriptionExchange() { - return env('MOCK_TEST') + return env('MOCK_DATA') ? mockSubscriptionExchange : DEFAULT_SUBSCRIPTION_EXCHANGE } diff --git a/src/index.js b/src/index.js index 0bee255c..89a09dd8 100644 --- a/src/index.js +++ b/src/index.js @@ -12,12 +12,13 @@ import { import App from './App' import endpoints from './endpoints' -import initializeSentry from './sentry' +import env from './environment' import { getFetchExchange, getSubscriptionExchange, subscriptionClient, } from './exchanges' +import initializeSentry from './sentry' initializeSentry() @@ -39,6 +40,10 @@ subscriptionClient.onConnected(() => (connectionAttempts = 0)) // Check for connection errors and if reaches max attempts send error log to Sentry subscriptionClient.onError(err => { + if (env('MOCK_DATA')) { + return + } + const maxReconnectionAttempts = subscriptionClient.reconnectionAttempts if (maxReconnectionAttempts === ++connectionAttempts) { diff --git a/src/mock/data/Disputes.js b/src/mock/data/Disputes.js index c062a066..e42596dc 100644 --- a/src/mock/data/Disputes.js +++ b/src/mock/data/Disputes.js @@ -46,27 +46,43 @@ const ROUNDS = { const DISPUTES_DATA = [ { state: DisputeState.Ruled, - metadata: 'Dispute finished', + metadata: JSON.stringify({ + description: 'Dispute finished', + metadata: 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json', + }), rounds: [{ ...ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL }], }, { state: DisputeState.Adjudicating, - metadata: 'Dispute appealed', + metadata: JSON.stringify({ + description: 'Dispute appealed', + metadata: 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json', + }), rounds: [{ ...ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL }], }, { state: DisputeState.Adjudicating, - metadata: 'Dispute in last round', + metadata: JSON.stringify({ + description: 'Dispute in last round', + metadata: 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json', + }), rounds: [{ ...ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL }], }, { state: DisputeState.Adjudicating, - metadata: 'Dispute in first adjudication round (jurors already drafted)', + metadata: JSON.stringify({ + description: + 'Dispute in first adjudication round (jurors already drafted)', + metadata: 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json', + }), rounds: [{ ...ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL }], }, { state: DisputeState.Evidence, - metadata: 'Dispute in evidence submission', + metadata: JSON.stringify({ + description: 'Dispute in evidence submission', + metadata: 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json', + }), rounds: [{ ...ROUNDS.FIRST_NOT_DRAFTED }], }, ] diff --git a/src/mock/data/Jurors.js b/src/mock/data/Jurors.js index 28cbfa28..b3564009 100644 --- a/src/mock/data/Jurors.js +++ b/src/mock/data/Jurors.js @@ -6,7 +6,6 @@ const ACTIVE_BASE_BALANCE = '10000' function generateJurors() { return accounts.map((account, index) => { const activeBalance = bigExp(`${ACTIVE_BASE_BALANCE * (index + 1)}`) - console.log('activeBalance', activeBalance) return { id: account, diff --git a/src/mock/data/index.js b/src/mock/data/index.js index d25fee4a..67532f8c 100644 --- a/src/mock/data/index.js +++ b/src/mock/data/index.js @@ -20,6 +20,11 @@ export default { jurorsRegistryModule: court.jurorsRegistryModule, }), + FeeMovements: () => ({ feeMovements: [] }), + + JurorFeesClaimed: ({ owner }) => ({}), + + ActiveJurors: () => ({ jurors: [] }), // Get first activation movements for juror with id `id` JurorFirstANJActivationMovement: ({ id }) => { const { movements } = court.getJuror(id) || {} @@ -29,7 +34,7 @@ export default { return { juror: { - movements: firstActivationMovement ? [firstActivationMovement] : [], + anjMovements: firstActivationMovement ? [firstActivationMovement] : [], }, } }, @@ -65,6 +70,9 @@ export default { const { walletBalance } = court.getJuror(id) || {} return { anjbalance: walletBalance } }, + + JurorTreasuryBalances: ({ owner }) => [], + AppealsByMaker: ({ maker }) => ({ appeals: [], }), @@ -103,7 +111,7 @@ export default { }, }), - /** **** DASHBOARD STATE *****/ + /** **** DISPUTES *****/ // Get all disputes AllDisputes: () => ({ diff --git a/src/mock/models/Court.js b/src/mock/models/Court.js index fbc6ea56..0b0012f6 100644 --- a/src/mock/models/Court.js +++ b/src/mock/models/Court.js @@ -10,14 +10,12 @@ import { accounts, getRandomNumber } from '../helper' export default class { constructor() { this.config = courtConfig - this.jurorRegistryModule = JurorRegistry + this.jurorsRegistryModule = JurorRegistry this.disputes = Disputes this.jurors = Jurors this.draftJurors() - - console.log('disputes', this.disputes) } getDispute(id) { @@ -31,7 +29,6 @@ export default class { draftJurors() { for (let i = 0; i < this.disputes.length; i++) { const dispute = this.disputes[i] - console.log('Drafting for dispute', dispute, i) // We will only "draft" jurors for last round since we don't really care for previos rounds data const lastRoundId = dispute.rounds.length - 1 const lastRound = dispute.rounds[lastRoundId] @@ -40,7 +37,6 @@ export default class { let selectedJurors = 0 const jurorsNumber = lastRound.jurorsNumber while (selectedJurors < jurorsNumber) { - console.log('entered while selectedJurors', selectedJurors) // We select a juror betwwen the 5 available accounts const selectedAccountIndex = getRandomNumber(0, accounts.length - 1) const selectedAccount = accounts[selectedAccountIndex] From 329986460691e276ca51b2b0452117d0b73482a1 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Mon, 30 Mar 2020 01:34:10 -0300 Subject: [PATCH 08/18] Add disputes for different phases draft jurors create votes create appeals --- .../Dashboard/ANJLockedDistribution.js | 2 +- src/components/Dashboard/Balance.js | 4 +- src/components/Disputes/DisputeActions.js | 1 + src/hooks/subscription-hooks.js | 2 +- src/mock/data/CourtConfig.js | 8 +- src/mock/data/Disputes.js | 181 ++++++++-- src/mock/data/Jurors.js | 2 +- src/mock/data/index.js | 109 +++--- src/mock/helper.js | 82 ++++- src/mock/models/Court.js | 312 ++++++++++++++++-- src/mock/types.js | 20 ++ src/utils/juror-draft-utils.js | 2 +- 12 files changed, 606 insertions(+), 119 deletions(-) diff --git a/src/components/Dashboard/ANJLockedDistribution.js b/src/components/Dashboard/ANJLockedDistribution.js index d9b3ac0f..4d462cba 100644 --- a/src/components/Dashboard/ANJLockedDistribution.js +++ b/src/components/Dashboard/ANJLockedDistribution.js @@ -95,7 +95,7 @@ function Row({ label, isLabelLink, amount, symbol, weight }) { )} - {weight?.gt(1) && `${weight.toNumber()}x `} {amount} {symbol} + {weight > 1 && `${weight}x `} {amount} {symbol} ) diff --git a/src/components/Dashboard/Balance.js b/src/components/Dashboard/Balance.js index ebafcdf0..a95ffc2f 100644 --- a/src/components/Dashboard/Balance.js +++ b/src/components/Dashboard/Balance.js @@ -279,8 +279,8 @@ function useHelpAttributes(distribution) { const { lockedPerDispute } = distribution const onlyOneDispute = lockedPerDispute.length === 1 - const isJurorDraftedMultipleTimesSameDispute = lockedPerDispute.some(lock => - lock.weight.gt(1) + const isJurorDraftedMultipleTimesSameDispute = lockedPerDispute.some( + lock => lock.weight > 1 ) let text diff --git a/src/components/Disputes/DisputeActions.js b/src/components/Disputes/DisputeActions.js index 47a33c24..d1ce3992 100644 --- a/src/components/Disputes/DisputeActions.js +++ b/src/components/Disputes/DisputeActions.js @@ -187,6 +187,7 @@ function InformationSection({ } // Helper function that returns main attributes for the YourVoteInfo component +// TODO: Contemplate final round cases (when a juror has voted, the ANJ amount is pre-slashed) const useInfoAttributes = ({ hasJurorVoted, jurorDraft, diff --git a/src/hooks/subscription-hooks.js b/src/hooks/subscription-hooks.js index e368408d..c38cf503 100644 --- a/src/hooks/subscription-hooks.js +++ b/src/hooks/subscription-hooks.js @@ -208,7 +208,7 @@ export function useDisputesSubscription() { const disputes = useMemo( () => - data && data.disputes + data?.disputes ? data.disputes.map(dispute => transformDisputeDataAttributes(dispute, courtConfig) ) diff --git a/src/mock/data/CourtConfig.js b/src/mock/data/CourtConfig.js index e70e82ee..7379276b 100644 --- a/src/mock/data/CourtConfig.js +++ b/src/mock/data/CourtConfig.js @@ -2,9 +2,9 @@ import { getNetwork } from '../../networks' import { bigExp } from '../helper' import dayjs from 'dayjs' -const TERM_DURATION = 240 // 4 minutes -const CURRENT_TERM = 10 -const COURT_START = dayjs() // Court started 10 terms ago +const TERM_DURATION = 60 // 1 minutes +const CURRENT_TERM = 100 +const COURT_START = dayjs() // Court started 100 terms ago .subtract(TERM_DURATION * CURRENT_TERM, 'second') .unix() @@ -44,7 +44,7 @@ const courtConfig = { finalRoundReduction: '5000', firstRoundJurorsNumber: '3', appealStepFactor: '3', - maxRegularAppealRounds: '3', + maxRegularAppealRounds: '2', appealCollateralFactor: '30000', appealConfirmCollateralFactor: '20000', minActiveBalance: bigExp('100'), diff --git a/src/mock/data/Disputes.js b/src/mock/data/Disputes.js index e42596dc..c0df6fd7 100644 --- a/src/mock/data/Disputes.js +++ b/src/mock/data/Disputes.js @@ -2,17 +2,45 @@ import courtConfig from './CourtConfig' import { hash256 } from '../../lib/web3-utils' import { dayjs } from '../../utils/date-utils' -import { DisputeState, AdjudicationState } from '../types' +import { + AdjudicationState, + DisputeState, + RulingOptions, + getRulingOptionNumber, +} from '../types' +const DEFAULT_IPFS_METADATA = + 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json' const CREATE_TERM_ID = courtConfig.currentTerm -const PAST_DRAFT_TERM_ID = courtConfig.currentTerm - 4 const DRAFT_TERM_ID = CREATE_TERM_ID + 4 const ROUNDS = { - FIRST_NOT_DRAFTED: { + // Mock round to use for multi-round disputes + PREVIOUS: { + id: '0', + state: AdjudicationState.Ended, + draftTermId: '50', // TODO: Find better calculation + createdAt: 0, + delayedTerms: 0, + jurors: [], + + // We'll create "mock" votes and appeals for previous rounds + // Note that these won't be considered for appeal collaterals or other accountable data + vote: { + winningOutcome: getRulingOptionNumber(RulingOptions.Against), + }, + appeal: { + appealedRuling: getRulingOptionNumber(RulingOptions.InFavor), + createdAt: dayjs().unix(), + opposedRuling: getRulingOptionNumber(RulingOptions.Against), + confirmedAt: dayjs().unix(), + }, + }, + + // Round not drafted + NOT_DRAFTED: { id: '0', state: AdjudicationState.Invalid, - number: '0', draftTermId: DRAFT_TERM_ID, jurorsNumber: 0, settledPenalties: false, @@ -21,88 +49,179 @@ const ROUNDS = { coherentJurors: 0, collectedTokens: 0, createdAt: 0, - jurors: [], - vote: null, - appeal: null, }, - FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL: { + + // Round in comitting phase + COMITTING: { id: '0', state: AdjudicationState.Committing, - number: '0', - draftTermId: PAST_DRAFT_TERM_ID, - jurorsNumber: 3, + jurorsNumber: courtConfig.firstRoundJurorsNumber, settledPenalties: false, jurorFees: courtConfig.jurorFee, - delayedTerms: 3, + delayedTerms: 0, + selectedJurors: 3, + coherentJurors: 0, + collectedTokens: 0, + createdAt: 0, + }, + + // Round has been appealed + APPEALED: { + id: '0', + state: AdjudicationState.ConfirmingAppeal, + jurorsNumber: courtConfig.firstRoundJurorsNumber, + settledPenalties: false, + jurorFees: courtConfig.jurorFee, + delayedTerms: 0, + selectedJurors: 3, + coherentJurors: 0, + collectedTokens: 0, + createdAt: 0, + }, + + // Round has been confirm appealed + CONFIRM_APPEALED: { + id: '0', + state: AdjudicationState.Invalid, + jurorsNumber: + courtConfig.firstRoundJurorsNumber * courtConfig.appealStepFactor, + settledPenalties: false, + jurorFees: courtConfig.jurorFee, + delayedTerms: 0, + selectedJurors: 3, + coherentJurors: 0, + collectedTokens: 0, + createdAt: 0, + }, + + // Round ended + ENDED: { + id: '0', + state: AdjudicationState.Ended, + jurorsNumber: courtConfig.firstRoundJurorsNumber, + settledPenalties: false, + jurorFees: courtConfig.jurorFee, + delayedTerms: 0, selectedJurors: 3, coherentJurors: 0, collectedTokens: 0, createdAt: 0, - vote: null, - appeal: null, }, } +// Data that tells the state of each dispute const DISPUTES_DATA = [ { state: DisputeState.Ruled, metadata: JSON.stringify({ - description: 'Dispute finished', - metadata: 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json', + description: 'Dispute finished (First round, In favor unanimous)', + metadata: DEFAULT_IPFS_METADATA, }), - rounds: [{ ...ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL }], + rounds: [{ ...ROUNDS.ENDED }], + flagData: { + vote: { + winningOutcome: RulingOptions.InFavor, + }, + }, }, { - state: DisputeState.Adjudicating, + state: DisputeState.Ruled, metadata: JSON.stringify({ - description: 'Dispute appealed', - metadata: 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json', + description: 'Dispute finished (First round, No one voted)', + metadata: DEFAULT_IPFS_METADATA, + }), + rounds: [{ ...ROUNDS.ENDED }], + }, + { + state: DisputeState.Ruled, + metadata: JSON.stringify({ + description: 'Dispute finished (Last round)', + metadata: DEFAULT_IPFS_METADATA, }), - rounds: [{ ...ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL }], + rounds: [ + ...populatePreviousRounds(courtConfig.maxRegularAppealRounds), + { ...ROUNDS.ENDED }, + ], + flagData: { + vote: { + winningOutcome: RulingOptions.Against, + }, + }, + }, + { + state: DisputeState.Drafting, + metadata: JSON.stringify({ + description: 'Dispute confirm appealed', + metadata: DEFAULT_IPFS_METADATA, + }), + rounds: [{ ...ROUNDS.PREVIOUS }, { ...ROUNDS.CONFIRM_APPEALED }], }, { state: DisputeState.Adjudicating, metadata: JSON.stringify({ - description: 'Dispute in last round', - metadata: 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json', + description: 'Dispute appealed', + metadata: DEFAULT_IPFS_METADATA, }), - rounds: [{ ...ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL }], + rounds: [{ ...ROUNDS.APPEALED }], + flagData: { + vote: { + winningOutcome: RulingOptions.Against, + }, + appeal: { + appealedRuling: RulingOptions.InFavor, + }, + }, }, { state: DisputeState.Adjudicating, metadata: JSON.stringify({ description: 'Dispute in first adjudication round (jurors already drafted)', - metadata: 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json', + metadata: DEFAULT_IPFS_METADATA, }), - rounds: [{ ...ROUNDS.FIRST_DRAFTED_COMITTING_NO_VOTES_NO_APPEAL }], + rounds: [{ ...ROUNDS.COMITTING }], }, { state: DisputeState.Evidence, metadata: JSON.stringify({ description: 'Dispute in evidence submission', - metadata: 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json', + metadata: DEFAULT_IPFS_METADATA, }), - rounds: [{ ...ROUNDS.FIRST_NOT_DRAFTED }], + rounds: [{ ...ROUNDS.NOT_DRAFTED }], }, ] +function populatePreviousRounds(numberOfRounds) { + return Array.from({ length: numberOfRounds }).map(_ => ({ + ...ROUNDS.PREVIOUS, + })) +} + function generateDisputes() { const disputes = [] for (let i = 0; i < DISPUTES_DATA.length; i++) { - const { state, metadata, rounds } = DISPUTES_DATA[i] + const { flagData, metadata, rounds, state } = DISPUTES_DATA[i] + const disputeId = String(i) const dispute = { - id: String(i), + id: disputeId, txHash: hash256(i), createTermId: courtConfig.currentTerm, createdAt: dayjs().unix(), possibleRulings: 2, state, metadata, - rounds, + rounds: rounds.map((round, index) => ({ + ...round, + number: String(index), + dispute: { + id: disputeId, + rounds: rounds.map(round => ({ id: round.id })), + }, + })), lastRoundId: rounds.length - 1, + flagData, } disputes.unshift(dispute) diff --git a/src/mock/data/Jurors.js b/src/mock/data/Jurors.js index b3564009..0834d86e 100644 --- a/src/mock/data/Jurors.js +++ b/src/mock/data/Jurors.js @@ -21,7 +21,7 @@ function generateJurors() { treasuryTokens: [], // Mimicking ANJ activation from wallet - movements: [ + anjMovements: [ { amount: activeBalance, effectiveTermId: 3, diff --git a/src/mock/data/index.js b/src/mock/data/index.js index 67532f8c..8c723eb7 100644 --- a/src/mock/data/index.js +++ b/src/mock/data/index.js @@ -1,6 +1,9 @@ -import { bigExp } from '../helper' import Court from '../models/Court' import { ANJMovementType } from '../types' +import { + removeRoundCircularReferences, + removeJurorCircularReferences, +} from '../helper' const court = new Court() @@ -22,13 +25,13 @@ export default { FeeMovements: () => ({ feeMovements: [] }), - JurorFeesClaimed: ({ owner }) => ({}), + JurorFeesClaimed: ({ owner }) => ({ feeMovements: [] }), ActiveJurors: () => ({ jurors: [] }), // Get first activation movements for juror with id `id` JurorFirstANJActivationMovement: ({ id }) => { - const { movements } = court.getJuror(id) || {} - const firstActivationMovement = movements?.find( + const { anjMovements } = court.getJuror(id) || {} + const firstActivationMovement = anjMovements?.find( movement => movement.type === ANJMovementType.Activation ) @@ -48,7 +51,7 @@ export default { availableBalance, deactivationBalance, treasuryTokens, - movements, + anjMovements, } = juror || {} return { @@ -59,7 +62,7 @@ export default { availableBalance, deactivationBalance, treasuryTokens, - movements, + anjMovements, } : null, } @@ -73,12 +76,26 @@ export default { JurorTreasuryBalances: ({ owner }) => [], - AppealsByMaker: ({ maker }) => ({ - appeals: [], - }), - AppealsByTaker: ({ taker }) => ({ - appeals: [], - }), + AppealsByMaker: ({ maker }) => { + const appeals = court.getAppealsByMaker(maker) + + return { + appeals: appeals.map(({ taker, ...appeal }) => ({ + ...appeal, + })), + } + }, + + AppealsByTaker: ({ taker }) => { + const appeals = court.getAppealsByTaker(taker) + + return { + appeals: appeals.map(({ maker, ...appeal }) => ({ + ...appeal, + })), + } + }, + JurorDraftsFrom: ({ id, from }) => ({ drafts: [], }), @@ -88,54 +105,56 @@ export default { drafts: [], }, }), - JurorDraftsNotRewarded: ({ id }) => ({ - juror: { - id: '', - drafts: [ - { - weight: 3, - outcome: 4, - round: { - number: '1', - coherentJurors: '1', - collectedTokens: bigExp('20'), - jurorFees: bigExp('10'), - settledPenalties: true, - dispute: { - id: '1', - finalRuling: 4, - }, - }, - }, - ], - }, - }), + JurorDraftsNotRewarded: ({ id }) => { + const juror = removeJurorCircularReferences(court.getJuror(id)) + const { drafts = [] } = juror || {} + + return { + juror: { + id, + drafts: drafts.filter(draft => !draft.rewarded), + }, + } + }, /** **** DISPUTES *****/ // Get all disputes AllDisputes: () => ({ - disputes: court.disputes, + disputes: court.disputes.map(dispute => ({ + ...dispute, + rounds: dispute.rounds.map(removeRoundCircularReferences), + })), }), // Get dispute with id `id` SingleDispute: ({ id }) => { const dispute = court.getDispute(id) return { - dispute, + dispute: { + ...dispute, + rounds: dispute.rounds.map(removeRoundCircularReferences), + }, } }, // Get all juror drafts for juror with id `id` - JurorDrafts: ({ id }) => ({ - juror: { - id: '', - drafts: [], - }, - }), + JurorDrafts: ({ id }) => { + const juror = removeJurorCircularReferences(court.getJuror(id)) + const { drafts = [] } = juror || {} + + return { + juror: { + drafts, + }, + } + }, // Get all open tasks - OpenTasks: () => ({ - adjudicationRounds: [], - }), + OpenTasks: ({ state }) => { + const rounds = court.getRoundsByState(state) + return { + adjudicationRounds: rounds.map(removeRoundCircularReferences), + } + }, } diff --git a/src/mock/helper.js b/src/mock/helper.js index 5bffc46d..155ba203 100644 --- a/src/mock/helper.js +++ b/src/mock/helper.js @@ -1,12 +1,90 @@ +import { AdjudicationState } from './types' +import { FINAL_ROUND_WEIGHT_PRECISION, PCT_BASE } from '../utils/dispute-utils' + export const bigExp = (x, y = 18) => `${x}${''.padEnd(y, '0')}` export const accounts = [ '0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1', '0xffcf8fdee72ac11b5c542428b35eef5769c409f0', '0x22d491bde2303f2f43325b2108d26f1eaba1e32b', - '0xe11ba2b4d45eaed5996cd0823791e0c93114882d', - '0xd03ea8624c8c5987235048901fb614fdca89b117', + // '0xe11ba2b4d45eaed5996cd0823791e0c93114882d', + // '0xd03ea8624c8c5987235048901fb614fdca89b117', ] export const getRandomNumber = (min, max) => Math.floor(Math.random() * (max - min + 1) + min) + +export const getDraftTermId = (state, courtConfig) => { + const { + currentTerm, + commitTerms, + revealTerms, + appealTerms, + appealConfirmationTerms, + } = courtConfig + + if (state === AdjudicationState.Committing) { + return currentTerm + } + + if (state === AdjudicationState.Revealing) { + return String(currentTerm - commitTerms) + } + + if (state === AdjudicationState.Appealing) { + return String(currentTerm - commitTerms - revealTerms) + } + + if (state === AdjudicationState.ConfirmingAppeal) { + return String(currentTerm - commitTerms - revealTerms - appealTerms) + } + + return String( + currentTerm - + commitTerms - + revealTerms - + appealTerms - + appealConfirmationTerms + ) +} + +export const getMinActiveBalanceMultiple = ( + activeBalance, + minActiveBalance +) => { + if (activeBalance.lt(minActiveBalance)) { + return '0' + } + + return FINAL_ROUND_WEIGHT_PRECISION.mul(activeBalance).div(minActiveBalance) +} + +export const pct = (self, pct) => self.mul(pct).div(PCT_BASE) + +export const removeJurorCircularReferences = juror => { + if (!juror) { + return + } + + return { + ...juror, + drafts: juror.drafts.map(jurorDraft => ({ + ...jurorDraft, + round: removeRoundCircularReferences(jurorDraft.round), + juror: { id: jurorDraft.id }, + })), + } +} + +export const removeRoundCircularReferences = round => { + const { jurors = [] } = round || {} + + return { + ...round, + jurors: jurors.map(jurorDraft => ({ + ...jurorDraft, + juror: { id: jurorDraft.juror.id }, + round: { id: jurorDraft.round.id }, + })), + } +} diff --git a/src/mock/models/Court.js b/src/mock/models/Court.js index 0b0012f6..50e40070 100644 --- a/src/mock/models/Court.js +++ b/src/mock/models/Court.js @@ -4,8 +4,29 @@ import courtConfig from '../data/CourtConfig' import { JurorRegistry } from '../data/Modules' import { bigNum } from '../../lib/math-utils' -import { PCT_BASE } from '../../utils/dispute-utils' -import { accounts, getRandomNumber } from '../helper' +import { dayjs } from '../../utils/date-utils' +import { addressesEqual } from '../../lib/web3-utils' +import { + accounts, + bigExp, + getDraftTermId, + getMinActiveBalanceMultiple, + getRandomNumber, + pct, +} from '../helper' +import { + ANJMovementType, + AdjudicationState, + DisputeState, + RulingOptions, + getAdjudicationStateNumber, + getRulingOptionNumber, +} from '../types' + +const DEFAULT_APPEAL_MAKER = accounts[0] +const DEFAULT_APPEAL_TAKER = accounts[1] +const DEFAULT_APPEAL_DEPOSIT = bigExp('185') +const DEFAULT_CONFIRM_APPEAL_DEPOSIT = bigExp('225') export default class { constructor() { @@ -14,8 +35,13 @@ export default class { this.disputes = Disputes this.jurors = Jurors + this.appeals = [] + this.adjudicationRounds = [] + this.updateTotalActiveBalance() this.draftJurors() + this.createVotes() + this.createAppeals() } getDispute(id) { @@ -23,49 +49,273 @@ export default class { } getJuror(id) { - return this.jurors.find(juror => juror.id === id) + return this.jurors.find(juror => addressesEqual(juror.id, id)) + } + + getAppealsByMaker(maker) { + return this.appeals.filter(appeal => addressesEqual(appeal.maker, maker)) + } + + getAppealsByTaker(taker) { + return this.appeals.filter(appeal => addressesEqual(appeal.taker, taker)) + } + + getRoundsByState(state) { + return this.adjudicationRounds.filter(round => + state.includes(getAdjudicationStateNumber(round.state)) + ) } draftJurors() { for (let i = 0; i < this.disputes.length; i++) { const dispute = this.disputes[i] - // We will only "draft" jurors for last round since we don't really care for previos rounds data + // We will only "draft" jurors for last round since we don't really care for previous rounds data const lastRoundId = dispute.rounds.length - 1 const lastRound = dispute.rounds[lastRoundId] + + if (lastRound.state === AdjudicationState.Invalid) { + continue + } + + this.adjudicationRounds.push(lastRound) + lastRound.jurors = [] + lastRound.draftTermId = getDraftTermId(lastRound.state, this.config) + const maxRegularAppealRoundsReached = + this.config.maxRegularAppealRounds <= lastRoundId + + // If we reached the last possible round, juror's weight is relative to the number of times the min active balance the juror has + if (maxRegularAppealRoundsReached) { + // final round + + lastRound.jurorsNumber = getMinActiveBalanceMultiple( + bigNum(this.jurorsRegistryModule.totalActive), + bigNum(this.config.minActiveBalance) + ) + } else { + // normal round + let selectedJurors = 0 + const jurorsNumber = lastRound.jurorsNumber + while (selectedJurors < jurorsNumber) { + // We select a juror betwwen the 3 available accounts + + const selectedAccountIndex = getRandomNumber(0, accounts.length - 1) + const selectedAccount = accounts[selectedAccountIndex] + + const selectedJuror = this.getJuror(selectedAccount) + + const draftLockAmount = pct( + bigNum(this.config.minActiveBalance), + this.config.penaltyPct + ) + + const jurorDraft = lastRound.jurors.find(jurorDraft => + addressesEqual(jurorDraft.juror.id, selectedAccount) + ) + + if (!jurorDraft) { + this.createDraft(selectedJuror, lastRound, 1, draftLockAmount) + } else { + jurorDraft.weight += 1 + + this.lockAnjAmount(selectedJuror, draftLockAmount) + } - let selectedJurors = 0 - const jurorsNumber = lastRound.jurorsNumber - while (selectedJurors < jurorsNumber) { - // We select a juror betwwen the 5 available accounts - const selectedAccountIndex = getRandomNumber(0, accounts.length - 1) - const selectedAccount = accounts[selectedAccountIndex] - - const selectedJuror = this.getJuror(selectedAccount) - - const jurorWeight = getRandomNumber(1, jurorsNumber - selectedJurors) - const jurorDraft = { - id: '0x', - round: lastRound, - juror: selectedJuror, - weight: jurorWeight, - locked: bigNum(this.config.minActiveBalance) - .mul(this.config.penaltyPct) - .div(PCT_BASE), + selectedJurors += 1 } + } + } + } + + createDraft(juror, round, weight, draftLockAmount) { + const jurorDraft = { + id: '0x', + round, + juror, + weight, + } + + this.lockAnjAmount(juror, draftLockAmount) + + // Associate respective entities. + juror.drafts.push(jurorDraft) + round.jurors.push(jurorDraft) + } + + lockAnjAmount(juror, amount) { + if (amount.gt(0)) { + // Create lock anjMovement + juror.anjMovements = [ + { + amount: amount.toString(), + effectiveTermId: null, + createdAt: dayjs().unix(), + type: ANJMovementType.Lock, + }, + ...juror.anjMovements, + ] + + // Update juror locked balance + juror.lockedBalance = bigNum(juror.lockedBalance) + .add(amount) + .toString() + } + } + + createVotes() { + for (let i = 0; i < this.disputes.length; i++) { + const dispute = this.disputes[i] + + if (!dispute.flagData?.vote) { + if (dispute.state === DisputeState.Ruled) { + dispute.finalRuling = getRulingOptionNumber(RulingOptions.Refused) + } + + continue + } + + // We will only create votes for last round since we don't really care for previous rounds data + const lastRoundId = dispute.rounds.length - 1 + const lastRound = dispute.rounds[lastRoundId] + const maxRegularAppealRoundsReached = + this.config.maxRegularAppealRounds <= lastRoundId + + if (maxRegularAppealRoundsReached) { + const selectedJurors = this.jurors.filter(juror => + bigNum(juror.activeBalance).gt(this.config.minActiveBalance) + ) - // We associate respective entities. - // Note that we prevent storing circular references when setting null values - // since they would error when querying them and we won't be using them anyways - selectedJuror.drafts.push({ ...jurorDraft, juror: null }) - lastRound.jurors.push({ - ...jurorDraft, - juror: { id: selectedJuror.id }, - round: null, + selectedJurors.forEach(juror => { + const jurorWeight = getMinActiveBalanceMultiple( + bigNum(juror.activeBalance), + bigNum(this.config.minActiveBalance) + ) + + this.createDraft(juror, lastRound, jurorWeight, bigNum(0)) + + const weightedPenalty = pct( + bigNum(juror.activeBalance), + bigNum(this.config.penaltyPct) + ) + + this.slashJuror(juror, weightedPenalty) }) + } + + const voteMetadata = dispute.flagData.vote + for (let j = 0; j < lastRound.jurors.length; j++) { + const draft = lastRound.jurors[j] + draft.commitment = '0x' + draft.commitmentDate = 0 - selectedJurors += jurorWeight + draft.outcome = getRulingOptionNumber(voteMetadata.winningOutcome) + draft.revealDate = dayjs().unix() + } + + lastRound.vote = { + winningOutcome: voteMetadata.winningOutcome, + } + + if (lastRound.state === AdjudicationState.Ended) { + dispute.finalRuling = getRulingOptionNumber(voteMetadata.winningOutcome) } } } + + slashJuror(juror, amount) { + juror.activeBalance = bigNum(juror.activeBalance).sub(amount) + + juror.anjMovements.unshift({ + amount: amount.toString(), + effectiveTermId: null, + createdAt: dayjs().unix(), + type: ANJMovementType.Slash, + }) + } + + createAppeals() { + for (let i = 0; i < this.disputes.length; i++) { + const dispute = this.disputes[i] + + if (!dispute.flagData?.appeal) { + continue + } + + const appealMetaData = dispute.flagData.appeal + + const lastRoundId = dispute.rounds.length - 1 + const lastRound = dispute.rounds[lastRoundId] + + const appeal = { + id: '', + + round: { + number: lastRound.number, + settledPenalties: lastRound.settledPenalties, + dispute: { + id: dispute.id, + finalRuling: dispute.finalRuling, + lastRoundId: dispute.lastRoundId, + rounds: dispute.rounds.map(round => ({ + jurorsNumber: round.jurorsNumber, + number: round.number, + })), + }, + }, + + maker: DEFAULT_APPEAL_MAKER, + appealedRuling: getRulingOptionNumber(appealMetaData.appealedRuling), + appealDeposit: DEFAULT_APPEAL_DEPOSIT, + createdAt: dayjs().unix(), + + ...(appealMetaData.opposedRuling + ? { + opposedRuling: getRulingOptionNumber( + appealMetaData.opposedRuling + ), + confirmedAt: appealMetaData.opposedRuling ? dayjs().unix() : null, + confirmAppealDeposit: DEFAULT_CONFIRM_APPEAL_DEPOSIT, + taker: appealMetaData.opposedRuling ? DEFAULT_APPEAL_TAKER : null, + } + : { + confirmAppealDeposit: '0', + }), + } + lastRound.appeal = appeal + + // Save appeal to collection + this.appeals.push(appeal) + } + } + + updateTotalActiveBalance() { + this.jurorsRegistryModule.totalActive = String( + this.jurors.reduce( + (acc, juror) => acc.add(juror.activeBalance), + bigNum(0) + ) + ) + } } + +/// // Juror draft not rewarded Example//// +// juror: { +// id: '', +// drafts: [ +// { +// weight: 3, +// outcome: 4, +// round: { +// number: '1', +// coherentJurors: '1', +// collectedTokens: bigExp('20'), +// jurorFees: bigExp('10'), +// settledPenalties: true, +// dispute: { +// id: '1', +// finalRuling: 4, +// }, +// }, +// }, +// ], +// }, diff --git a/src/mock/types.js b/src/mock/types.js index 4542289c..0723ed59 100644 --- a/src/mock/types.js +++ b/src/mock/types.js @@ -24,3 +24,23 @@ export const AdjudicationState = { ConfirmingAppeal: 'ConfirmingAppeal', Ended: 'Ended', } + +export const getAdjudicationStateNumber = state => { + return Object.values(AdjudicationState).findIndex( + adjudicationState => adjudicationState === state + ) +} + +export const RulingOptions = { + Missing: 'Missing', + Leaked: 'Leaked', + Refused: 'Refused', + Against: 'Against', + InFavor: 'InFavor', +} + +export const getRulingOptionNumber = option => { + return Object.values(RulingOptions).findIndex( + rulingPption => rulingPption === option + ) +} diff --git a/src/utils/juror-draft-utils.js b/src/utils/juror-draft-utils.js index 6cb9c850..08184757 100644 --- a/src/utils/juror-draft-utils.js +++ b/src/utils/juror-draft-utils.js @@ -33,7 +33,7 @@ export function transformJurorDataAttributes(jurorDraft) { return { ...jurorDraft, - weight: bigNum(weight), + weight, round: { ...round, number: parseInt(round.number, 10), From 7fb51647868af2f9c14d0f0814b2455d58861628 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Tue, 31 Mar 2020 11:33:25 -0300 Subject: [PATCH 09/18] Support final rounds --- src/mock/data/CourtConfig.js | 8 +- src/mock/data/Disputes.js | 224 +++++--------------- src/mock/data/Jurors.js | 4 +- src/mock/data/Rounds.js | 131 ++++++++++++ src/mock/data/index.js | 15 +- src/mock/helper.js | 39 +++- src/mock/models/Court.js | 386 +++++++++++++++++++++-------------- src/mock/types.js | 2 +- 8 files changed, 462 insertions(+), 347 deletions(-) create mode 100644 src/mock/data/Rounds.js diff --git a/src/mock/data/CourtConfig.js b/src/mock/data/CourtConfig.js index 7379276b..ab8faf2e 100644 --- a/src/mock/data/CourtConfig.js +++ b/src/mock/data/CourtConfig.js @@ -32,10 +32,10 @@ const courtConfig = { draftFee: bigExp('18', 16), settleFee: bigExp('1', 17), evidenceTerms: 21, - commitTerms: '6', - revealTerms: '6', - appealTerms: '6', - appealConfirmationTerms: '6', + commitTerms: '3', + revealTerms: '3', + appealTerms: '3', + appealConfirmationTerms: '3', terms: [ { startTime: COURT_START, diff --git a/src/mock/data/Disputes.js b/src/mock/data/Disputes.js index c0df6fd7..80af1511 100644 --- a/src/mock/data/Disputes.js +++ b/src/mock/data/Disputes.js @@ -1,128 +1,30 @@ import courtConfig from './CourtConfig' - +import ROUNDS from './Rounds' import { hash256 } from '../../lib/web3-utils' import { dayjs } from '../../utils/date-utils' -import { - AdjudicationState, - DisputeState, - RulingOptions, - getRulingOptionNumber, -} from '../types' +import { DisputeState } from '../types' const DEFAULT_IPFS_METADATA = 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json' -const CREATE_TERM_ID = courtConfig.currentTerm -const DRAFT_TERM_ID = CREATE_TERM_ID + 4 - -const ROUNDS = { - // Mock round to use for multi-round disputes - PREVIOUS: { - id: '0', - state: AdjudicationState.Ended, - draftTermId: '50', // TODO: Find better calculation - createdAt: 0, - delayedTerms: 0, - jurors: [], - - // We'll create "mock" votes and appeals for previous rounds - // Note that these won't be considered for appeal collaterals or other accountable data - vote: { - winningOutcome: getRulingOptionNumber(RulingOptions.Against), - }, - appeal: { - appealedRuling: getRulingOptionNumber(RulingOptions.InFavor), - createdAt: dayjs().unix(), - opposedRuling: getRulingOptionNumber(RulingOptions.Against), - confirmedAt: dayjs().unix(), - }, - }, - - // Round not drafted - NOT_DRAFTED: { - id: '0', - state: AdjudicationState.Invalid, - draftTermId: DRAFT_TERM_ID, - jurorsNumber: 0, - settledPenalties: false, - delayedTerms: 0, - selectedJurors: 0, - coherentJurors: 0, - collectedTokens: 0, - createdAt: 0, - }, - - // Round in comitting phase - COMITTING: { - id: '0', - state: AdjudicationState.Committing, - jurorsNumber: courtConfig.firstRoundJurorsNumber, - settledPenalties: false, - jurorFees: courtConfig.jurorFee, - delayedTerms: 0, - selectedJurors: 3, - coherentJurors: 0, - collectedTokens: 0, - createdAt: 0, - }, - - // Round has been appealed - APPEALED: { - id: '0', - state: AdjudicationState.ConfirmingAppeal, - jurorsNumber: courtConfig.firstRoundJurorsNumber, - settledPenalties: false, - jurorFees: courtConfig.jurorFee, - delayedTerms: 0, - selectedJurors: 3, - coherentJurors: 0, - collectedTokens: 0, - createdAt: 0, - }, - - // Round has been confirm appealed - CONFIRM_APPEALED: { - id: '0', - state: AdjudicationState.Invalid, - jurorsNumber: - courtConfig.firstRoundJurorsNumber * courtConfig.appealStepFactor, - settledPenalties: false, - jurorFees: courtConfig.jurorFee, - delayedTerms: 0, - selectedJurors: 3, - coherentJurors: 0, - collectedTokens: 0, - createdAt: 0, - }, - - // Round ended - ENDED: { - id: '0', - state: AdjudicationState.Ended, - jurorsNumber: courtConfig.firstRoundJurorsNumber, - settledPenalties: false, - jurorFees: courtConfig.jurorFee, - delayedTerms: 0, - selectedJurors: 3, - coherentJurors: 0, - collectedTokens: 0, - createdAt: 0, - }, -} // Data that tells the state of each dispute const DISPUTES_DATA = [ { state: DisputeState.Ruled, metadata: JSON.stringify({ - description: 'Dispute finished (First round, In favor unanimous)', + description: 'Dispute finished (First round, In favor)', + metadata: DEFAULT_IPFS_METADATA, + }), + rounds: [{ ...ROUNDS.ENDED.IN_FAVOR }], + }, + { + state: DisputeState.Ruled, + metadata: JSON.stringify({ + description: + 'Dispute finished (First round, Refused to vote, Penalties Settled)', metadata: DEFAULT_IPFS_METADATA, }), - rounds: [{ ...ROUNDS.ENDED }], - flagData: { - vote: { - winningOutcome: RulingOptions.InFavor, - }, - }, + rounds: [{ ...ROUNDS.ENDED.REFUSED }], }, { state: DisputeState.Ruled, @@ -130,23 +32,26 @@ const DISPUTES_DATA = [ description: 'Dispute finished (First round, No one voted)', metadata: DEFAULT_IPFS_METADATA, }), - rounds: [{ ...ROUNDS.ENDED }], + rounds: [{ ...ROUNDS.ENDED.NO_VOTES }], }, { state: DisputeState.Ruled, metadata: JSON.stringify({ - description: 'Dispute finished (Last round)', + description: 'Dispute finished (Final round, Against)', metadata: DEFAULT_IPFS_METADATA, }), rounds: [ ...populatePreviousRounds(courtConfig.maxRegularAppealRounds), - { ...ROUNDS.ENDED }, + { ...ROUNDS.ENDED.FINAL_ROUND }, ], - flagData: { - vote: { - winningOutcome: RulingOptions.Against, - }, - }, + }, + { + state: DisputeState.Adjudicating, + metadata: JSON.stringify({ + description: 'Dispute finished (Execute ruling)', + metadata: DEFAULT_IPFS_METADATA, + }), + rounds: [{ ...ROUNDS.ENDED.IN_FAVOR }], }, { state: DisputeState.Drafting, @@ -163,20 +68,27 @@ const DISPUTES_DATA = [ metadata: DEFAULT_IPFS_METADATA, }), rounds: [{ ...ROUNDS.APPEALED }], - flagData: { - vote: { - winningOutcome: RulingOptions.Against, - }, - appeal: { - appealedRuling: RulingOptions.InFavor, - }, - }, }, { state: DisputeState.Adjudicating, metadata: JSON.stringify({ - description: - 'Dispute in first adjudication round (jurors already drafted)', + description: 'Dispute appealing', + metadata: DEFAULT_IPFS_METADATA, + }), + rounds: [{ ...ROUNDS.APPEALING }], + }, + { + state: DisputeState.Adjudicating, + metadata: JSON.stringify({ + description: 'Dispute revealing', + metadata: DEFAULT_IPFS_METADATA, + }), + rounds: [{ ...ROUNDS.REVEALING }], + }, + { + state: DisputeState.Adjudicating, + metadata: JSON.stringify({ + description: 'Dispute comitting', metadata: DEFAULT_IPFS_METADATA, }), rounds: [{ ...ROUNDS.COMITTING }], @@ -201,7 +113,7 @@ function generateDisputes() { const disputes = [] for (let i = 0; i < DISPUTES_DATA.length; i++) { - const { flagData, metadata, rounds, state } = DISPUTES_DATA[i] + const { metadata, rounds, state } = DISPUTES_DATA[i] const disputeId = String(i) const dispute = { @@ -212,59 +124,19 @@ function generateDisputes() { possibleRulings: 2, state, metadata, - rounds: rounds.map((round, index) => ({ - ...round, - number: String(index), - dispute: { - id: disputeId, - rounds: rounds.map(round => ({ id: round.id })), - }, - })), lastRoundId: rounds.length - 1, - flagData, } + dispute.rounds = rounds.map((round, index) => ({ + ...round, + number: String(index), + dispute, + })) + disputes.unshift(dispute) } return disputes } -// lastRoundId -// createdAt -// rounds { -// id -// state -// number -// draftTermId -// jurorsNumber -// settledPenalties -// jurorFees -// delayedTerms -// selectedJurors -// coherentJurors -// collectedTokens -// createdAt -// jurors { -// juror { -// id -// } -// commitment -// outcome -// } -// vote { -// id -// winningOutcome -// } -// appeal { -// id -// maker -// appealedRuling -// taker -// opposedRuling -// settled -// createdAt -// } -// } - export default generateDisputes() diff --git a/src/mock/data/Jurors.js b/src/mock/data/Jurors.js index 0834d86e..b718ceea 100644 --- a/src/mock/data/Jurors.js +++ b/src/mock/data/Jurors.js @@ -2,9 +2,10 @@ import { accounts, bigExp } from '../helper' import { ANJMovementType } from '../types' const ACTIVE_BASE_BALANCE = '10000' +const numberOfJurors = 3 function generateJurors() { - return accounts.map((account, index) => { + return accounts.slice(0, numberOfJurors).map((account, index) => { const activeBalance = bigExp(`${ACTIVE_BASE_BALANCE * (index + 1)}`) return { @@ -13,7 +14,6 @@ function generateJurors() { // Wallet balance (from the subgraph we actually don't get this amount from the juror entity itself // but in this case since we are mocking data doesn't really matter) walletBalance: '0', - activeBalance, lockedBalance: '0', availableBalance: '0', diff --git a/src/mock/data/Rounds.js b/src/mock/data/Rounds.js new file mode 100644 index 00000000..7c0878d1 --- /dev/null +++ b/src/mock/data/Rounds.js @@ -0,0 +1,131 @@ +import courtConfig from './CourtConfig' +import { AdjudicationState, RulingOptions } from '../types' + +const DEFAULT_ROUND_DATA = { + id: '0', + coherentJurors: 0, + collectedTokens: '0', + createdAt: 0, + delayedTerms: 0, + jurorFees: '0', + settledPenalties: false, +} + +const ROUNDS = { + // Mock round to use for multi-round disputes + PREVIOUS: { + state: AdjudicationState.Ended, + draftTermId: '50', // TODO: Find better calculation + + // We'll create "mock" votes and appeals for previous rounds + voteData: { + winningOutcome: RulingOptions.Against, + }, + + appealData: { + appealedRuling: RulingOptions.InFavor, + opposedRuling: RulingOptions.Against, + }, + ...DEFAULT_ROUND_DATA, + }, + + // Round not drafted + NOT_DRAFTED: { + state: AdjudicationState.Invalid, + jurorsNumber: 0, + ...DEFAULT_ROUND_DATA, + }, + + // Round in comitting phase + COMITTING: { + state: AdjudicationState.Committing, + jurorsNumber: courtConfig.firstRoundJurorsNumber, + ...DEFAULT_ROUND_DATA, + }, + + // Round in revealing phase + REVEALING: { + state: AdjudicationState.Revealing, + jurorsNumber: courtConfig.firstRoundJurorsNumber, + voteData: { + onlyCommit: true, + }, + ...DEFAULT_ROUND_DATA, + }, + + // Round in appealing phase + APPEALING: { + state: AdjudicationState.Appealing, + jurorsNumber: courtConfig.firstRoundJurorsNumber, + voteData: { + winningOutcome: RulingOptions.Against, + minority: RulingOptions.InFavor, + }, + ...DEFAULT_ROUND_DATA, + }, + + // Round has been appealed (in confirm appeal phase) + APPEALED: { + state: AdjudicationState.ConfirmingAppeal, + jurorsNumber: courtConfig.firstRoundJurorsNumber, + voteData: { + winningOutcome: RulingOptions.Against, + minority: RulingOptions.InFavor, + }, + appealData: { + appealedRuling: RulingOptions.InFavor, + }, + ...DEFAULT_ROUND_DATA, + }, + + // Round has been confirm appealed + CONFIRM_APPEALED: { + state: AdjudicationState.Invalid, + jurorsNumber: + courtConfig.firstRoundJurorsNumber * courtConfig.appealStepFactor, + ...DEFAULT_ROUND_DATA, + }, + + // Round ended In favor + ENDED: { + IN_FAVOR: { + state: AdjudicationState.Ended, + jurorsNumber: courtConfig.firstRoundJurorsNumber, + voteData: { + winningOutcome: RulingOptions.InFavor, + minority: RulingOptions.Against, + }, + ...DEFAULT_ROUND_DATA, + }, + + // Round ended and Refused + REFUSED: { + state: AdjudicationState.Ended, + jurorsNumber: courtConfig.firstRoundJurorsNumber, + voteData: { + winningOutcome: RulingOptions.Refused, + minority: RulingOptions.InFavor, + }, + settlePenalties: true, + ...DEFAULT_ROUND_DATA, + }, + + NO_VOTES: { + state: AdjudicationState.Ended, + jurorsNumber: courtConfig.firstRoundJurorsNumber, + ...DEFAULT_ROUND_DATA, + }, + + FINAL_ROUND: { + state: AdjudicationState.Ended, + voteData: { + winningOutcome: RulingOptions.Against, + minority: RulingOptions.InFavor, + }, + // settlePenalties: true, + ...DEFAULT_ROUND_DATA, + }, + }, +} + +export default ROUNDS diff --git a/src/mock/data/index.js b/src/mock/data/index.js index 8c723eb7..abf00864 100644 --- a/src/mock/data/index.js +++ b/src/mock/data/index.js @@ -1,8 +1,9 @@ import Court from '../models/Court' import { ANJMovementType } from '../types' import { - removeRoundCircularReferences, + removeAppealCircularReferences, removeJurorCircularReferences, + removeRoundCircularReferences, } from '../helper' const court = new Court() @@ -80,9 +81,9 @@ export default { const appeals = court.getAppealsByMaker(maker) return { - appeals: appeals.map(({ taker, ...appeal }) => ({ - ...appeal, - })), + appeals: appeals.map(({ taker, ...appeal }) => + removeAppealCircularReferences(appeal) + ), } }, @@ -90,9 +91,9 @@ export default { const appeals = court.getAppealsByTaker(taker) return { - appeals: appeals.map(({ maker, ...appeal }) => ({ - ...appeal, - })), + appeals: appeals.map(({ maker, ...appeal }) => + removeAppealCircularReferences(appeal) + ), } }, diff --git a/src/mock/helper.js b/src/mock/helper.js index 155ba203..01543c8b 100644 --- a/src/mock/helper.js +++ b/src/mock/helper.js @@ -7,8 +7,8 @@ export const accounts = [ '0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1', '0xffcf8fdee72ac11b5c542428b35eef5769c409f0', '0x22d491bde2303f2f43325b2108d26f1eaba1e32b', - // '0xe11ba2b4d45eaed5996cd0823791e0c93114882d', - // '0xd03ea8624c8c5987235048901fb614fdca89b117', + '0xe11ba2b4d45eaed5996cd0823791e0c93114882d', + '0xd03ea8624c8c5987235048901fb614fdca89b117', ] export const getRandomNumber = (min, max) => @@ -23,6 +23,11 @@ export const getDraftTermId = (state, courtConfig) => { appealConfirmationTerms, } = courtConfig + // When round has not yet started + if (state === AdjudicationState.Invalid) { + return String(currentTerm + 3) + } + if (state === AdjudicationState.Committing) { return currentTerm } @@ -61,6 +66,22 @@ export const getMinActiveBalanceMultiple = ( export const pct = (self, pct) => self.mul(pct).div(PCT_BASE) +export const removeAppealCircularReferences = appeal => { + return { + ...appeal, + round: { + ...removeRoundCircularReferences(appeal.round), + dispute: { + ...appeal.round.dispute, + rounds: appeal.round.dispute.rounds.map(({ number, jurorsNumber }) => ({ + number, + jurorsNumber, + })), + }, + }, + } +} + export const removeJurorCircularReferences = juror => { if (!juror) { return @@ -77,10 +98,22 @@ export const removeJurorCircularReferences = juror => { } export const removeRoundCircularReferences = round => { - const { jurors = [] } = round || {} + const { jurors = [], dispute } = round || {} return { ...round, + appeal: round.appeal + ? { + ...round.appeal, + round: { + id: round.id, + }, + } + : null, + dispute: { + ...dispute, + rounds: dispute.rounds.map(round => ({ id: round.id })), + }, jurors: jurors.map(jurorDraft => ({ ...jurorDraft, juror: { id: jurorDraft.juror.id }, diff --git a/src/mock/models/Court.js b/src/mock/models/Court.js index 50e40070..d62225c9 100644 --- a/src/mock/models/Court.js +++ b/src/mock/models/Court.js @@ -23,8 +23,8 @@ import { getRulingOptionNumber, } from '../types' -const DEFAULT_APPEAL_MAKER = accounts[0] -const DEFAULT_APPEAL_TAKER = accounts[1] +const DEFAULT_APPEAL_MAKER = accounts[3] +const DEFAULT_APPEAL_TAKER = accounts[4] const DEFAULT_APPEAL_DEPOSIT = bigExp('185') const DEFAULT_CONFIRM_APPEAL_DEPOSIT = bigExp('225') @@ -42,6 +42,7 @@ export default class { this.draftJurors() this.createVotes() this.createAppeals() + this.settlePenalties() } getDispute(id) { @@ -61,67 +62,74 @@ export default class { } getRoundsByState(state) { - return this.adjudicationRounds.filter(round => - state.includes(getAdjudicationStateNumber(round.state)) - ) + return this.adjudicationRounds.filter(round => { + const adjudicationState = getAdjudicationStateNumber(round.state) + return state[0] <= adjudicationState && adjudicationState <= state[1] + }) } draftJurors() { for (let i = 0; i < this.disputes.length; i++) { const dispute = this.disputes[i] - // We will only "draft" jurors for last round since we don't really care for previous rounds data - const lastRoundId = dispute.rounds.length - 1 - const lastRound = dispute.rounds[lastRoundId] - - if (lastRound.state === AdjudicationState.Invalid) { - continue - } - - this.adjudicationRounds.push(lastRound) - lastRound.jurors = [] - lastRound.draftTermId = getDraftTermId(lastRound.state, this.config) - const maxRegularAppealRoundsReached = - this.config.maxRegularAppealRounds <= lastRoundId + // Draft jurors for each round + for (let roundId = 0; roundId < dispute.rounds.length; roundId++) { + const round = dispute.rounds[roundId] - // If we reached the last possible round, juror's weight is relative to the number of times the min active balance the juror has - if (maxRegularAppealRoundsReached) { - // final round + round.draftTermId = getDraftTermId(round.state, this.config) + round.jurors = [] - lastRound.jurorsNumber = getMinActiveBalanceMultiple( - bigNum(this.jurorsRegistryModule.totalActive), - bigNum(this.config.minActiveBalance) - ) - } else { - // normal round - let selectedJurors = 0 - const jurorsNumber = lastRound.jurorsNumber - while (selectedJurors < jurorsNumber) { - // We select a juror betwwen the 3 available accounts + this.adjudicationRounds.push(round) - const selectedAccountIndex = getRandomNumber(0, accounts.length - 1) - const selectedAccount = accounts[selectedAccountIndex] + if (round.state === AdjudicationState.Invalid) { + continue + } - const selectedJuror = this.getJuror(selectedAccount) + const maxRegularAppealRoundsReached = + this.config.maxRegularAppealRounds <= roundId - const draftLockAmount = pct( - bigNum(this.config.minActiveBalance), - this.config.penaltyPct - ) + // If we reached the last possible round, juror's weight is relative to the number of times the min active balance the juror has + if (maxRegularAppealRoundsReached) { + // final round - const jurorDraft = lastRound.jurors.find(jurorDraft => - addressesEqual(jurorDraft.juror.id, selectedAccount) + round.jurorsNumber = getMinActiveBalanceMultiple( + bigNum(this.jurorsRegistryModule.totalActive), + bigNum(this.config.minActiveBalance) ) + } else { + // normal round + let selectedJurors = 0 + const jurorsNumber = round.jurorsNumber + while (selectedJurors < jurorsNumber) { + // Select a juror + const selectedJurorIndex = getRandomNumber( + 0, + this.jurors.length - 1 + ) + const selectedJuror = this.jurors[selectedJurorIndex] + + const draftLockAmount = pct( + bigNum(this.config.minActiveBalance), + this.config.penaltyPct + ) + + const jurorDraft = round.jurors.find(jurorDraft => + addressesEqual(jurorDraft.juror.id, selectedJuror.id) + ) + + if (!jurorDraft) { + this.createDraft(selectedJuror, round, 1, draftLockAmount) + } else { + jurorDraft.weight += 1 + + this.lockAnjAmount(selectedJuror, draftLockAmount) + } - if (!jurorDraft) { - this.createDraft(selectedJuror, lastRound, 1, draftLockAmount) - } else { - jurorDraft.weight += 1 - - this.lockAnjAmount(selectedJuror, draftLockAmount) + selectedJurors += 1 } - selectedJurors += 1 + round.jurorFees = bigNum(this.config.jurorFee).mul(selectedJurors) + round.selectedJurors = selectedJurors } } } @@ -166,58 +174,173 @@ export default class { for (let i = 0; i < this.disputes.length; i++) { const dispute = this.disputes[i] - if (!dispute.flagData?.vote) { - if (dispute.state === DisputeState.Ruled) { - dispute.finalRuling = getRulingOptionNumber(RulingOptions.Refused) - } - - continue + if (dispute.state === DisputeState.Ruled) { + dispute.finalRuling = getRulingOptionNumber(RulingOptions.Refused) } - // We will only create votes for last round since we don't really care for previous rounds data - const lastRoundId = dispute.rounds.length - 1 - const lastRound = dispute.rounds[lastRoundId] - const maxRegularAppealRoundsReached = - this.config.maxRegularAppealRounds <= lastRoundId + // Create votes for each round + for (let roundId = 0; roundId < dispute.rounds.length; roundId++) { + const round = dispute.rounds[roundId] - if (maxRegularAppealRoundsReached) { - const selectedJurors = this.jurors.filter(juror => - bigNum(juror.activeBalance).gt(this.config.minActiveBalance) - ) + // voteData tells whether we should create votes for the dispute in question + if (!round.voteData) { + continue + } - selectedJurors.forEach(juror => { - const jurorWeight = getMinActiveBalanceMultiple( - bigNum(juror.activeBalance), - bigNum(this.config.minActiveBalance) + const maxRegularAppealRoundsReached = + this.config.maxRegularAppealRounds <= roundId + + // If we are at the final round, we preslash jurors + if (maxRegularAppealRoundsReached) { + const selectedJurors = this.jurors.filter(juror => + bigNum(juror.activeBalance).gt(this.config.minActiveBalance) ) - this.createDraft(juror, lastRound, jurorWeight, bigNum(0)) + selectedJurors.forEach(juror => { + const jurorWeight = getMinActiveBalanceMultiple( + bigNum(juror.activeBalance), + bigNum(this.config.minActiveBalance) + ) + + this.createDraft(juror, round, jurorWeight, bigNum(0)) + + const weightedPenalty = pct( + bigNum(juror.activeBalance), + bigNum(this.config.penaltyPct) + ) + + this.collectTokens(juror, round, weightedPenalty, false) + }) + } + + const { voteData } = round + + let processedWeight = 0 + const jurorsNumber = round.jurorsNumber + for (let j = 0; j < round.jurors.length; j++) { + const draft = round.jurors[j] + draft.commitment = '0x' + draft.commitmentDate = dayjs().unix() + + if (voteData.onlyCommit) { + continue + } - const weightedPenalty = pct( - bigNum(juror.activeBalance), - bigNum(this.config.penaltyPct) + const mayorityEnsured = processedWeight > jurorsNumber / 2 + + // If possible we'll try to ditribute the total votes + // `winningOutcome` has the ruling option that should have the mayority of votes + // `minority` has the ruling option that should have the minority + // TODO: Add cases to distribute votes among the 3 ruling options + draft.revealDate = dayjs().unix() + draft.outcome = getRulingOptionNumber( + voteData[ + mayorityEnsured && voteData.minority + ? 'minority' + : 'winningOutcome' + ] ) - this.slashJuror(juror, weightedPenalty) - }) - } + processedWeight += draft.weight + } - const voteMetadata = dispute.flagData.vote - for (let j = 0; j < lastRound.jurors.length; j++) { - const draft = lastRound.jurors[j] - draft.commitment = '0x' - draft.commitmentDate = 0 + round.vote = { + winningOutcome: voteData.winningOutcome, + } - draft.outcome = getRulingOptionNumber(voteMetadata.winningOutcome) - draft.revealDate = dayjs().unix() + if (round.state === AdjudicationState.Ended) { + dispute.finalRuling = getRulingOptionNumber(voteData.winningOutcome) + } } + } + } + + createAppeals() { + for (let i = 0; i < this.disputes.length; i++) { + const dispute = this.disputes[i] + + for (let roundId = 0; roundId < dispute.rounds.length; roundId++) { + const round = dispute.rounds[roundId] + + // flagData tells whether we should create appeals for the dispute in question + if (!round.appealData) { + continue + } - lastRound.vote = { - winningOutcome: voteMetadata.winningOutcome, + const { appealData } = round + + const appeal = { + round, + appealedRuling: getRulingOptionNumber(appealData.appealedRuling), + maker: DEFAULT_APPEAL_MAKER, + appealDeposit: DEFAULT_APPEAL_DEPOSIT, + createdAt: dayjs().unix(), + + ...(appealData.opposedRuling + ? { + opposedRuling: getRulingOptionNumber(appealData.opposedRuling), + taker: DEFAULT_APPEAL_TAKER, + confirmAppealDeposit: DEFAULT_CONFIRM_APPEAL_DEPOSIT, + confirmedAt: dayjs().unix(), + } + : { + confirmAppealDeposit: '0', + }), + } + + // Save appeal round reference + round.appeal = appeal + + // Save appeal to collection + this.appeals.push(appeal) } + } + } + + settlePenalties() { + for (let i = 0; i < this.disputes.length; i++) { + const dispute = this.disputes[i] + + for (let roundId = 0; roundId < dispute.rounds.length; roundId++) { + const round = dispute.rounds[roundId] + + if (!round.settlePenalties) { + continue + } + + const maxRegularAppealRoundsReached = + this.config.maxRegularAppealRounds <= roundId + + if (!maxRegularAppealRoundsReached) { + for (let i = 0; i < round.jurors.length; i++) { + const jurorDraft = round.jurors[i] + + const isCoherentJuror = jurorDraft.outcome === dispute.finalRuling + + const slashOrUnlockAmount = pct( + bigNum(this.config.minActiveBalance), + this.config.penaltyPct + ) + const draftLockAmountTotal = slashOrUnlockAmount.mul( + jurorDraft.weight + ) + + if (isCoherentJuror) { + // unlock juror ANJ if juror is coherent + round.coherentJurors += jurorDraft.weight + this.unlockJurorANJ(jurorDraft.juror, draftLockAmountTotal) + } else { + this.collectTokens( + jurorDraft.juror, + round, + draftLockAmountTotal, + true + ) + } + } + } - if (lastRound.state === AdjudicationState.Ended) { - dispute.finalRuling = getRulingOptionNumber(voteMetadata.winningOutcome) + round.settledPenalties = true } } } @@ -225,6 +348,10 @@ export default class { slashJuror(juror, amount) { juror.activeBalance = bigNum(juror.activeBalance).sub(amount) + this.jurorsRegistryModule.totalActive = bigNum( + this.jurorsRegistryModule.totalActive + ).sub(amount) + juror.anjMovements.unshift({ amount: amount.toString(), effectiveTermId: null, @@ -233,61 +360,34 @@ export default class { }) } - createAppeals() { - for (let i = 0; i < this.disputes.length; i++) { - const dispute = this.disputes[i] + unlockJurorANJ(juror, amount) { + this.updateJurorLockedBalance(juror, amount) - if (!dispute.flagData?.appeal) { - continue - } + juror.anjMovements.unshift({ + amount: amount.toString(), + effectiveTermId: null, + createdAt: dayjs().unix(), + type: ANJMovementType.Unlock, + }) + } - const appealMetaData = dispute.flagData.appeal - - const lastRoundId = dispute.rounds.length - 1 - const lastRound = dispute.rounds[lastRoundId] - - const appeal = { - id: '', - - round: { - number: lastRound.number, - settledPenalties: lastRound.settledPenalties, - dispute: { - id: dispute.id, - finalRuling: dispute.finalRuling, - lastRoundId: dispute.lastRoundId, - rounds: dispute.rounds.map(round => ({ - jurorsNumber: round.jurorsNumber, - number: round.number, - })), - }, - }, + collectTokens(juror, round, amount, unlockBalance) { + // collect tokens if juror didn't vote for the winning outcome + round.collectedTokens = bigNum(round.collectedTokens) + .add(amount) + .toString() - maker: DEFAULT_APPEAL_MAKER, - appealedRuling: getRulingOptionNumber(appealMetaData.appealedRuling), - appealDeposit: DEFAULT_APPEAL_DEPOSIT, - createdAt: dayjs().unix(), - - ...(appealMetaData.opposedRuling - ? { - opposedRuling: getRulingOptionNumber( - appealMetaData.opposedRuling - ), - confirmedAt: appealMetaData.opposedRuling ? dayjs().unix() : null, - confirmAppealDeposit: DEFAULT_CONFIRM_APPEAL_DEPOSIT, - taker: appealMetaData.opposedRuling ? DEFAULT_APPEAL_TAKER : null, - } - : { - confirmAppealDeposit: '0', - }), - } - lastRound.appeal = appeal + this.slashJuror(juror, amount) - // Save appeal to collection - this.appeals.push(appeal) + if (unlockBalance) { + this.updateJurorLockedBalance(juror, amount) } } + updateJurorLockedBalance(juror, amount) { + juror.lockedBalance = bigNum(juror.lockedBalance).sub(amount) + } + updateTotalActiveBalance() { this.jurorsRegistryModule.totalActive = String( this.jurors.reduce( @@ -297,25 +397,3 @@ export default class { ) } } - -/// // Juror draft not rewarded Example//// -// juror: { -// id: '', -// drafts: [ -// { -// weight: 3, -// outcome: 4, -// round: { -// number: '1', -// coherentJurors: '1', -// collectedTokens: bigExp('20'), -// jurorFees: bigExp('10'), -// settledPenalties: true, -// dispute: { -// id: '1', -// finalRuling: 4, -// }, -// }, -// }, -// ], -// }, diff --git a/src/mock/types.js b/src/mock/types.js index 0723ed59..de044c79 100644 --- a/src/mock/types.js +++ b/src/mock/types.js @@ -41,6 +41,6 @@ export const RulingOptions = { export const getRulingOptionNumber = option => { return Object.values(RulingOptions).findIndex( - rulingPption => rulingPption === option + rulingOption => rulingOption === option ) } From 45072b0566ec99721425471a99bbc8e80956da95 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Wed, 1 Apr 2020 15:09:22 -0300 Subject: [PATCH 10/18] Fix ANT stat issue --- src/hooks/useCourtContracts.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hooks/useCourtContracts.js b/src/hooks/useCourtContracts.js index 39740c40..5b3d2ba3 100644 --- a/src/hooks/useCourtContracts.js +++ b/src/hooks/useCourtContracts.js @@ -583,7 +583,11 @@ export function useTotalANTStakedPolling(timeout = 1000) { let timeoutId // Since we don't have the ANT contract address on the local environment we are skipping the stat - if (isLocalOrUnknownNetwork()) { + if ( + isLocalOrUnknownNetwork() || + !networkAgentAddress || + !networkReserveAddress + ) { setError(true) return } From abba866200d47484de9e1bcfe950245ae98989e9 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Mon, 6 Apr 2020 22:59:48 -0300 Subject: [PATCH 11/18] Draft previous rounds --- src/exchanges.js | 2 +- src/hooks/useANJ.js | 4 +++- src/index.js | 5 ----- src/mock/data/Disputes.js | 5 +++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/exchanges.js b/src/exchanges.js index f7e5d361..0ead374e 100644 --- a/src/exchanges.js +++ b/src/exchanges.js @@ -14,7 +14,7 @@ const GRAPH_API_ENDPOINTS = endpoints() export const subscriptionClient = new SubscriptionClient( GRAPH_API_ENDPOINTS[1], { - reconnect: true, + reconnect: !env('MOCK_DATA'), reconnectionAttempts: 10, } ) diff --git a/src/hooks/useANJ.js b/src/hooks/useANJ.js index c6e0015a..e42e812e 100644 --- a/src/hooks/useANJ.js +++ b/src/hooks/useANJ.js @@ -52,6 +52,8 @@ export function useANJBalances() { // Use ANJ Locked distribution const lockedDistribution = useJurorLockedANJDistribution() + + console.log('lockedDistribution', lockedDistribution) const convertedLockedBalance = useMemo(() => { return { amount: lockedBalance, distribution: lockedDistribution } }, [lockedBalance, lockedDistribution]) @@ -261,7 +263,7 @@ export function useJurorLockedANJDistribution() { lockDistribution.splice(index, 1, { ...elem, amount: elem.amount.add(lockedAmount), - weight: elem.weight.add(weight), + weight: elem.weight + weight, }) } else { lockDistribution.push({ diff --git a/src/index.js b/src/index.js index 1ec5bc9c..eaab77bf 100644 --- a/src/index.js +++ b/src/index.js @@ -13,7 +13,6 @@ import { import App from './App' import endpoints from './endpoints' -import env from './environment' import { getFetchExchange, getSubscriptionExchange, @@ -41,10 +40,6 @@ subscriptionClient.onConnected(() => (connectionAttempts = 0)) // Check for connection errors and if reaches max attempts send error log to Sentry subscriptionClient.onError(err => { - if (env('MOCK_DATA')) { - return - } - const maxReconnectionAttempts = subscriptionClient.reconnectionAttempts if (maxReconnectionAttempts === ++connectionAttempts) { diff --git a/src/mock/data/Disputes.js b/src/mock/data/Disputes.js index 80af1511..8a7011fa 100644 --- a/src/mock/data/Disputes.js +++ b/src/mock/data/Disputes.js @@ -59,7 +59,7 @@ const DISPUTES_DATA = [ description: 'Dispute confirm appealed', metadata: DEFAULT_IPFS_METADATA, }), - rounds: [{ ...ROUNDS.PREVIOUS }, { ...ROUNDS.CONFIRM_APPEALED }], + rounds: [populatePreviousRounds(1), { ...ROUNDS.CONFIRM_APPEALED }], }, { state: DisputeState.Adjudicating, @@ -104,8 +104,9 @@ const DISPUTES_DATA = [ ] function populatePreviousRounds(numberOfRounds) { - return Array.from({ length: numberOfRounds }).map(_ => ({ + return Array.from({ length: numberOfRounds }).map((_, index) => ({ ...ROUNDS.PREVIOUS, + jurorsNumber: courtConfig.appealStepFactor ** (index + 1), })) } From 709795778ed734b7bbacb2d159711e9ea30e2017 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Thu, 9 Apr 2020 10:59:00 -0300 Subject: [PATCH 12/18] Update src/queries/jurorDrafts.js Co-Authored-By: Brett Sun --- src/queries/jurorDrafts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/queries/jurorDrafts.js b/src/queries/jurorDrafts.js index f2ad1a6c..851c2b95 100644 --- a/src/queries/jurorDrafts.js +++ b/src/queries/jurorDrafts.js @@ -38,7 +38,7 @@ export const JurorDraftsRewarded = gql` } ` -// Jurors drafts for juror with id `$id` created from `$from` +// Jurors drafts for juror with id `$id` created since `$from` export const JurorDraftsFrom = gql` subscription JurorDraftsFrom($id: ID!, $from: BigInt!) { juror(id: $id) { From c31743d1a0ff0ea300e5f27056f4dfa73045e25a Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Thu, 9 Apr 2020 11:38:04 -0300 Subject: [PATCH 13/18] Mock data: use new networkConfig --- src/mock/data/CourtConfig.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mock/data/CourtConfig.js b/src/mock/data/CourtConfig.js index ab8faf2e..ecff5f5a 100644 --- a/src/mock/data/CourtConfig.js +++ b/src/mock/data/CourtConfig.js @@ -1,4 +1,4 @@ -import { getNetwork } from '../../networks' +import { getNetworkConfig } from '../../networks' import { bigExp } from '../helper' import dayjs from 'dayjs' @@ -23,7 +23,7 @@ const feeToken = { } const courtConfig = { - id: getNetwork().court, + id: getNetworkConfig().court, currentTerm: CURRENT_TERM, termDuration: TERM_DURATION, // 4 minutes anjToken, From 03afe1ea91906ed8076b4b60d35f17419a06b1df Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Wed, 15 Apr 2020 13:44:17 -0300 Subject: [PATCH 14/18] Rever juror wieght conversion --- src/components/Dashboard/ANJLockedDistribution.js | 2 +- src/components/Dashboard/Balance.js | 4 ++-- src/utils/juror-draft-utils.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/Dashboard/ANJLockedDistribution.js b/src/components/Dashboard/ANJLockedDistribution.js index 4d462cba..d9b3ac0f 100644 --- a/src/components/Dashboard/ANJLockedDistribution.js +++ b/src/components/Dashboard/ANJLockedDistribution.js @@ -95,7 +95,7 @@ function Row({ label, isLabelLink, amount, symbol, weight }) { )} - {weight > 1 && `${weight}x `} {amount} {symbol} + {weight?.gt(1) && `${weight.toNumber()}x `} {amount} {symbol} ) diff --git a/src/components/Dashboard/Balance.js b/src/components/Dashboard/Balance.js index a95ffc2f..ebafcdf0 100644 --- a/src/components/Dashboard/Balance.js +++ b/src/components/Dashboard/Balance.js @@ -279,8 +279,8 @@ function useHelpAttributes(distribution) { const { lockedPerDispute } = distribution const onlyOneDispute = lockedPerDispute.length === 1 - const isJurorDraftedMultipleTimesSameDispute = lockedPerDispute.some( - lock => lock.weight > 1 + const isJurorDraftedMultipleTimesSameDispute = lockedPerDispute.some(lock => + lock.weight.gt(1) ) let text diff --git a/src/utils/juror-draft-utils.js b/src/utils/juror-draft-utils.js index 08184757..fa8965d2 100644 --- a/src/utils/juror-draft-utils.js +++ b/src/utils/juror-draft-utils.js @@ -29,11 +29,11 @@ export function isJurorCoherent(jurorDraft) { } export function transformJurorDataAttributes(jurorDraft) { - const { weight, round } = jurorDraft + const { round, weight } = jurorDraft return { ...jurorDraft, - weight, + weight: bigNum(weight), round: { ...round, number: parseInt(round.number, 10), From 37f99f96fccccaa43af012450b4693d96bbff121 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Wed, 15 Apr 2020 21:21:19 -0300 Subject: [PATCH 15/18] Do minor refactor and add comments --- src/graphql-exchanges.js | 2 +- src/hooks/useANJ.js | 3 +- src/mock/data/CourtConfig.js | 7 +--- src/mock/data/Disputes.js | 77 ++++++++++++++---------------------- src/mock/data/Jurors.js | 33 ++++++++++------ src/mock/data/Rounds.js | 6 +-- src/mock/data/index.js | 26 ++++++------ src/mock/exchanges/index.js | 32 +++++---------- src/mock/helper.js | 9 +++++ src/mock/models/Court.js | 16 +++++--- src/queries/jurorDrafts.js | 12 ------ 11 files changed, 100 insertions(+), 123 deletions(-) diff --git a/src/graphql-exchanges.js b/src/graphql-exchanges.js index 7deb96ed..af80a52f 100644 --- a/src/graphql-exchanges.js +++ b/src/graphql-exchanges.js @@ -3,7 +3,7 @@ import { SubscriptionClient } from 'subscriptions-transport-ws' import { captureMessage } from '@sentry/browser' import env from './environment' import endpoints from './endpoints' -import { mockFetchExchange, mockSubscriptionExchange } from './mock/exchanges/' +import { mockFetchExchange, mockSubscriptionExchange } from './mock/exchanges' const GRAPH_API_ENDPOINTS = endpoints() const subscriptionClient = new SubscriptionClient(GRAPH_API_ENDPOINTS[1], { diff --git a/src/hooks/useANJ.js b/src/hooks/useANJ.js index e42e812e..4ae127d6 100644 --- a/src/hooks/useANJ.js +++ b/src/hooks/useANJ.js @@ -53,7 +53,6 @@ export function useANJBalances() { // Use ANJ Locked distribution const lockedDistribution = useJurorLockedANJDistribution() - console.log('lockedDistribution', lockedDistribution) const convertedLockedBalance = useMemo(() => { return { amount: lockedBalance, distribution: lockedDistribution } }, [lockedBalance, lockedDistribution]) @@ -263,7 +262,7 @@ export function useJurorLockedANJDistribution() { lockDistribution.splice(index, 1, { ...elem, amount: elem.amount.add(lockedAmount), - weight: elem.weight + weight, + weight: elem.weight.add(weight), }) } else { lockDistribution.push({ diff --git a/src/mock/data/CourtConfig.js b/src/mock/data/CourtConfig.js index ecff5f5a..48c60bf1 100644 --- a/src/mock/data/CourtConfig.js +++ b/src/mock/data/CourtConfig.js @@ -2,7 +2,7 @@ import { getNetworkConfig } from '../../networks' import { bigExp } from '../helper' import dayjs from 'dayjs' -const TERM_DURATION = 60 // 1 minutes +const TERM_DURATION = 60 // 1 minute const CURRENT_TERM = 100 const COURT_START = dayjs() // Court started 100 terms ago .subtract(TERM_DURATION * CURRENT_TERM, 'second') @@ -49,10 +49,7 @@ const courtConfig = { appealConfirmCollateralFactor: '20000', minActiveBalance: bigExp('100'), penaltyPct: '1000', - modules: [ - // type - // address - ], + modules: [], subscriptions: { currentPeriod: '0', feeAmount: bigExp('10'), diff --git a/src/mock/data/Disputes.js b/src/mock/data/Disputes.js index 8a7011fa..77e92d46 100644 --- a/src/mock/data/Disputes.js +++ b/src/mock/data/Disputes.js @@ -3,43 +3,35 @@ import ROUNDS from './Rounds' import { hash256 } from '../../lib/web3-utils' import { dayjs } from '../../utils/date-utils' import { DisputeState } from '../types' +import { accounts } from '../helper' +const DEFAULT_SUBMITTER = accounts[6] +const DEFAULT_EVIDENCE = + '0x697066733a516d55765a53545a3958767156786b624446664a576e6644394759703376376d71353778464d563173774e34314c' const DEFAULT_IPFS_METADATA = 'QmPWJBAvLqdv5oNv7WvEFaghiMkWtcThDRJGFKu6kennpF/metadata.json' -// Data that tells the state of each dispute +// State of each dispute const DISPUTES_DATA = [ { state: DisputeState.Ruled, - metadata: JSON.stringify({ - description: 'Dispute finished (First round, In favor)', - metadata: DEFAULT_IPFS_METADATA, - }), + description: 'Dispute finished (First round, In favor)', rounds: [{ ...ROUNDS.ENDED.IN_FAVOR }], }, { state: DisputeState.Ruled, - metadata: JSON.stringify({ - description: - 'Dispute finished (First round, Refused to vote, Penalties Settled)', - metadata: DEFAULT_IPFS_METADATA, - }), + description: + 'Dispute finished (First round, Refused to vote, Penalties Settled)', rounds: [{ ...ROUNDS.ENDED.REFUSED }], }, { state: DisputeState.Ruled, - metadata: JSON.stringify({ - description: 'Dispute finished (First round, No one voted)', - metadata: DEFAULT_IPFS_METADATA, - }), + description: 'Dispute finished (First round, No one voted)', rounds: [{ ...ROUNDS.ENDED.NO_VOTES }], }, { state: DisputeState.Ruled, - metadata: JSON.stringify({ - description: 'Dispute finished (Final round, Against)', - metadata: DEFAULT_IPFS_METADATA, - }), + description: 'Dispute finished (Final round, Against)', rounds: [ ...populatePreviousRounds(courtConfig.maxRegularAppealRounds), { ...ROUNDS.ENDED.FINAL_ROUND }, @@ -47,58 +39,37 @@ const DISPUTES_DATA = [ }, { state: DisputeState.Adjudicating, - metadata: JSON.stringify({ - description: 'Dispute finished (Execute ruling)', - metadata: DEFAULT_IPFS_METADATA, - }), + description: 'Dispute finished (Execute ruling)', rounds: [{ ...ROUNDS.ENDED.IN_FAVOR }], }, { state: DisputeState.Drafting, - metadata: JSON.stringify({ - description: 'Dispute confirm appealed', - metadata: DEFAULT_IPFS_METADATA, - }), + description: 'Dispute confirm appealed', rounds: [populatePreviousRounds(1), { ...ROUNDS.CONFIRM_APPEALED }], }, { state: DisputeState.Adjudicating, - metadata: JSON.stringify({ - description: 'Dispute appealed', - metadata: DEFAULT_IPFS_METADATA, - }), + description: 'Dispute appealed', rounds: [{ ...ROUNDS.APPEALED }], }, { state: DisputeState.Adjudicating, - metadata: JSON.stringify({ - description: 'Dispute appealing', - metadata: DEFAULT_IPFS_METADATA, - }), + description: 'Dispute appealing', rounds: [{ ...ROUNDS.APPEALING }], }, { state: DisputeState.Adjudicating, - metadata: JSON.stringify({ - description: 'Dispute revealing', - metadata: DEFAULT_IPFS_METADATA, - }), + description: 'Dispute revealing', rounds: [{ ...ROUNDS.REVEALING }], }, { state: DisputeState.Adjudicating, - metadata: JSON.stringify({ - description: 'Dispute comitting', - metadata: DEFAULT_IPFS_METADATA, - }), + description: 'Dispute comitting', rounds: [{ ...ROUNDS.COMITTING }], }, { state: DisputeState.Evidence, - metadata: JSON.stringify({ - description: 'Dispute in evidence submission', - metadata: DEFAULT_IPFS_METADATA, - }), + description: 'Dispute in evidence submission', rounds: [{ ...ROUNDS.NOT_DRAFTED }], }, ] @@ -114,7 +85,7 @@ function generateDisputes() { const disputes = [] for (let i = 0; i < DISPUTES_DATA.length; i++) { - const { metadata, rounds, state } = DISPUTES_DATA[i] + const { description, rounds, state } = DISPUTES_DATA[i] const disputeId = String(i) const dispute = { @@ -124,8 +95,18 @@ function generateDisputes() { createdAt: dayjs().unix(), possibleRulings: 2, state, - metadata, + metadata: JSON.stringify({ + description, + metadata: DEFAULT_IPFS_METADATA, + }), lastRoundId: rounds.length - 1, + evidences: [ + { + submitter: DEFAULT_SUBMITTER, + data: DEFAULT_EVIDENCE, + createdAt: dayjs().unix(), + }, + ], } dispute.rounds = rounds.map((round, index) => ({ diff --git a/src/mock/data/Jurors.js b/src/mock/data/Jurors.js index b718ceea..2805faf4 100644 --- a/src/mock/data/Jurors.js +++ b/src/mock/data/Jurors.js @@ -1,37 +1,44 @@ import { accounts, bigExp } from '../helper' import { ANJMovementType } from '../types' +import courtConfig from './CourtConfig' const ACTIVE_BASE_BALANCE = '10000' -const numberOfJurors = 3 +const numberOfJurors = 4 + +const JUROR_DEFAULT_DATA = { + // Wallet balance (from the subgraph we actually don't get this amount from the juror entity itself + // but in this case since we are mocking data doesn't really matter) + walletBalance: '0', + activeBalance: '0', + lockedBalance: '0', + availableBalance: '0', + deactivationBalance: '0', + treasuryTokens: [], +} function generateJurors() { return accounts.slice(0, numberOfJurors).map((account, index) => { const activeBalance = bigExp(`${ACTIVE_BASE_BALANCE * (index + 1)}`) + // The last account will be a new active juror, which means that the activation must be effective on the next term + const newJuror = index === numberOfJurors - 1 + const activationEffectiveTermId = newJuror ? courtConfig.currentTerm + 1 : 1 + return { + ...JUROR_DEFAULT_DATA, id: account, - - // Wallet balance (from the subgraph we actually don't get this amount from the juror entity itself - // but in this case since we are mocking data doesn't really matter) - walletBalance: '0', activeBalance, - lockedBalance: '0', - availableBalance: '0', - deactivationBalance: '0', - treasuryTokens: [], // Mimicking ANJ activation from wallet anjMovements: [ { amount: activeBalance, - effectiveTermId: 3, - createdAt: '1', + effectiveTermId: activationEffectiveTermId, type: ANJMovementType.Activation, }, { amount: activeBalance, - effectiveTermId: 3, - createdAt: '1', + effectiveTermId: activationEffectiveTermId, type: ANJMovementType.Stake, }, ], diff --git a/src/mock/data/Rounds.js b/src/mock/data/Rounds.js index 7c0878d1..40815e06 100644 --- a/src/mock/data/Rounds.js +++ b/src/mock/data/Rounds.js @@ -17,7 +17,7 @@ const ROUNDS = { state: AdjudicationState.Ended, draftTermId: '50', // TODO: Find better calculation - // We'll create "mock" votes and appeals for previous rounds + // Create mock votes and appeals for previous rounds voteData: { winningOutcome: RulingOptions.Against, }, @@ -86,8 +86,8 @@ const ROUNDS = { ...DEFAULT_ROUND_DATA, }, - // Round ended In favor ENDED: { + // Round ended In favor IN_FAVOR: { state: AdjudicationState.Ended, jurorsNumber: courtConfig.firstRoundJurorsNumber, @@ -110,6 +110,7 @@ const ROUNDS = { ...DEFAULT_ROUND_DATA, }, + // Round ended no votes NO_VOTES: { state: AdjudicationState.Ended, jurorsNumber: courtConfig.firstRoundJurorsNumber, @@ -122,7 +123,6 @@ const ROUNDS = { winningOutcome: RulingOptions.Against, minority: RulingOptions.InFavor, }, - // settlePenalties: true, ...DEFAULT_ROUND_DATA, }, }, diff --git a/src/mock/data/index.js b/src/mock/data/index.js index abf00864..d0933806 100644 --- a/src/mock/data/index.js +++ b/src/mock/data/index.js @@ -20,7 +20,7 @@ export default { /** **** DASHBOARD STATE *****/ // Get Court JurorRegistry module - JurorsRegistryModule: ({ id }) => ({ + JurorsRegistryModule: () => ({ jurorsRegistryModule: court.jurorsRegistryModule, }), @@ -28,7 +28,9 @@ export default { JurorFeesClaimed: ({ owner }) => ({ feeMovements: [] }), - ActiveJurors: () => ({ jurors: [] }), + ActiveJurors: () => ({ + jurors: court.jurors.map(juror => ({ id: juror.id })), + }), // Get first activation movements for juror with id `id` JurorFirstANJActivationMovement: ({ id }) => { const { anjMovements } = court.getJuror(id) || {} @@ -97,15 +99,17 @@ export default { } }, - JurorDraftsFrom: ({ id, from }) => ({ - drafts: [], - }), - JurorDraftsRewarded: ({ id }) => ({ - juror: { - id: '', - drafts: [], - }, - }), + JurorDraftsFrom: ({ id, from }) => { + const juror = removeJurorCircularReferences(court.getJuror(id)) + + return { + juror: { + id, + drafts: juror.drafts.filter(draft => draft.createdAt >= from), + }, + } + }, + JurorDraftsNotRewarded: ({ id }) => { const juror = removeJurorCircularReferences(court.getJuror(id)) const { drafts = [] } = juror || {} diff --git a/src/mock/exchanges/index.js b/src/mock/exchanges/index.js index 39bf8feb..6f14b926 100644 --- a/src/mock/exchanges/index.js +++ b/src/mock/exchanges/index.js @@ -1,5 +1,5 @@ import { makeResult } from 'urql' -import { filter, make, merge, mergeMap, pipe, share, takeUntil } from 'wonka' +import { filter, make, merge, mergeMap, pipe, share } from 'wonka' import mockData from '../data' const OPERATION_DEFINITION = 'OperationDefinition' @@ -15,34 +15,26 @@ export const mockSubscriptionExchange = ({ forward }) => { } function handleOperation(operationType, forward) { - const isDesiredOperation = operation => { + const isOperationType = operation => { const { operationName } = operation return operationName === operationType } return ops$ => { const sharedOps$ = share(ops$) - const subscriptionResults$ = pipe( + const results$ = pipe( sharedOps$, - filter(isDesiredOperation), - mergeMap(operation => { - const { key } = operation - const teardown$ = pipe( - sharedOps$, - filter(op => op.operationName === 'teardown' && op.key === key) - ) - - return pipe(convertMockedData(operation), takeUntil(teardown$)) - }) + filter(isOperationType), + mergeMap(convertMockedData) ) const forward$ = pipe( sharedOps$, - filter(op => !isDesiredOperation(op)), + filter(op => !isOperationType(op)), forward ) - return merge([subscriptionResults$, forward$]) + return merge([results$, forward$]) } } @@ -52,9 +44,7 @@ const convertMockedData = operation => { node => node.kind === OPERATION_DEFINITION && node.name ) - const abortController = - typeof AbortController !== 'undefined' ? new AbortController() : undefined - + // Get the desired mocked data const convertedData = mockData[queryName.value](operation.variables) Promise.resolve() @@ -72,10 +62,6 @@ const convertMockedData = operation => { complete() }) - return () => { - if (abortController !== undefined) { - abortController.abort() - } - } + return () => {} }) } diff --git a/src/mock/helper.js b/src/mock/helper.js index 01543c8b..0d03d3ac 100644 --- a/src/mock/helper.js +++ b/src/mock/helper.js @@ -9,6 +9,8 @@ export const accounts = [ '0x22d491bde2303f2f43325b2108d26f1eaba1e32b', '0xe11ba2b4d45eaed5996cd0823791e0c93114882d', '0xd03ea8624c8c5987235048901fb614fdca89b117', + '0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC', + '0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9', ] export const getRandomNumber = (min, max) => @@ -52,6 +54,13 @@ export const getDraftTermId = (state, courtConfig) => { appealConfirmationTerms ) } +export const getTermStartTime = (termId, courtConfig) => { + const { termDuration, terms } = courtConfig + const secondsFromFirstTerm = termId * termDuration + + const firstTermStartTime = terms[0].startTime + return firstTermStartTime + secondsFromFirstTerm +} export const getMinActiveBalanceMultiple = ( activeBalance, diff --git a/src/mock/models/Court.js b/src/mock/models/Court.js index d62225c9..5a7ac94b 100644 --- a/src/mock/models/Court.js +++ b/src/mock/models/Court.js @@ -13,6 +13,7 @@ import { getMinActiveBalanceMultiple, getRandomNumber, pct, + getTermStartTime, } from '../helper' import { ANJMovementType, @@ -23,12 +24,12 @@ import { getRulingOptionNumber, } from '../types' -const DEFAULT_APPEAL_MAKER = accounts[3] -const DEFAULT_APPEAL_TAKER = accounts[4] +const DEFAULT_APPEAL_MAKER = accounts[4] +const DEFAULT_APPEAL_TAKER = accounts[5] const DEFAULT_APPEAL_DEPOSIT = bigExp('185') const DEFAULT_CONFIRM_APPEAL_DEPOSIT = bigExp('225') -export default class { +export default class Court { constructor() { this.config = courtConfig this.jurorsRegistryModule = JurorRegistry @@ -68,6 +69,7 @@ export default class { }) } + // Randomly draft the 3 possible jurors. draftJurors() { for (let i = 0; i < this.disputes.length; i++) { const dispute = this.disputes[i] @@ -104,7 +106,7 @@ export default class { // Select a juror const selectedJurorIndex = getRandomNumber( 0, - this.jurors.length - 1 + this.jurors.length - 2 ) const selectedJuror = this.jurors[selectedJurorIndex] @@ -141,6 +143,7 @@ export default class { round, juror, weight, + createdAt: getTermStartTime(round.draftTermId, this.config), } this.lockAnjAmount(juror, draftLockAmount) @@ -170,6 +173,7 @@ export default class { } } + // Create votes for each round flagged with `voteData` createVotes() { for (let i = 0; i < this.disputes.length; i++) { const dispute = this.disputes[i] @@ -255,6 +259,7 @@ export default class { } } + // Create appeals for each round flagged with `appealData` createAppeals() { for (let i = 0; i < this.disputes.length; i++) { const dispute = this.disputes[i] @@ -262,7 +267,7 @@ export default class { for (let roundId = 0; roundId < dispute.rounds.length; roundId++) { const round = dispute.rounds[roundId] - // flagData tells whether we should create appeals for the dispute in question + // `appealData` tells whether we should create appeals for the dispute in question if (!round.appealData) { continue } @@ -297,6 +302,7 @@ export default class { } } + // Settle penalties for each round that is flagged with `settlePenalties` prop settlePenalties() { for (let i = 0; i < this.disputes.length; i++) { const dispute = this.disputes[i] diff --git a/src/queries/jurorDrafts.js b/src/queries/jurorDrafts.js index 851c2b95..07a0fae8 100644 --- a/src/queries/jurorDrafts.js +++ b/src/queries/jurorDrafts.js @@ -26,18 +26,6 @@ export const JurorDraftsNotRewarded = gql` } ` -// First juror draft already rewarded -export const JurorDraftsRewarded = gql` - query JurorDraftsRewarded($id: ID!) { - juror(id: $id) { - id - drafts(where: { rewarded: true }, first: 1) { - id - } - } - } -` - // Jurors drafts for juror with id `$id` created since `$from` export const JurorDraftsFrom = gql` subscription JurorDraftsFrom($id: ID!, $from: BigInt!) { From ce8ed6e121c247443f266c9f67f96e38d767b01e Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Wed, 15 Apr 2020 21:43:29 -0300 Subject: [PATCH 16/18] Minor fixes --- src/hooks/useANJ.js | 1 - src/mock/data/Disputes.js | 2 +- src/mock/data/Jurors.js | 11 +++-------- src/mock/helper.js | 1 - src/mock/models/Court.js | 8 ++++---- 5 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/hooks/useANJ.js b/src/hooks/useANJ.js index 4ae127d6..c6e0015a 100644 --- a/src/hooks/useANJ.js +++ b/src/hooks/useANJ.js @@ -52,7 +52,6 @@ export function useANJBalances() { // Use ANJ Locked distribution const lockedDistribution = useJurorLockedANJDistribution() - const convertedLockedBalance = useMemo(() => { return { amount: lockedBalance, distribution: lockedDistribution } }, [lockedBalance, lockedDistribution]) diff --git a/src/mock/data/Disputes.js b/src/mock/data/Disputes.js index 77e92d46..f04fe46a 100644 --- a/src/mock/data/Disputes.js +++ b/src/mock/data/Disputes.js @@ -5,7 +5,7 @@ import { dayjs } from '../../utils/date-utils' import { DisputeState } from '../types' import { accounts } from '../helper' -const DEFAULT_SUBMITTER = accounts[6] +const DEFAULT_SUBMITTER = accounts[5] const DEFAULT_EVIDENCE = '0x697066733a516d55765a53545a3958767156786b624446664a576e6644394759703376376d71353778464d563173774e34314c' const DEFAULT_IPFS_METADATA = diff --git a/src/mock/data/Jurors.js b/src/mock/data/Jurors.js index 2805faf4..7de31db6 100644 --- a/src/mock/data/Jurors.js +++ b/src/mock/data/Jurors.js @@ -1,9 +1,8 @@ import { accounts, bigExp } from '../helper' import { ANJMovementType } from '../types' -import courtConfig from './CourtConfig' const ACTIVE_BASE_BALANCE = '10000' -const numberOfJurors = 4 +const numberOfJurors = 3 const JUROR_DEFAULT_DATA = { // Wallet balance (from the subgraph we actually don't get this amount from the juror entity itself @@ -20,10 +19,6 @@ function generateJurors() { return accounts.slice(0, numberOfJurors).map((account, index) => { const activeBalance = bigExp(`${ACTIVE_BASE_BALANCE * (index + 1)}`) - // The last account will be a new active juror, which means that the activation must be effective on the next term - const newJuror = index === numberOfJurors - 1 - const activationEffectiveTermId = newJuror ? courtConfig.currentTerm + 1 : 1 - return { ...JUROR_DEFAULT_DATA, id: account, @@ -33,12 +28,12 @@ function generateJurors() { anjMovements: [ { amount: activeBalance, - effectiveTermId: activationEffectiveTermId, + effectiveTermId: 1, type: ANJMovementType.Activation, }, { amount: activeBalance, - effectiveTermId: activationEffectiveTermId, + effectiveTermId: 1, type: ANJMovementType.Stake, }, ], diff --git a/src/mock/helper.js b/src/mock/helper.js index 0d03d3ac..4f91d474 100644 --- a/src/mock/helper.js +++ b/src/mock/helper.js @@ -10,7 +10,6 @@ export const accounts = [ '0xe11ba2b4d45eaed5996cd0823791e0c93114882d', '0xd03ea8624c8c5987235048901fb614fdca89b117', '0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC', - '0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9', ] export const getRandomNumber = (min, max) => diff --git a/src/mock/models/Court.js b/src/mock/models/Court.js index 5a7ac94b..d04e3803 100644 --- a/src/mock/models/Court.js +++ b/src/mock/models/Court.js @@ -12,8 +12,8 @@ import { getDraftTermId, getMinActiveBalanceMultiple, getRandomNumber, - pct, getTermStartTime, + pct, } from '../helper' import { ANJMovementType, @@ -24,8 +24,8 @@ import { getRulingOptionNumber, } from '../types' -const DEFAULT_APPEAL_MAKER = accounts[4] -const DEFAULT_APPEAL_TAKER = accounts[5] +const DEFAULT_APPEAL_MAKER = accounts[3] +const DEFAULT_APPEAL_TAKER = accounts[4] const DEFAULT_APPEAL_DEPOSIT = bigExp('185') const DEFAULT_CONFIRM_APPEAL_DEPOSIT = bigExp('225') @@ -106,7 +106,7 @@ export default class Court { // Select a juror const selectedJurorIndex = getRandomNumber( 0, - this.jurors.length - 2 + this.jurors.length - 1 ) const selectedJuror = this.jurors[selectedJurorIndex] From 7398a3379b9ee49cbaa4becf813be19210a633f2 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Wed, 15 Apr 2020 21:53:07 -0300 Subject: [PATCH 17/18] SubscriptionClient: Prevent reconnection attempt --- src/graphql-exchanges.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphql-exchanges.js b/src/graphql-exchanges.js index af80a52f..b909c38e 100644 --- a/src/graphql-exchanges.js +++ b/src/graphql-exchanges.js @@ -7,7 +7,7 @@ import { mockFetchExchange, mockSubscriptionExchange } from './mock/exchanges' const GRAPH_API_ENDPOINTS = endpoints() const subscriptionClient = new SubscriptionClient(GRAPH_API_ENDPOINTS[1], { - reconnect: true, + reconnect: !env('MOCK_DATA'), reconnectionAttempts: 10, }) From f0a7bfaae2abb006ebdf30296cc50ab3d4d4bf49 Mon Sep 17 00:00:00 2001 From: Fabrizio Vigevani Date: Sat, 25 Apr 2020 13:48:01 -0300 Subject: [PATCH 18/18] Initialize jurors balances realtive to config min active balance --- src/mock/data/Jurors.js | 10 +++++++--- src/mock/data/index.js | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/mock/data/Jurors.js b/src/mock/data/Jurors.js index 7de31db6..0ad824e5 100644 --- a/src/mock/data/Jurors.js +++ b/src/mock/data/Jurors.js @@ -1,7 +1,9 @@ -import { accounts, bigExp } from '../helper' +import { accounts } from '../helper' +import courtConfig from './CourtConfig' import { ANJMovementType } from '../types' +import { bigNum } from '../../lib/math-utils' -const ACTIVE_BASE_BALANCE = '10000' +const MIN_ACTIVE_BASE_MULTIPLIER = '10' const numberOfJurors = 3 const JUROR_DEFAULT_DATA = { @@ -17,7 +19,9 @@ const JUROR_DEFAULT_DATA = { function generateJurors() { return accounts.slice(0, numberOfJurors).map((account, index) => { - const activeBalance = bigExp(`${ACTIVE_BASE_BALANCE * (index + 1)}`) + const activeBalance = bigNum(courtConfig.minActiveBalance).mul( + MIN_ACTIVE_BASE_MULTIPLIER * (index + 1) + ) return { ...JUROR_DEFAULT_DATA, diff --git a/src/mock/data/index.js b/src/mock/data/index.js index d0933806..bdaf5832 100644 --- a/src/mock/data/index.js +++ b/src/mock/data/index.js @@ -101,11 +101,12 @@ export default { JurorDraftsFrom: ({ id, from }) => { const juror = removeJurorCircularReferences(court.getJuror(id)) + const { drafts = [] } = juror || {} return { juror: { id, - drafts: juror.drafts.filter(draft => draft.createdAt >= from), + drafts: drafts.filter(draft => draft.createdAt >= from), }, } },