diff --git a/lib/connect-wallet/config/chains.js b/lib/connect-wallet/config/chains.js index 99c0c4927..840aad42c 100644 --- a/lib/connect-wallet/config/chains.js +++ b/lib/connect-wallet/config/chains.js @@ -190,7 +190,7 @@ export const ChainLogos = { export const ChainAnalyticsColors = { DEFAULT: '4E7DD9', - 43113: '21AD8C', + 43113: 'E84142', 84531: '4E7DD9', 42161: '21AD8C', 1: '4E7DD9', @@ -206,6 +206,10 @@ export const ChainColorsRGB = { 56: '202, 133, 4' } +export const getHexColorByChain = (chainId) => { + return `#${ChainAnalyticsColors[chainId] || ChainAnalyticsColors.DEFAULT}` +} + export const explorer = { address: { 56: 'https://bscscan.com/address/%s', diff --git a/lib/dates.js b/lib/dates.js index c4e7f1ccf..5bb6aab75 100644 --- a/lib/dates.js +++ b/lib/dates.js @@ -23,7 +23,7 @@ function getMonthsBetweenDates (locale, startDate, endDate) { return months } -function formatDateByLocale (locale, date, overrides = {}) { +function formatDateByLocale (locale = 'en', date, overrides = {}) { return new Date(date).toLocaleString(locale, { month: 'short', year: '2-digit', ...overrides }) } diff --git a/src/common/LiquidityForms/ProvideLiquidityForm.jsx b/src/common/LiquidityForms/ProvideLiquidityForm.jsx index 812c9f1e3..326a81a19 100644 --- a/src/common/LiquidityForms/ProvideLiquidityForm.jsx +++ b/src/common/LiquidityForms/ProvideLiquidityForm.jsx @@ -28,7 +28,6 @@ import { Routes } from '@/src/config/routes' import { useAppConstants } from '@/src/context/AppConstants' import { useNetwork } from '@/src/context/Network' import { useCalculatePods } from '@/src/hooks/useCalculatePods' -import { useCoverActiveReportings } from '@/src/hooks/useCoverActiveReportings' import { useProvideLiquidity } from '@/src/hooks/useProvideLiquidity' import { convertFromUnits, @@ -44,6 +43,7 @@ import { Trans } from '@lingui/macro' import { useLingui } from '@lingui/react' +import { useActiveReportings } from '@/src/hooks/useActiveReportings' export const ProvideLiquidityForm = ({ coverKey, info, isDiversified, underwrittenProducts }) => { const [lqValue, setLqValue] = useState('') @@ -107,7 +107,7 @@ export const ProvideLiquidityForm = ({ coverKey, info, isDiversified, underwritt podAddress: vaultTokenAddress }) - const { data: activeReportings } = useCoverActiveReportings({ coverKey }) + const { data: activeReportings } = useActiveReportings() const requiredStake = toBN(minStakeToAddLiquidity).minus(myStake).toString() @@ -184,10 +184,12 @@ export const ProvideLiquidityForm = ({ coverKey, info, isDiversified, underwritt const hasBothAllowances = hasLqTokenAllowance && hasNPMTokenAllowance - if (activeReportings.length > 0) { - const status = activeReportings[0].status - const incidentDate = activeReportings[0].incidentDate - const productKey = activeReportings[0].productKey + // @todo: Instead we could expose `isCoverNormalInternal` from smart contracts + const currentCoverActiveIncidents = activeReportings.incidentReports.filter(x => { return x.coverKey === coverKey }) + if (currentCoverActiveIncidents.length > 0) { + const status = 'Reporting' // @todo: Update status to be dynamic from API or smart contracts + const incidentDate = currentCoverActiveIncidents[0].incidentDate + const productKey = currentCoverActiveIncidents[0].productKey const statusLink = ( { - return ` - { - userPolicies( - skip: ${limit * (page - 1)} - first: ${limit} - where: { - expiresOn_gt: "${startOfMonth}" - account: "${account}" - coverKey: "${coverKey}" - productKey: "${productKey}" - } - ) { - id - coverKey - productKey - cxToken { - id - creationDate - expiryDate - tokenSymbol - tokenDecimals - } - totalAmountToCover - expiresOn - cover { - id - } - } - } - ` -} - -export const useActivePoliciesByCover = ({ - coverKey, - productKey, - limit, - page -}) => { - const [data, setData] = useState({ - userPolicies: [] - }) - const [loading, setLoading] = useState(false) - const [hasMore, setHasMore] = useState(true) - - const { networkId } = useNetwork() - const { account } = useWeb3React() - const fetchActivePoliciesByCover = useSubgraphFetch( - 'useActivePoliciesByCover' - ) - - useEffect(() => { - if (!networkId || !account) { - return - } - - const startOfMonth = DateLib.toUnix(DateLib.getSomInUTC(Date.now())) - - setLoading(true) - - fetchActivePoliciesByCover( - networkId, - getQuery(limit, page, startOfMonth, account, coverKey, productKey) - ) - .then((_data) => { - if (!_data) { return } - - const isLastPage = - _data.userPolicies.length === 0 || _data.userPolicies.length < limit - - if (isLastPage) { - setHasMore(false) - } - - setData((prev) => { - return { - userPolicies: [...prev.userPolicies, ..._data.userPolicies] - } - }) - }) - .catch((err) => { - console.error(err) - }) - .finally(() => { - setLoading(false) - }) - }, [ - account, - coverKey, - fetchActivePoliciesByCover, - limit, - networkId, - page, - productKey - ]) - - const totalActiveProtection = useMemo(() => { - return sumOf( - '0', - ...data.userPolicies.map((x) => { return x.totalAmountToCover || '0' }) - ) - }, [data.userPolicies]) - - return { - data: { - activePolicies: data.userPolicies, - totalActiveProtection - }, - loading, - hasMore - } -} diff --git a/src/hooks/useActiveReportings.jsx b/src/hooks/useActiveReportings.jsx index 957f25ba2..071d01864 100644 --- a/src/hooks/useActiveReportings.jsx +++ b/src/hooks/useActiveReportings.jsx @@ -1,53 +1,36 @@ import { useState, useEffect, useCallback } from 'react' import { useNetwork } from '@/src/context/Network' import { CARDS_PER_PAGE } from '@/src/config/constants' -import { useSubgraphFetch } from '@/src/hooks/useSubgraphFetch' - -const getQuery = (itemsToSkip) => { - return ` - { - incidentReports( - skip: ${itemsToSkip} - first: ${CARDS_PER_PAGE} - orderBy: incidentDate - orderDirection: desc - where:{ - finalized: false - } - ) { - id - coverKey - productKey - incidentDate - resolutionDeadline - resolved - finalized - status - resolutionTimestamp - } - } - ` -} +import { getActiveIncidents } from '@/src/services/api/consensus/active' export const useActiveReportings = () => { const [data, setData] = useState({ incidentReports: [] }) - const [loading, setLoading] = useState(false) + const [loading, setLoading] = useState(true) const [itemsToSkip, setItemsToSkip] = useState(0) const [hasMore, setHasMore] = useState(true) const { networkId } = useNetwork() - const fetchActiveReportings = useSubgraphFetch('useActiveReportings') useEffect(() => { + setData({ incidentReports: [] }) + setItemsToSkip(0) + setHasMore(true) + setLoading(true) + }, [networkId]) + + useEffect(() => { + let ignore = false + setLoading(true) - fetchActiveReportings(networkId, getQuery(itemsToSkip)) + // @ts-ignore + getActiveIncidents(networkId, itemsToSkip) .then((_data) => { - if (!_data) { return } + if (ignore || !_data) { return } const isLastPage = - _data.incidentReports.length === 0 || - _data.incidentReports.length < CARDS_PER_PAGE + _data.length === 0 || + _data.length < CARDS_PER_PAGE if (isLastPage) { setHasMore(false) @@ -55,7 +38,7 @@ export const useActiveReportings = () => { setData((prev) => { return { - incidentReports: [...prev.incidentReports, ..._data.incidentReports] + incidentReports: [...prev.incidentReports, ..._data] } }) }) @@ -65,7 +48,11 @@ export const useActiveReportings = () => { .finally(() => { setLoading(false) }) - }, [fetchActiveReportings, itemsToSkip, networkId]) + + return () => { + ignore = true + } + }, [itemsToSkip, networkId]) const handleShowMore = useCallback(() => { setItemsToSkip((prev) => { return prev + CARDS_PER_PAGE }) diff --git a/src/hooks/useConsensusInsights.jsx b/src/hooks/useConsensusInsights.jsx index 1ffa26007..3259d5972 100644 --- a/src/hooks/useConsensusInsights.jsx +++ b/src/hooks/useConsensusInsights.jsx @@ -5,33 +5,7 @@ import { } from 'react' import { useNetwork } from '@/src/context/Network' -import { getSubgraphData } from '@/src/services/subgraph' - -const getQuery = () => { - return ` - { - incidentReports( - orderBy: incidentDate - orderDirection: desc - where:{ - finalized: false - } - ) { - id - coverKey - productKey - incidentDate - resolutionDeadline - resolved - finalized - status - resolutionTimestamp - totalRefutedStake - totalAttestedStake - } - } -` -} +import { getActiveIncidents } from '@/src/services/api/consensus/active' export const useConsensusInsights = () => { const [data, setData] = useState({ @@ -49,13 +23,13 @@ export const useConsensusInsights = () => { setLoading(true) - getSubgraphData(networkId, getQuery()) + getActiveIncidents(networkId) .then((_data) => { if (!_data) { return } setData(() => { return { - incidentReports: _data.incidentReports + incidentReports: _data } }) diff --git a/src/hooks/useCoverActiveReportings.jsx b/src/hooks/useCoverActiveReportings.jsx deleted file mode 100644 index 9f2916681..000000000 --- a/src/hooks/useCoverActiveReportings.jsx +++ /dev/null @@ -1,61 +0,0 @@ -import { - useEffect, - useState -} from 'react' - -import { getNetworkId } from '@/src/config/environment' -import { useSubgraphFetch } from '@/src/hooks/useSubgraphFetch' - -const getQuery = (coverKey) => { - return ` - { - incidentReports(where: { - coverKey: "${coverKey}" - finalized: false - }) { - id - status - productKey - incidentDate - } - } - ` -} - -// @todo: Instead we could expose `isCoverNormalInternal` from smart contracts -/** - * - * @param {object} param - * @param {string} param.coverKey - * @returns - */ -export const useCoverActiveReportings = ({ coverKey }) => { - const [data, setData] = useState([]) - const [loading, setLoading] = useState(false) - const fetchCoverActiveReportings = useSubgraphFetch( - 'useCoverActiveReportings' - ) - - useEffect(() => { - if (!coverKey || !getNetworkId()) { - return - } - - setLoading(true) - fetchCoverActiveReportings(getNetworkId(), getQuery(coverKey)) - .then((result) => { - if (!result) { - return - } - - return setData(result.incidentReports) - }) - .catch((e) => { return console.error(e) }) - .finally(() => { return setLoading(false) }) - }, [coverKey, fetchCoverActiveReportings]) - - return { - data, - loading - } -} diff --git a/src/hooks/useCoverEarningInsights.jsx b/src/hooks/useCoverEarningInsights.jsx index ae5a27627..2981a2030 100644 --- a/src/hooks/useCoverEarningInsights.jsx +++ b/src/hooks/useCoverEarningInsights.jsx @@ -1,4 +1,5 @@ import { + useCallback, useEffect, useMemo, useState @@ -9,9 +10,10 @@ import { getMonthsBetweenDates } from '@/lib/dates' import { useAppConstants } from '@/src/context/AppConstants' -import { useProtocolMonthData } from '@/src/hooks/useProtocolMonthData' import { useLanguageContext } from '@/src/i18n/i18n' import { toBN } from '@/utils/bn' +import { getCoverEarnings } from '@/src/services/api/home/charts/cover-earnings' +import { useNetwork } from '@/src/context/Network' const getInitialDateRange = (from) => { const currentDate = from @@ -30,7 +32,10 @@ const getInitialDateRange = (from) => { function useCoverEarningInsights () { const [dateRange, setDateRange] = useState(getInitialDateRange(new Date())) - const { data, loading, fetchData } = useProtocolMonthData() + const { networkId } = useNetwork() + + const [loading, setLoading] = useState(true) + const [data, setData] = useState([]) const { liquidityTokenDecimals } = useAppConstants() @@ -54,6 +59,21 @@ function useCoverEarningInsights () { setDateRange(getInitialDateRange(newInitialDate)) } + const fetchData = useCallback(() => { + getCoverEarnings(networkId) + .then((_data) => { + if (_data) { + setData(_data) + } + }) + .catch((err) => { + console.error(err) + }) + .finally(() => { + setLoading(false) + }) + }, [networkId]) + useEffect(() => { if (data) { const newLabels = getMonthsBetweenDates(locale, dateRange[0], dateRange[1]) @@ -61,14 +81,14 @@ function useCoverEarningInsights () { setLabels(newLabels) const monthDataInRange = data.filter((monthData) => { - const monthDate = new Date(monthData.id) + const monthDate = new Date(monthData.startDate) const id = new Date(monthDate.getTime() + monthDate.getTimezoneOffset() * 60 * 1000) return id >= dateRange[0] && id <= dateRange[1] }).map(monthData => { return { ...monthData, - id: formatDateByLocale(locale, new Date(monthData.id), { timeZone: 'UTC' }) + id: formatDateByLocale(locale, monthData.endDate, { timeZone: 'UTC' }) } }) @@ -76,7 +96,7 @@ function useCoverEarningInsights () { const foundMonth = monthDataInRange.find(monthData => { return monthData.id === lbl }) if (foundMonth) { - return foundMonth.nonCumulativeCoverFee + return foundMonth.totalCoverFeeEarned } return '0' diff --git a/src/hooks/useFetchCoverProductActiveReportings.jsx b/src/hooks/useFetchCoverProductActiveReportings.jsx deleted file mode 100644 index a7d74606e..000000000 --- a/src/hooks/useFetchCoverProductActiveReportings.jsx +++ /dev/null @@ -1,59 +0,0 @@ -import { useState, useEffect } from 'react' -import { getNetworkId } from '@/src/config/environment' -import { useSubgraphFetch } from '@/src/hooks/useSubgraphFetch' - -const getQuery = (coverKey, productKey) => { - return ` - { - incidentReports(where: { - coverKey: "${coverKey}" - productKey: "${productKey}" - finalized: false - }) { - id - reporterInfo - coverKey - productKey - incidentDate - } - } - ` -} - -/** - * - * @param {object} param - * @param {string} param.coverKey - * @param {string} param.productKey - * @returns - */ -export const useFetchCoverProductActiveReportings = ({ - coverKey, - productKey -}) => { - const [data, setData] = useState([]) - const [loading, setLoading] = useState(false) - const fetchCoverProductActiveReportings = useSubgraphFetch( - 'useFetchCoverProductActiveReportings' - ) - - useEffect(() => { - if (productKey && coverKey) { - setLoading(true) - fetchCoverProductActiveReportings( - getNetworkId(), - getQuery(coverKey, productKey) - ) - .then(({ incidentReports }) => { - setData(incidentReports) - }) - .catch((e) => { return console.error(e) }) - .finally(() => { return setLoading(false) }) - } - }, [coverKey, fetchCoverProductActiveReportings, productKey]) - - return { - data, - loading - } -} diff --git a/src/hooks/useFetchReport.jsx b/src/hooks/useFetchReport.jsx index 16f014275..48d4f40b6 100644 --- a/src/hooks/useFetchReport.jsx +++ b/src/hooks/useFetchReport.jsx @@ -1,64 +1,11 @@ import { useCallback, useEffect, - useMemo, useState } from 'react' -import { getNetworkId } from '@/src/config/environment' -import { useSubgraphFetch } from '@/src/hooks/useSubgraphFetch' - -const getQuery = (reportId) => { - return ` - { - incidentReport( - id: "${reportId}" - ) { - id - coverKey - productKey - incidentDate - resolutionDeadline - resolved - resolveTransaction{ - timestamp - } - emergencyResolved - emergencyResolveTransaction{ - timestamp - } - finalized - status - decision - resolutionTimestamp - claimBeginsFrom - claimExpiresAt - reporter - reporterInfo - reporterStake - disputer - disputerInfo - disputerStake - totalAttestedStake - totalAttestedCount - totalRefutedStake - totalRefutedCount - reportTransaction { - id - timestamp - } - disputeTransaction { - id - timestamp - } - reportIpfsHash - disputeIpfsHash - reportIpfsData - disputeIpfsData - } - } - ` -} +import { getIncidentDetail } from '@/src/services/api/consensus/detail' +import { useNetwork } from '@/src/context/Network' /** * @@ -70,31 +17,25 @@ const getQuery = (reportId) => { */ export const useFetchReport = ({ coverKey, productKey, incidentDate }) => { const [data, setData] = useState(null) - const [loading, setLoading] = useState(false) - const fetchReport = useSubgraphFetch('useFetchReport') + const [loading, setLoading] = useState(true) - const reportId = useMemo(() => { - if (!coverKey || !productKey || !incidentDate) { - return null - } - - return `${coverKey}-${productKey}-${incidentDate}` - }, [coverKey, incidentDate, productKey]) + const { networkId } = useNetwork() - const getData = useCallback(async () => { - if (!reportId) { + const getData = useCallback(() => { + if (!coverKey || !productKey || !incidentDate) { return } - try { - const data = await fetchReport(getNetworkId(), getQuery(reportId)) - if (data && data.incidentReport) { - setData(data.incidentReport) - } - } catch (e) { - console.error(e) - } - }, [fetchReport, reportId]) + return getIncidentDetail(networkId, coverKey, productKey, incidentDate) + .then(data => { + if (data) { + setData(data) + } + }) + .catch(error => { + console.error(error) + }) + }, [coverKey, productKey, incidentDate, networkId]) useEffect(() => { async function updateData () { diff --git a/src/hooks/useFetchReportsByKeyAndDate.jsx b/src/hooks/useFetchReportsByKeyAndDate.jsx deleted file mode 100644 index d0e3e2b05..000000000 --- a/src/hooks/useFetchReportsByKeyAndDate.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import { useState, useEffect } from 'react' -import { getNetworkId } from '@/src/config/environment' -import { useSubgraphFetch } from '@/src/hooks/useSubgraphFetch' - -const getQuery = (coverKey, incidentDate) => { - return ` - { - incidentReports ( - where: { - coverKey: "${coverKey}" - incidentDate: "${incidentDate}" - decision: true - resolved: true - } - ) { - id - claimExpiresAt - } - } - - ` -} - -/** - * - * @param {object} param - * @param {string} param.coverKey - * @param {string | string[]} param.incidentDate - * @returns - */ -export const useFetchReportsByKeyAndDate = ({ coverKey, incidentDate }) => { - const [data, setData] = useState([]) - const [loading, setLoading] = useState(false) - const fetchReportsByKeyAndDate = useSubgraphFetch( - 'useFetchReportsByKeyAndDate' - ) - - useEffect(() => { - if (coverKey && incidentDate) { - setLoading(true) - fetchReportsByKeyAndDate(getNetworkId(), getQuery(coverKey, incidentDate)) - .then(({ incidentReports }) => { - setData(incidentReports) - }) - .catch((e) => { return console.error(e) }) - .finally(() => { return setLoading(false) }) - } - }, [coverKey, fetchReportsByKeyAndDate, incidentDate]) - - return { - data, - loading - } -} diff --git a/src/hooks/useProtectionChartData.jsx b/src/hooks/useProtectionChartData.jsx index 83431121b..4172e7f28 100644 --- a/src/hooks/useProtectionChartData.jsx +++ b/src/hooks/useProtectionChartData.jsx @@ -1,25 +1,31 @@ import { useCallback, + useMemo, useRef, useState } from 'react' +import { useRouter } from 'next/router' + import { useNetwork } from '@/src/context/Network' import { getProtectionByMonth } from '@/src/services/api/home/charts/protection-by-month' -import { sortDates } from '@/utils/sorting' +import { formatDateByLocale } from '@/lib/dates' -const getAggregatedDataWithLabels = (data = []) => { +const getAggregatedDataWithLabels = (data = [], locale) => { const aggregatedData = {} let labels = [] data.forEach(item => { + const label = formatDateByLocale(locale, new Date(item.expiresOn || item.endDate), { timeZone: 'UTC' }) + const chain = item.chainId if (!aggregatedData[chain]) { aggregatedData[chain] = [] } aggregatedData[chain].push({ - label: item.expiry, + label, + date: item.expiresOn || item.endDate, protection: item.protection, income: item.income, expired: item.expired, @@ -28,7 +34,6 @@ const getAggregatedDataWithLabels = (data = []) => { incomePercent: item.feeRate }) - const label = item.expiry if (!labels.includes(label)) { labels.push(label) } }) @@ -54,19 +59,18 @@ const getAggregatedDataWithLabels = (data = []) => { Object.keys(aggregatedData).forEach(chain => { const arr = aggregatedData[chain] - const sortedArr = sortDates( - arr, - x => { return x.label } - ) + + // @ts-ignore + const sortedArr = arr.sort((a, b) => { return new Date(b.date) - new Date(a.date) }) aggregatedData[chain] = sortedArr }) - // @todo: Remove this once the backend API is updated - Object.keys(aggregatedData).forEach(chain => { - aggregatedData[chain].reverse() - }) + const keys = Object.keys(aggregatedData) + + if (keys.length === 0) { return { data: {}, labels: [] } } + + const key = keys[0] - const key = Object.keys(aggregatedData)[0] labels = aggregatedData[key].map(i => { return i.label }) return { @@ -78,8 +82,9 @@ const getAggregatedDataWithLabels = (data = []) => { export const useProtectionChartData = () => { const fetched = useRef(false) const [loading, setLoading] = useState(false) - const [data, setData] = useState(null) - const [labels, setLabels] = useState([]) + const [_data, _setData] = useState(undefined) + + const { locale } = useRouter() const { networkId } = useNetwork() @@ -91,11 +96,9 @@ export const useProtectionChartData = () => { try { const _data = await getProtectionByMonth(networkId) - const { labels, data } = getAggregatedDataWithLabels(_data) + _setData(_data) - setData(data) fetched.current = true - setLabels(labels) } catch (err) { console.error(err) } @@ -103,6 +106,10 @@ export const useProtectionChartData = () => { setLoading(false) }, [networkId]) + const { data, labels } = useMemo(() => { + return getAggregatedDataWithLabels(_data, locale) + }, [locale, _data]) + return { fetchMonthlyProtectionData, loading, diff --git a/src/hooks/useProtocolMonthData.jsx b/src/hooks/useProtocolMonthData.jsx deleted file mode 100644 index e74e22f32..000000000 --- a/src/hooks/useProtocolMonthData.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import { - useCallback, - useRef, - useState -} from 'react' - -import { useNetwork } from '@/src/context/Network' -import { - getGroupedProtocolMonthData -} from '@/src/services/aggregated-stats/protocol' - -export const useProtocolMonthData = (cache = true) => { - const [data, setData] = useState(null) - const [loading, setLoading] = useState(false) - - const fetched = useRef(false) - - const { networkId } = useNetwork() - - const fetchData = useCallback(() => { - if ((cache && fetched.current)) { return } - - setLoading(true) - - getGroupedProtocolMonthData(networkId) - .then((_data) => { - if (!_data) { return } - - setData(_data) - - fetched.current = true - }) - .catch((err) => { - console.error(err) - }) - .finally(() => { - setLoading(false) - }) - }, [cache, networkId]) - - return { - data, - loading, - fetchData - } -} diff --git a/src/hooks/useResolvedReportings.jsx b/src/hooks/useResolvedReportings.jsx index 359fd649a..8b9c46ac6 100644 --- a/src/hooks/useResolvedReportings.jsx +++ b/src/hooks/useResolvedReportings.jsx @@ -1,69 +1,36 @@ -import { - useCallback, - useEffect, - useState -} from 'react' - -import { CARDS_PER_PAGE } from '@/src/config/constants' +import { useState, useEffect, useCallback } from 'react' import { useNetwork } from '@/src/context/Network' -import { useSubgraphFetch } from '@/src/hooks/useSubgraphFetch' - -const getQuery = (itemsToSkip) => { - return ` - { - incidentReports( - skip: ${itemsToSkip} - first: ${CARDS_PER_PAGE} - orderBy: incidentDate - orderDirection: desc - where:{ - resolved: true - } - ) { - id - coverKey - productKey - incidentDate - resolutionDeadline - resolved - emergencyResolved - emergencyResolveTransaction{ - timestamp - } - resolveTransaction{ - timestamp - } - finalized - status - resolutionTimestamp - totalAttestedStake - totalRefutedStake - } - } - ` -} +import { CARDS_PER_PAGE } from '@/src/config/constants' +import { getResolvedIncidents } from '@/src/services/api/consensus/resolved' export const useResolvedReportings = () => { - const [data, setData] = useState({ - incidentReports: [] - }) - const [loading, setLoading] = useState(false) + const [data, setData] = useState({ incidentReports: [] }) + const [loading, setLoading] = useState(true) const [itemsToSkip, setItemsToSkip] = useState(0) const [hasMore, setHasMore] = useState(true) const { networkId } = useNetwork() - const fetchResolvedReportings = useSubgraphFetch('useResolvedReportings') useEffect(() => { + setData({ incidentReports: [] }) + setItemsToSkip(0) + setHasMore(true) setLoading(true) + }, [networkId]) - fetchResolvedReportings(networkId, getQuery(itemsToSkip)) + useEffect(() => { + let ignore = false + + setLoading(true) + + // @ts-ignore + getResolvedIncidents(networkId, itemsToSkip) .then((_data) => { - if (!_data) { return } + if (ignore || !_data) { return } const isLastPage = - _data.incidentReports.length === 0 || - _data.incidentReports.length < CARDS_PER_PAGE + _data.length === 0 || + _data.length < CARDS_PER_PAGE if (isLastPage) { setHasMore(false) @@ -71,7 +38,7 @@ export const useResolvedReportings = () => { setData((prev) => { return { - incidentReports: [...prev.incidentReports, ..._data.incidentReports] + incidentReports: [...prev.incidentReports, ..._data] } }) }) @@ -81,7 +48,11 @@ export const useResolvedReportings = () => { .finally(() => { setLoading(false) }) - }, [fetchResolvedReportings, itemsToSkip, networkId]) + + return () => { + ignore = true + } + }, [itemsToSkip, networkId]) const handleShowMore = useCallback(() => { setItemsToSkip((prev) => { return prev + CARDS_PER_PAGE }) diff --git a/src/hooks/useValidReport.jsx b/src/hooks/useValidReport.jsx deleted file mode 100644 index 46f8db39e..000000000 --- a/src/hooks/useValidReport.jsx +++ /dev/null @@ -1,64 +0,0 @@ -import { useState, useEffect } from 'react' -import { useNetwork } from '@/src/context/Network' -import { useSubgraphFetch } from '@/src/hooks/useSubgraphFetch' - -const isValidTimestamp = (_unix) => { return !!_unix && _unix !== '0' } - -const getQuery = (start, end, coverKey, productKey) => { - return ` - { - incidentReports( - where: { - incidentDate_gt: "${start}", - incidentDate_lt: "${end}", - coverKey: "${coverKey}" - productKey: "${productKey}" - }, - orderBy: incidentDate, - orderDirection: desc - ) { - incidentDate - resolutionDeadline - status - claimBeginsFrom - claimExpiresAt - } - } - ` -} - -export const useValidReport = ({ start, end, coverKey, productKey }) => { - const [data, setData] = useState({ - incidentReports: [] - }) - const [loading, setLoading] = useState(false) - const { networkId } = useNetwork() - const fetchValidReport = useSubgraphFetch('useValidReport') - - useEffect(() => { - if (!isValidTimestamp(start) || !isValidTimestamp(end)) { - return - } - - setLoading(true) - - fetchValidReport(networkId, getQuery(start, end, coverKey, productKey)) - .then((_data) => { - if (!_data) { return } - setData(_data) - }) - .catch((err) => { - console.error(err) - }) - .finally(() => { - setLoading(false) - }) - }, [coverKey, end, fetchValidReport, networkId, productKey, start]) - - return { - data: { - report: data?.incidentReports[0] - }, - loading - } -} diff --git a/src/modules/home/Hero.jsx b/src/modules/home/Hero.jsx index 23da4e32f..56f43c27b 100644 --- a/src/modules/home/Hero.jsx +++ b/src/modules/home/Hero.jsx @@ -154,7 +154,7 @@ export const HomeHero = ({ breadcrumbs = [], title = '' }) => { // Active Protection (or) Commitment name: t(i18n)`Coverage`, amount: formatCurrency( - aggregated.totalCoveredAmount, + aggregated.activeCoveredAmount, locale ).short }, diff --git a/src/modules/insights/Consensus.jsx b/src/modules/insights/Consensus.jsx index cd1065ca8..5bedad3b1 100644 --- a/src/modules/insights/Consensus.jsx +++ b/src/modules/insights/Consensus.jsx @@ -20,7 +20,6 @@ import { getCoverImgSrc, isValidProduct } from '@/src/helpers/cover' -import { convertFromUnits } from '@/utils/bn' import { formatCurrency } from '@/utils/formatter/currency' import { t } from '@lingui/macro' import { useLingui } from '@lingui/react' @@ -49,7 +48,7 @@ const renderAttestedStake = (row, { locale, NPMTokenSymbol }) => { Yes @@ -66,7 +65,7 @@ const renderRefutedStake = (row, { locale, NPMTokenSymbol }) => { No @@ -78,10 +77,9 @@ const renderRefutedStake = (row, { locale, NPMTokenSymbol }) => { const StakeText = ({ amount, locale, NPMTokenSymbol }) => { const textForm = formatCurrency( - convertFromUnits(amount), + amount, locale, NPMTokenSymbol, - true, true ) @@ -115,9 +113,9 @@ const renderCover = (row, _extraData) => { ) } -const renderProtection = (row, { liquidityTokenDecimals, locale }) => { +const renderProtection = (row, { locale }) => { const protection = formatCurrency( - convertFromUnits(row.coverOrProductData.commitment, liquidityTokenDecimals).toString(), + row.coverOrProductData.commitment.toString(), locale ) diff --git a/src/modules/insights/ConsensusDetails.jsx b/src/modules/insights/ConsensusDetails.jsx index 3c091709a..2cec8445e 100644 --- a/src/modules/insights/ConsensusDetails.jsx +++ b/src/modules/insights/ConsensusDetails.jsx @@ -47,8 +47,8 @@ function ConsensusDetails ({ consensusIndex, setConsensusIndex, data }) { const coverName = coverOrProductData?.coverInfoDetails.coverName || coverOrProductData?.coverInfoDetails.projectName const projectOrProductName = isDiversified ? coverOrProductData?.productInfoDetails?.productName : coverName - const totalAttested = report.totalAttestedStake - const totalRefuted = report.totalRefutedStake + const totalAttested = report.totalAttestationStake + const totalRefuted = report.totalRefutationStake const isResolved = report.resolved const status = identifyStatus(report.status) @@ -73,7 +73,7 @@ function ConsensusDetails ({ consensusIndex, setConsensusIndex, data }) { const formattedProtection = formatCurrency( convertFromUnits(protection, liquidityTokenDecimals).toString(), - router.locale, 'USD', false, true + router.locale, 'USD', false ) const efficiency = formatPercent( @@ -94,26 +94,23 @@ function ConsensusDetails ({ consensusIndex, setConsensusIndex, data }) { } const refuted = formatCurrency( - convertFromUnits(totalRefuted), + totalRefuted, router.locale, NPMTokenSymbol, - true, true ) const attested = formatCurrency( - convertFromUnits(totalAttested), + totalAttested, router.locale, NPMTokenSymbol, - true, true ) const totalStakeText = formatCurrency( - convertFromUnits(totalStake), + totalStake, router.locale, NPMTokenSymbol, - true, true ) @@ -121,8 +118,7 @@ function ConsensusDetails ({ consensusIndex, setConsensusIndex, data }) { convertFromUnits(liquidity, liquidityTokenDecimals).toString(), router.locale, 'USD', - false, - true + false ) return ( diff --git a/src/modules/insights/HistoricalRoi.jsx b/src/modules/insights/HistoricalRoi.jsx index 601f8ee1b..40994ecf3 100644 --- a/src/modules/insights/HistoricalRoi.jsx +++ b/src/modules/insights/HistoricalRoi.jsx @@ -5,8 +5,8 @@ import { useRouter } from 'next/router' import { HighchartsReactComponent } from '@/common/HighChartsReactComponent' import { Loading } from '@/common/Loading' import { - ChainAnalyticsColors, - ShortNetworkNames + ShortNetworkNames, + getHexColorByChain } from '@/lib/connect-wallet/config/chains' import { formatDateByLocale } from '@/lib/dates' import { hexToRgba } from '@/utils/hex-to-rgba' @@ -77,7 +77,7 @@ export const HistoricalRoi = ({ loading, data }) => { }) .sort((a, b) => { return a.x - b.x }), lineWidth: 3, - lineColor: '#' + (ChainAnalyticsColors[chain.value] || ChainAnalyticsColors.DEFAULT), + lineColor: getHexColorByChain(chain.value), fillColor: { linearGradient: { x1: 0, @@ -86,15 +86,15 @@ export const HistoricalRoi = ({ loading, data }) => { y2: 1 }, stops: [ - [0, hexToRgba(ChainAnalyticsColors[chain.value] || ChainAnalyticsColors.DEFAULT, 0.2)], - [1, hexToRgba(ChainAnalyticsColors[chain.value] || ChainAnalyticsColors.DEFAULT, 0)] + [0, hexToRgba(getHexColorByChain(chain.value), 0.2)], + [1, hexToRgba(getHexColorByChain(chain.value), 0)] ] }, marker: { fillColor: 'white', lineWidth: 2, radius: 3, - lineColor: '#' + (ChainAnalyticsColors[chain.value] || ChainAnalyticsColors.DEFAULT) + lineColor: getHexColorByChain(chain.value) }, animation: { duration: 500 @@ -177,7 +177,10 @@ export const HistoricalRoi = ({ loading, data }) => { {chains.map(chain => { return (
-
+
{chain.label}
) diff --git a/src/modules/insights/ProtectionChart/ProtectionChart.jsx b/src/modules/insights/ProtectionChart/ProtectionChart.jsx index a9e80924e..6d22429af 100644 --- a/src/modules/insights/ProtectionChart/ProtectionChart.jsx +++ b/src/modules/insights/ProtectionChart/ProtectionChart.jsx @@ -14,8 +14,8 @@ import { Bar } from 'react-chartjs-2' import { Loading } from '@/common/Loading' import { - ChainAnalyticsColors, - ShortNetworkNames + ShortNetworkNames, + getHexColorByChain } from '@/lib/connect-wallet/config/chains' import { externalTooltipHandler @@ -70,7 +70,7 @@ export const ProtectionChart = ({ loading, data, labels, dataKey = 'protection' return { label: data[chain].length ? data[chain][0].networkName : '', data: data[chain].map(item => { return parseFloat(item[dataKey]) }), - backgroundColor: ['1', '84531'].includes(chain) ? '#4E7DD9' : '#21AD8C', + backgroundColor: getHexColorByChain(chain), barPercentage: 1, borderWidth: 0, maxBarThickness: 17, @@ -248,7 +248,7 @@ export const ProtectionChart = ({ loading, data, labels, dataKey = 'protection' {chains.map(chain => { return (
-
+
{chain.label}
) diff --git a/src/modules/insights/StatsCard.jsx b/src/modules/insights/StatsCard.jsx index 7bfa25fc8..2b33609a4 100644 --- a/src/modules/insights/StatsCard.jsx +++ b/src/modules/insights/StatsCard.jsx @@ -1,4 +1,4 @@ -export const StatsCard = ({ title, titleTooltip, value, className = '', titleClass = '', valueClass = '', tooltip }) => { +export const StatsCard = ({ title, titleTooltip = undefined, value, className = '', titleClass = '', valueClass = '', tooltip = undefined }) => { return (
{title}
diff --git a/src/modules/my-policies/ClaimCxTokensTable.jsx b/src/modules/my-policies/ClaimCxTokensTable.jsx index 409a117dd..0a4c1a5aa 100644 --- a/src/modules/my-policies/ClaimCxTokensTable.jsx +++ b/src/modules/my-policies/ClaimCxTokensTable.jsx @@ -5,7 +5,6 @@ import { useRouter } from 'next/router' import { renderHeader } from '@/common/Table/renderHeader' import { Table, - TableShowMore, TableWrapper, TBody, THead @@ -23,7 +22,7 @@ import { fromNow } from '@/utils/formatter/relative-time' const renderAddress = (row) => { return ( - {row.cxToken.id} + {row.cxToken} ) } @@ -63,7 +62,7 @@ export const columns = [ } ] -const ClaimTableContext = React.createContext({ report: null }) +const ClaimTableContext = React.createContext({ claimExpiresAt: null }) export function useClaimTableContext () { const context = React.useContext(ClaimTableContext) @@ -79,36 +78,28 @@ export function useClaimTableContext () { export const ClaimCxTokensTable = ({ activePolicies, coverKey, + productKey, incidentDate, - report, - setPage, - hasMore = false, + claimExpiresAt, loading = false, claimPlatformFee }) => { return ( <> - +
- { - setPage((prev) => { return prev + 1 }) - }} - loading={loading} - />
) @@ -147,8 +138,8 @@ const CxTokenAmountRenderer = () => { } export const ClaimBeforeColumnRenderer = () => { - const { report } = useClaimTableContext() - const claimExpiryDate = report?.claimExpiresAt || 0 + const { claimExpiresAt } = useClaimTableContext() + const claimExpiryDate = claimExpiresAt const router = useRouter() return ( @@ -187,9 +178,9 @@ export const ClaimActionsColumnRenderer = ({ row, extraData }) => { { const router = useRouter() - const { page, limit, setPage } = usePagination() + + const { liquidityTokenDecimals } = useAppConstants() const { loading: dataLoading, getProduct, getCoverByCoverKey } = useCoversAndProducts() const isDiversified = isValidProduct(productKey) const coverOrProductData = isDiversified ? getProduct(coverKey, productKey) : getCoverByCoverKey(coverKey) const projectOrProductName = isDiversified ? coverOrProductData?.productInfoDetails?.productName : coverOrProductData?.coverInfoDetails.coverName || coverOrProductData?.coverInfoDetails.projectName - const { data, hasMore } = useActivePoliciesByCover({ - coverKey, - productKey, - page, - limit - }) - const { data: reports, loading: loadingReports } = - useFetchReportsByKeyAndDate({ - coverKey, - incidentDate: timestamp - }) - const { liquidityTokenDecimals } = useAppConstants() + const { data: allActivePolicies, loading } = useActivePolicies() + const policies = allActivePolicies.activePolicies.filter(x => { return x.coverKey === coverKey && x.productKey === productKey }) + const totalActiveProtection = sumOf(...policies.map(policy => { return policy.amount })).toString() + + const { data: { incidentReports: allIncidentReports }, loading: loadingReports } = useActiveReportings() + const reports = allIncidentReports.filter(x => { return x.incidentDate.toString() === timestamp.toString() && x.coverKey === coverKey && x.productKey === productKey }) - if (dataLoading) { + if (dataLoading || loading) { return ( ) @@ -94,7 +87,7 @@ export const ClaimDetailsPage = ({ ]} /> -
+
My Policies @@ -105,7 +98,7 @@ export const ClaimDetailsPage = ({ { formatCurrency( convertFromUnits( - data.totalActiveProtection, + totalActiveProtection, liquidityTokenDecimals ), router.locale, @@ -142,13 +135,12 @@ export const ClaimDetailsPage = ({ diff --git a/src/modules/my-policies/CxTokenRowContext.jsx b/src/modules/my-policies/CxTokenRowContext.jsx index 8693ad3f9..158ef82a4 100644 --- a/src/modules/my-policies/CxTokenRowContext.jsx +++ b/src/modules/my-policies/CxTokenRowContext.jsx @@ -1,3 +1,5 @@ +import { ChainConfig } from '@/src/config/hardcoded' +import { useNetwork } from '@/src/context/Network' import { useERC20Balance } from '@/src/hooks/useERC20Balance' import React from 'react' @@ -11,9 +13,10 @@ const CxTokenRowContext = React.createContext({ }) export const CxTokenRowProvider = ({ row, _extraData, ...props }) => { - const tokenAddress = row.cxToken.id - const tokenSymbol = row.cxToken.tokenSymbol - const tokenDecimals = row.cxToken.tokenDecimals + const tokenAddress = row.cxToken + const { networkId } = useNetwork() + const tokenSymbol = 'cxUSD' + const tokenDecimals = ChainConfig[networkId].cxTokenDecimals const { balance, loading: loadingBalance, diff --git a/src/modules/reporting/CoverReportingRules.jsx b/src/modules/reporting/CoverReportingRules.jsx index c8f68fd31..e3ee99522 100644 --- a/src/modules/reporting/CoverReportingRules.jsx +++ b/src/modules/reporting/CoverReportingRules.jsx @@ -15,11 +15,10 @@ import { ReportingInfo } from './ReportingInfo' export const CoverReportingRules = ({ coverOrProductData, handleAcceptRules, - activeReportings + activeIncidentIpfsHashes }) => { const reporterCommission = coverOrProductData?.reporterCommission const reportingPeriod = coverOrProductData?.reportingPeriod - const hasActiveReportings = activeReportings && activeReportings.length > 0 const isDiversified = isValidProduct(coverOrProductData.productKey) const parameters = isDiversified ? coverOrProductData.productInfoDetails?.parameters : coverOrProductData.coverInfoDetails?.parameters @@ -42,7 +41,7 @@ export const CoverReportingRules = ({ Active Reporting - {!hasActiveReportings && ( + {!(activeIncidentIpfsHashes.length > 0) && (

There are no known incidents of {projectOrProductName}. @@ -50,11 +49,11 @@ export const CoverReportingRules = ({

)} - {hasActiveReportings && ( + {(activeIncidentIpfsHashes.length > 0) && (
- {activeReportings.map((x) => { + {activeIncidentIpfsHashes.map((x) => { return ( - + ) })}
diff --git a/src/modules/reporting/NewDisputeReportForm.jsx b/src/modules/reporting/NewDisputeReportForm.jsx index f197b0e41..4d8bbfdfe 100644 --- a/src/modules/reporting/NewDisputeReportForm.jsx +++ b/src/modules/reporting/NewDisputeReportForm.jsx @@ -25,7 +25,12 @@ import { } from '@lingui/macro' import { useLingui } from '@lingui/react' -export const NewDisputeReportForm = ({ incidentReport, minReportingStake }) => { +export const NewDisputeReportForm = ({ + coverKey, + productKey, + incidentDate + , minReportingStake +}) => { const form = useRef(null) const [value, setValue] = useState('') @@ -42,9 +47,9 @@ export const NewDisputeReportForm = ({ incidentReport, minReportingStake }) => { canDispute } = useDisputeIncident({ value, - coverKey: incidentReport.coverKey, - productKey: incidentReport.productKey, - incidentDate: incidentReport.incidentDate, + coverKey, + productKey, + incidentDate, minStake: minReportingStake }) diff --git a/src/modules/reporting/NewDisputeReportFormContainer.jsx b/src/modules/reporting/NewDisputeReportFormContainer.jsx index 81944ef41..693e444be 100644 --- a/src/modules/reporting/NewDisputeReportFormContainer.jsx +++ b/src/modules/reporting/NewDisputeReportFormContainer.jsx @@ -83,15 +83,20 @@ function DisputeForm ({ coverKey, productKey, timestamp, minReportingStake }) { const now = DateLib.unix() const reportingEnded = incidentReportData - ? isGreater(now, incidentReportData.resolutionTimestamp || '0') + ? isGreater(now, incidentReportData.reportResolutionTimestamp || '0') : false - const canDispute = !reportingEnded && incidentReportData?.totalRefutedCount === '0' + const canDispute = !reportingEnded && incidentReportData?.refutationCount?.toString() === '0' return ( canDispute ? ( - + ) : ( diff --git a/src/modules/reporting/ReportListing.jsx b/src/modules/reporting/ReportListing.jsx index 88e96a97f..ea270665f 100644 --- a/src/modules/reporting/ReportListing.jsx +++ b/src/modules/reporting/ReportListing.jsx @@ -28,7 +28,6 @@ import { useNetwork } from '@/src/context/Network' import { isValidProduct } from '@/src/helpers/cover' import { useSubgraphFetch } from '@/src/hooks/useSubgraphFetch' import { truncateAddress } from '@/utils/address' -import { convertFromUnits } from '@/utils/bn' import { classNames } from '@/utils/classnames' import { formatCurrency } from '@/utils/formatter/currency' import { fromNow } from '@/utils/formatter/relative-time' @@ -141,7 +140,7 @@ const ReportListing = (props) => { const [reports, setReports] = useState([]) const fetchReports = useSubgraphFetch('ReportListing') - const { NPMTokenSymbol, NPMTokenDecimals } = useAppConstants() + const { NPMTokenSymbol } = useAppConstants() const isDiversified = isValidProduct(productKey) const { loading, getProduct, getCoverByCoverKey } = useCoversAndProducts() @@ -208,13 +207,13 @@ const ReportListing = (props) => { {reports.map((report, i) => { const formattedTotalAttestedStake = formatCurrency( - convertFromUnits(report.totalAttestedStake, NPMTokenDecimals), + report.totalAttestationStake, router.locale, NPMTokenSymbol, true ) const formattedTotalRefutedStake = formatCurrency( - convertFromUnits(report.totalRefutedStake, NPMTokenDecimals), + report.totalRefutationStake, router.locale, NPMTokenSymbol, true diff --git a/src/modules/reporting/ReportingPeriodStatus.jsx b/src/modules/reporting/ReportingPeriodStatus.jsx index 8404a212c..e43714669 100644 --- a/src/modules/reporting/ReportingPeriodStatus.jsx +++ b/src/modules/reporting/ReportingPeriodStatus.jsx @@ -6,9 +6,9 @@ import { fromNow } from '@/utils/formatter/relative-time' import { Trans } from '@lingui/macro' import * as Tooltip from '@radix-ui/react-tooltip' -export const ReportingPeriodStatus = ({ resolutionTimestamp }) => { +export const ReportingPeriodStatus = ({ reportingEndsAt }) => { const router = useRouter() - const endDate = DateLib.fromUnix(resolutionTimestamp) + const endDate = DateLib.fromUnix(reportingEndsAt) const isPast = DateLib.toUnix(new Date()) > DateLib.toUnix(endDate) const longDate = ( diff --git a/src/modules/reporting/active/ActiveReportSummary.jsx b/src/modules/reporting/active/ActiveReportSummary.jsx index d33e9daed..17c30a76b 100644 --- a/src/modules/reporting/active/ActiveReportSummary.jsx +++ b/src/modules/reporting/active/ActiveReportSummary.jsx @@ -52,7 +52,7 @@ export const ActiveReportSummary = ({ }) => { const router = useRouter() const startDate = DateLib.fromUnix(incidentReport.incidentDate) - const endDate = DateLib.fromUnix(incidentReport.resolutionTimestamp) + const endDate = DateLib.fromUnix(incidentReport.reportResolutionTimestamp) const { NPMTokenSymbol, NPMTokenDecimals } = useAppConstants() const { i18n } = useLingui() @@ -60,7 +60,7 @@ export const ActiveReportSummary = ({ const isAfterResolution = useRetryUntilPassed(() => { const _now = DateLib.unix() - return isGreater(_now, incidentReport.resolutionTimestamp) + return isGreater(_now, incidentReport.reportResolutionTimestamp) }) const votes = { @@ -75,19 +75,19 @@ export const ActiveReportSummary = ({ .decimalPlaces(2) .toNumber() - let isAttestedWon = incidentReport.decision + let isAttestedWon = incidentReport.resolutionDecision - if (incidentReport.decision === null) { + if (incidentReport.resolutionDecision === null) { isAttestedWon = isGreater( - incidentReport.totalAttestedStake, - incidentReport.totalRefutedStake + incidentReport.totalAttestationStake, + incidentReport.totalRefutationStake ) } const majority = { voteCount: isAttestedWon - ? incidentReport.totalAttestedCount - : incidentReport.totalRefutedCount, + ? incidentReport.attestationCount + : incidentReport.refutationCount, stake: isAttestedWon ? yes : no, percent: isAttestedWon ? yesPercent : noPercent, variant: isAttestedWon ? 'success' : 'failure' @@ -159,18 +159,18 @@ export const ActiveReportSummary = ({ }, { title: t(i18n)`User Votes:`, - value: incidentReport.totalAttestedCount + value: incidentReport.attestationCount }, { title: t(i18n)`Stake:`, value: formatCurrency( - convertFromUnits(incidentReport.totalAttestedStake), + incidentReport.totalAttestationStake, router.locale, NPMTokenSymbol, true ).short, htmlTooltip: formatCurrency( - convertFromUnits(incidentReport.totalAttestedStake), + incidentReport.totalAttestationStake, router.locale, NPMTokenSymbol, true @@ -204,13 +204,13 @@ export const ActiveReportSummary = ({ }, { title: t(i18n)`User Votes:`, - value: incidentReport.totalRefutedCount + value: incidentReport.refutationCount }, { title: t(i18n)`Stake:`, value: `${ formatCurrency( - convertFromUnits(incidentReport.totalRefutedStake), + incidentReport.totalRefutationStake, router.locale, NPMTokenSymbol, true @@ -218,7 +218,7 @@ export const ActiveReportSummary = ({ }`, htmlTooltip: `${ formatCurrency( - convertFromUnits(incidentReport.totalRefutedStake), + incidentReport.totalRefutationStake, router.locale, NPMTokenSymbol, true @@ -250,13 +250,13 @@ export const ActiveReportSummary = ({ {incidentReport.disputer && ( )} @@ -265,7 +265,7 @@ export const ActiveReportSummary = ({ Reporting Period

{DateLib.toDateFormat( - incidentReport.resolutionTimestamp, + incidentReport.reportResolutionTimestamp, router.locale, { month: 'short', day: 'numeric' }, 'UTC' diff --git a/src/modules/reporting/active/CastYourVote.jsx b/src/modules/reporting/active/CastYourVote.jsx index d34595923..cbf1c522d 100644 --- a/src/modules/reporting/active/CastYourVote.jsx +++ b/src/modules/reporting/active/CastYourVote.jsx @@ -109,7 +109,7 @@ export const CastYourVote = ({ incidentReport, idPrefix, reporterCommission, min const isFirstDispute = votingType === 'false-reporting' && - incidentReport.totalRefutedCount === '0' + incidentReport.refutationCount.toString() === '0' const handleReport = (onTxSuccess) => { if (votingType === 'false-reporting') { diff --git a/src/modules/reporting/details.jsx b/src/modules/reporting/details.jsx index 143668925..e78af88c9 100644 --- a/src/modules/reporting/details.jsx +++ b/src/modules/reporting/details.jsx @@ -60,7 +60,7 @@ export const ReportingDetailsPage = ({ const now = DateLib.unix() const showResolvedSummary = incidentReport.resolved && isPassedResolutionDeadline - const reportingEnded = isGreater(now, incidentReport.resolutionTimestamp) + const reportingEnded = isGreater(now, incidentReport.reportResolutionTimestamp) return (

@@ -119,10 +119,10 @@ export const ReportingDetailsPage = ({ } { return x.coverKey === coverKey && x.productKey === productKey }) useEffect(() => { window.scrollTo(0, 0) @@ -41,14 +38,14 @@ export function NewIncidentReportPage ({ coverKey, productKey }) { // Redirect to active reporting if exists useEffect(() => { - const hasActiveReportings = activeReportings && activeReportings.length > 0 + const hasActiveReportings = reports.length > 0 if (!hasActiveReportings) { return } router.replace( - Routes.ViewReport(coverKey, productKey, activeReportings[0].incidentDate) + Routes.ViewReport(coverKey, productKey, reports[0].incidentDate) ) - }, [activeReportings, coverKey, productKey, router]) + }, [reports, coverKey, productKey, router]) if (loading) { return ( @@ -96,7 +93,7 @@ export function NewIncidentReportPage ({ coverKey, productKey }) { { return x.reportInfo })} /> )} diff --git a/src/modules/reporting/resolved/ResolvedReportSummary.jsx b/src/modules/reporting/resolved/ResolvedReportSummary.jsx index 865292ee2..96b14028e 100644 --- a/src/modules/reporting/resolved/ResolvedReportSummary.jsx +++ b/src/modules/reporting/resolved/ResolvedReportSummary.jsx @@ -71,19 +71,19 @@ export const ResolvedReportSummary = ({ .decimalPlaces(2) .toNumber() - let isAttestedWon = incidentReport.decision + let isAttestedWon = incidentReport.resolutionDecision - if (incidentReport.decision === null) { + if (incidentReport.resolutionDecision === null) { isAttestedWon = isGreater( - incidentReport.totalAttestedStake, - incidentReport.totalRefutedStake + incidentReport.totalAttestationStake, + incidentReport.totalRefutationStake ) } const majority = { voteCount: isAttestedWon - ? incidentReport.totalAttestedCount - : incidentReport.totalRefutedCount, + ? incidentReport.attestationCount + : incidentReport.refutationCount, stake: isAttestedWon ? yes : no, percent: isAttestedWon ? yesPercent : noPercent, variant: isAttestedWon ? 'success' : 'failure' @@ -130,18 +130,18 @@ export const ResolvedReportSummary = ({ }, { title: t(i18n)`User Votes:`, - value: incidentReport.totalAttestedCount + value: incidentReport.attestationCount }, { title: t(i18n)`Stake:`, value: formatCurrency( - convertFromUnits(incidentReport.totalAttestedStake), + incidentReport.totalAttestationStake, router.locale, NPMTokenSymbol, true ).short, htmlTooltip: formatCurrency( - convertFromUnits(incidentReport.totalAttestedStake), + incidentReport.totalAttestationStake, router.locale, NPMTokenSymbol, true @@ -175,18 +175,18 @@ export const ResolvedReportSummary = ({ }, { title: t(i18n)`User Votes:`, - value: incidentReport.totalRefutedCount + value: incidentReport.refutationCount }, { title: t(i18n)`Stake:`, value: formatCurrency( - convertFromUnits(incidentReport.totalRefutedStake), + incidentReport.totalRefutationStake, router.locale, NPMTokenSymbol, true ).short, htmlTooltip: formatCurrency( - convertFromUnits(incidentReport.totalRefutedStake), + incidentReport.totalRefutationStake, router.locale, NPMTokenSymbol, true @@ -217,13 +217,13 @@ export const ResolvedReportSummary = ({ {incidentReport.disputer && ( )} @@ -232,7 +232,7 @@ export const ResolvedReportSummary = ({ Reporting Period

{DateLib.toDateFormat( - incidentReport.resolutionTimestamp, + incidentReport.reportResolutionTimestamp, router.locale, { month: 'short', day: 'numeric' }, 'UTC' diff --git a/src/modules/reporting/resolved/ResolvedTBodyRow.jsx b/src/modules/reporting/resolved/ResolvedTBodyRow.jsx index 3afd4fbd5..f86915481 100644 --- a/src/modules/reporting/resolved/ResolvedTBodyRow.jsx +++ b/src/modules/reporting/resolved/ResolvedTBodyRow.jsx @@ -28,8 +28,8 @@ export const ResolvedTBodyRow = ({ id, coverKey, productKey = safeFormatBytes32String(''), - totalAttestedStake, - totalRefutedStake + totalAttestationStake, + totalRefutationStake } = report const isDiversified = isValidProduct(productKey) @@ -58,8 +58,8 @@ export const ResolvedTBodyRow = ({ locale: router.locale, status, resolvedOn, - totalAttestedStake, - totalRefutedStake, + totalAttestationStake, + totalRefutationStake, NPMTokenSymbol }) } diff --git a/src/modules/reporting/resolved/UnstakeYourAmount.jsx b/src/modules/reporting/resolved/UnstakeYourAmount.jsx index 52edd4b6b..c137de422 100644 --- a/src/modules/reporting/resolved/UnstakeYourAmount.jsx +++ b/src/modules/reporting/resolved/UnstakeYourAmount.jsx @@ -38,14 +38,12 @@ export const UnstakeYourAmount = ({ incidentReport, willReceive, refetchAll, pro const { unstake, unstakeWithClaim, unstaking } = useUnstakeReportingStake({ coverKey: incidentReport.coverKey, productKey: incidentReport.productKey, - incidentDate: incidentReport.incidentDate, - incidentStatus: incidentReport.status, - willReceive + incidentDate: incidentReport.incidentDate }) const isClaimExpired = useRetryUntilPassed(() => { // If false reporting, we don't care about the claim period - if (!incidentReport.decision) { return true } + if (!incidentReport.resolutionDecision) { return true } const _now = DateLib.unix() @@ -54,7 +52,7 @@ export const UnstakeYourAmount = ({ incidentReport, willReceive, refetchAll, pro const isClaimStarted = useRetryUntilPassed(() => { // If false reporting, we don't care about the claim period - if (!incidentReport.decision) { return true } + if (!incidentReport.resolutionDecision) { return true } const _now = DateLib.unix() @@ -71,7 +69,7 @@ export const UnstakeYourAmount = ({ incidentReport, willReceive, refetchAll, pro const now = DateLib.unix() - const isIncidentOccurred = incidentReport.decision + const isIncidentOccurred = incidentReport.resolutionDecision const notClaimableYet = isGreater(incidentReport.claimBeginsFrom, now) const isClaimableNow = isIncidentOccurred && !isClaimExpired && isClaimStarted @@ -96,7 +94,7 @@ export const UnstakeYourAmount = ({ incidentReport, willReceive, refetchAll, pro

Result:{' '} - {incidentReport.decision ? Incident Occurred : False Reporting}{' '} + {incidentReport.resolutionDecision ? Incident Occurred : False Reporting}{' '} {incidentReport.emergencyResolved && Emergency Resolved} diff --git a/src/modules/reporting/resolved/resolved.jsx b/src/modules/reporting/resolved/resolved.jsx index 351e75fe3..1799ee6c5 100644 --- a/src/modules/reporting/resolved/resolved.jsx +++ b/src/modules/reporting/resolved/resolved.jsx @@ -36,7 +36,6 @@ import { useSortableStats } from '@/src/context/SortableStatsContext' import { isValidProduct } from '@/src/helpers/cover' import { useResolvedReportings } from '@/src/hooks/useResolvedReportings' import { useSearchResults } from '@/src/hooks/useSearchResults' -import { convertFromUnits } from '@/utils/bn' import { formatCurrency } from '@/utils/formatter/currency' import { getUtcFormatString } from '@/utils/formatter/relative-time' import { @@ -116,7 +115,7 @@ const renderStatus = (row) => { } const renderTotalAttestedStake = (row) => { - if (!row.totalAttestedStake) { + if (!row.totalAttestationStake) { return null } @@ -125,7 +124,7 @@ const renderTotalAttestedStake = (row) => { className='px-6 py-6 text-sm leading-5 text-01052D w-52' title={ formatCurrency( - convertFromUnits(row?.totalAttestedStake), + row?.totalAttestationStake, row.locale, row.NPMTokenSymbol, true @@ -134,7 +133,7 @@ const renderTotalAttestedStake = (row) => { > { formatCurrency( - convertFromUnits(row?.totalAttestedStake), + (row?.totalAttestationStake), row.locale, row.NPMTokenSymbol, true @@ -145,7 +144,7 @@ const renderTotalAttestedStake = (row) => { } const renderTotalRefutedStake = (row) => { - if (!row.totalAttestedStake) { + if (!row.totalRefutationStake) { return null } @@ -154,7 +153,7 @@ const renderTotalRefutedStake = (row) => { className='px-6 py-2 text-sm leading-5 text-01052D w-52' title={ formatCurrency( - convertFromUnits(row.totalRefutedStake), + row.totalRefutationStake, row.locale, row.NPMTokenSymbol, true @@ -163,7 +162,7 @@ const renderTotalRefutedStake = (row) => { > { formatCurrency( - convertFromUnits(row.totalRefutedStake), + row.totalRefutationStake, row.locale, row.NPMTokenSymbol, true @@ -220,15 +219,6 @@ const getColumns = (i18n) => { ] } -const getUrl = (reportId) => { - const keysArray = reportId.split('-') - const coverKey = keysArray[0] - const productKey = keysArray[1] - const timestamp = keysArray[2] - - return Routes.ViewReport(coverKey, productKey, timestamp) -} - export const ReportingResolvedPage = () => { const router = useRouter() const { @@ -335,24 +325,23 @@ export const ReportingResolvedPage = () => { )} {resolvedReportsWithData.map(({ report, coverOrProductData }) => { - const resolvedOn = report.emergencyResolved - ? report.emergencyResolveTransaction?.timestamp - : report.resolveTransaction?.timestamp + const resolvedOn = report.resolutionTimestamp return ( { return router.push(getUrl(report.id)) }} + onClick={() => { return router.push(Routes.ViewReport(report.coverKey, report.productKey, report.incidentDate)) }} > + ) })} diff --git a/src/services/aggregated-stats/protocol.js b/src/services/aggregated-stats/protocol.js deleted file mode 100644 index 118677c75..000000000 --- a/src/services/aggregated-stats/protocol.js +++ /dev/null @@ -1,77 +0,0 @@ -import { SUBGRAPH_API_URLS } from '@/src/config/constants' -import { ChainConfig } from '@/src/config/hardcoded' - -import { getSubgraphData } from '@/src/services/subgraph' -import { - convertFromUnits, - sumOf -} from '@/utils/bn' -import { getNetworkInfo } from '@/utils/network' - -const protocolMonthCoverFeeQuery = ` -{ - protocolMonthDatas { - id - nonCumulativeCoverFee - } -} -` - -async function getIndividualProtocolMonthData (networkId) { - const data = await getSubgraphData( - networkId, - protocolMonthCoverFeeQuery - ) - - if (!data) { return } - - if (!Array.isArray(data.protocolMonthDatas) || !data.protocolMonthDatas.length) { - return - } - - return data.protocolMonthDatas.map(x => { - return { - networkId: networkId, - ...x - } - }) -} - -export async function getGroupedProtocolMonthData (networkId) { - const { isMainNet } = getNetworkInfo(networkId) - - const promises = [] - - for (const id in SUBGRAPH_API_URLS) { - const match = getNetworkInfo(parseInt(id)).isMainNet === isMainNet - - if (!match) { - continue - } - - promises.push(getIndividualProtocolMonthData(parseInt(id))) - } - - const result = await Promise.all(promises) - - const obj = {} - - result.forEach(arr => { - if (!Array.isArray(arr)) { return } - - arr.forEach(val => { - obj[val.id] = sumOf(convertFromUnits(val.nonCumulativeCoverFee, ChainConfig[val.networkId]?.stablecoin?.tokenDecimals || 6), obj[val.id] || '0') - }) - }) - - const sorted = Object.entries(obj).sort(([a], [b]) => { return parseInt(a) - parseInt(b) }) - - return sorted.reduce((prev, curr) => { - prev.push({ - id: curr[0], - nonCumulativeCoverFee: curr[1] - }) - - return prev - }, []) -} diff --git a/src/services/api/config.js b/src/services/api/config.js index d8c192d80..f24b625c4 100644 --- a/src/services/api/config.js +++ b/src/services/api/config.js @@ -51,8 +51,17 @@ export const LIQUIDITY_SUMMARY = `${API_BASE_URL}home/charts/liquidity-summary/{ export const TVL_DISTRIBUTION = `${API_BASE_URL}home/charts/tvl-distribution/{networkId}` +export const COVER_EARNINGS = `${API_BASE_URL}home/charts/cover-earnings/{networkId}` + +// GET: consensus export const RECENT_VOTES = `${API_BASE_URL}consensus/report/votes/{networkId}/{coverKey}/{productKey}/{incidentDate}` +export const INCIDENT_DETAIL = `${API_BASE_URL}consensus/report/insight/{networkId}/{coverKey}/{productKey}/{incidentDate}` + +export const ACTIVE_INCIDENTS = `${API_BASE_URL}consensus/report/active/{networkId}` + +export const RESOLVED_INCIDENTS = `${API_BASE_URL}consensus/report/resolved/{networkId}` + // GET: bridge export const BRIDGE_ETH_PRICING_URL = `${API_BASE_URL}bridge/pricing/eth` diff --git a/src/services/api/consensus/active.js b/src/services/api/consensus/active.js new file mode 100644 index 000000000..b1833f865 --- /dev/null +++ b/src/services/api/consensus/active.js @@ -0,0 +1,40 @@ +import { getReplacedString } from '@/utils/string' + +import * as api from '../config' + +export const getActiveIncidents = async (networkId) => { + try { + const url = getReplacedString(api.ACTIVE_INCIDENTS, { networkId }) + + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + } + }) + + if (!response.ok) { + return null + } + + const data = await response.json() + + const items = data.data + + if (!items || !Array.isArray(items)) { + return [] + } + + return items.map((item) => { + return { + ...item, + id: item.coverKey + item.productKey + item.incidentDate + } + }) + } catch (error) { + console.error('Could not get active incidents', error) + } + + return null +} diff --git a/src/services/api/consensus/detail.js b/src/services/api/consensus/detail.js new file mode 100644 index 000000000..f000c1696 --- /dev/null +++ b/src/services/api/consensus/detail.js @@ -0,0 +1,46 @@ +import { getReplacedString } from '@/utils/string' + +import * as api from '../config' + +export const getIncidentDetail = async (networkId, coverKey, productKey, incidentDate) => { + try { + const url = getReplacedString(api.INCIDENT_DETAIL, { networkId, coverKey, productKey, incidentDate }) + + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + } + }) + + if (!response.ok) { + return null + } + + const data = await response.json() + + const items = data.data + + if (!items || !Array.isArray(items)) { + return null + } + + const item = items[0] + + if (!item) { + return null + } + + return { + ...item, + id: item.coverKey + item.productKey + item.incidentDate, + totalAttestationStake: item.totalAttestation || '0', + totalRefutationStake: item.totalRefutation || '0' + } + } catch (error) { + console.error('Could not get incident detail', error) + } + + return null +} diff --git a/src/services/api/consensus/resolved.js b/src/services/api/consensus/resolved.js new file mode 100644 index 000000000..f8bae4f0f --- /dev/null +++ b/src/services/api/consensus/resolved.js @@ -0,0 +1,40 @@ +import { getReplacedString } from '@/utils/string' + +import * as api from '../config' + +export const getResolvedIncidents = async (networkId) => { + try { + const url = getReplacedString(api.RESOLVED_INCIDENTS, { networkId }) + + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + } + }) + + if (!response.ok) { + return null + } + + const data = await response.json() + + const items = data.data + + if (!items || !Array.isArray(items)) { + return [] + } + + return items.map((item) => { + return { + ...item, + id: item.coverKey + item.productKey + item.incidentDate + } + }) + } catch (error) { + console.error('Could not get resolved incidents', error) + } + + return null +} diff --git a/src/services/api/home/charts/cover-earnings.js b/src/services/api/home/charts/cover-earnings.js new file mode 100644 index 000000000..c9b7665d5 --- /dev/null +++ b/src/services/api/home/charts/cover-earnings.js @@ -0,0 +1,35 @@ +import { getReplacedString } from '@/utils/string' + +import * as api from '../../config' + +export const getCoverEarnings = async (networkId) => { + try { + const url = getReplacedString(api.COVER_EARNINGS, { networkId }) + + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + } + }) + + if (!response.ok) { + return null + } + + const data = await response.json() + + const items = data.data + + if (!items || !Array.isArray(items)) { + return null + } + + return items + } catch (error) { + console.error('Could not get cover earnings', error) + } + + return null +} diff --git a/src/services/subgraph.js b/src/services/subgraph.js deleted file mode 100644 index 831941615..000000000 --- a/src/services/subgraph.js +++ /dev/null @@ -1,36 +0,0 @@ -import { getGraphURL } from '@/src/config/environment' - -export async function getSubgraphData (networkId, query) { - if (!networkId) { - return null - } - - const graphURL = getGraphURL(networkId) - - if (!graphURL) { - return null - } - - const response = await fetch(graphURL, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json' - }, - body: JSON.stringify({ - query: query - }) - }) - - if (!response.ok) { - return null - } - - const result = await response.json() - - if (result.errors) { - return null - } - - return result.data -} diff --git a/src/utils/sorting.js b/src/utils/sorting.js index 0d269f6a6..96d20b1ac 100644 --- a/src/utils/sorting.js +++ b/src/utils/sorting.js @@ -1,4 +1,4 @@ -import { getMonthNames } from '@/lib/dates' + import { toBNSafe } from '@/utils/bn' import { toStringSafe } from '@/utils/string' import { t } from '@lingui/macro' @@ -68,25 +68,6 @@ const sortByBigNumber = (dataList, selector, asc = false) => { }) } -/* sort array of dates formatted as "MMM-YY" (eg. JAN-23) */ -export function sortDates (dates, selector = (x) => { return x }, asc = true) { - return dates.sort((a, b) => { - const aData = selector(a) - const bData = selector(b) - - const [aMonth, aYear] = aData.split('-') - const [bMonth, bYear] = bData.split('-') - const months = getMonthNames(undefined, true) - const aMonthIndex = months.indexOf(aMonth) - const bMonthIndex = months.indexOf(bMonth) - if (aYear === bYear) { - return asc ? (aMonthIndex - bMonthIndex) : (bMonthIndex - aMonthIndex) - } else { - return asc ? (aYear - bYear) : (bYear - aYear) - } - }) -} - /** * * @param {Object} sorterArgs - args used for sorting diff --git a/tailwind.config.js b/tailwind.config.js index fa0c2e9e2..2e2ee028d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -220,6 +220,8 @@ module.exports = { EEF4FF: '#EEF4FF', E31B54: '#E31B54', E5F4F5: '#E5F4F5', + E84142: '#E84142', + F3BA2F: '#F3BA2F', E6EAEF: '#E6EAEF', EAAA08: '#EAAA08', EAF7F8: '#EAF7F8',