From fd1d022ccce51c30306f6e4550671c9801753b7a Mon Sep 17 00:00:00 2001 From: Chef Penguin Date: Tue, 9 Jul 2024 13:31:27 +0530 Subject: [PATCH 01/13] feat: faster prediction prices --- .../src/pages/api/prediction/price/index.ts | 6 +-- .../AIPredictions/AILiveRoundCard.tsx | 10 +++-- .../Predictions/hooks/usePredictionPrice.ts | 43 ++++++++++++++++--- 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/apps/web/src/pages/api/prediction/price/index.ts b/apps/web/src/pages/api/prediction/price/index.ts index 070dae0b917fe..66d6ac980f1f5 100644 --- a/apps/web/src/pages/api/prediction/price/index.ts +++ b/apps/web/src/pages/api/prediction/price/index.ts @@ -27,9 +27,9 @@ const handler: NextApiHandler = async (req, res) => { price: string } = await response.json() - res.setHeader('Cache-Control', 's-maxage=10, stale-while-revalidate=10') - res.setHeader('Vercel-CDN-Cache-Control', 'max-age=10') - res.setHeader('CDN-Cache-Control', 'max-age=10') + res.setHeader('Cache-Control', 's-maxage=5, stale-while-revalidate=5') + res.setHeader('Vercel-CDN-Cache-Control', 'max-age=5') + res.setHeader('CDN-Cache-Control', 'max-age=5') return res.status(response.status).json({ currencyA, diff --git a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx index 6f53ea32d7620..5937026717497 100644 --- a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx +++ b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx @@ -9,7 +9,7 @@ import { useGetBufferSeconds } from 'state/predictions/hooks' import { NodeLedger, NodeRound } from 'state/types' import styled from 'styled-components' import { getNowInSeconds } from 'utils/getNowInSeconds' -import { usePredictionPrice } from 'views/Predictions/hooks/usePredictionPrice' +import { usePredictionPrice, usePredictionPriceMutation } from 'views/Predictions/hooks/usePredictionPrice' import { useConfig } from '../../../context/ConfigProvider' import PositionTag from '../../PositionTag' import { LockPriceRow, PrizePoolRow, RoundResultBox } from '../../RoundResult' @@ -57,10 +57,10 @@ export const AILiveRoundCard: React.FC 0) { const refreshPriceTimeout = setTimeout(() => { - refetch() + mutateAsync({ + currencyA: config?.token.symbol, + }) }, (secondsToClose - REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE) * 1000) const calculatingPhaseTimeout = setTimeout(() => { @@ -124,7 +126,7 @@ export const AILiveRoundCard: React.FC diff --git a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts index 85edb4ae89422..de5315dc2ba41 100644 --- a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts +++ b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts @@ -1,6 +1,5 @@ -import { useQuery } from '@tanstack/react-query' -import { FAST_INTERVAL } from 'config/constants' -import { PREDICTION_PRICE_API } from 'config/constants/endpoints' +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' +import { BINANCE_DATA_API, PREDICTION_PRICE_API } from 'config/constants/endpoints' import { PriceApiWhitelistedCurrency } from 'config/constants/prediction/price' interface UsePredictionPriceParameters { @@ -10,7 +9,7 @@ interface UsePredictionPriceParameters { /** Default: USDT */ currencyB?: PriceApiWhitelistedCurrency | (string & NonNullable) - /** Default: 10,000 milliseconds */ + /** Default: 5,000 milliseconds */ pollingInterval?: number enabled?: boolean @@ -23,10 +22,40 @@ interface PriceResponse { currencyB: PriceApiWhitelistedCurrency | (string & NonNullable) } +const DEFAULT_CURRENCY_A: PriceApiWhitelistedCurrency = 'ETH' +const DEFAULT_CURRENCY_B: PriceApiWhitelistedCurrency = 'USDT' +const DEFAULT_POLLING_INTERVAL = 5_000 + +/** + * Mutate the price directly from the source API if + * Live Price is needed urgently + */ +export const usePredictionPriceMutation = () => { + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async ({ + currencyA = DEFAULT_CURRENCY_A, + currencyB = DEFAULT_CURRENCY_B, + }: UsePredictionPriceParameters) => { + return fetch(`${BINANCE_DATA_API}/v3/ticker/price?symbol=${currencyA}${currencyB}`) + .then((res) => res.json()) + .then((data) => ({ + price: parseFloat(data.price), + currencyA, + currencyB, + })) + }, + onSuccess: (data, { currencyA = DEFAULT_CURRENCY_A, currencyB = DEFAULT_CURRENCY_B }) => { + queryClient.setQueryData(['price', currencyA, currencyB], data) + }, + }) +} + export const usePredictionPrice = ({ - currencyA = 'ETH', - currencyB = 'USDT', - pollingInterval = FAST_INTERVAL, + currencyA = DEFAULT_CURRENCY_A, + currencyB = DEFAULT_CURRENCY_B, + pollingInterval = DEFAULT_POLLING_INTERVAL, enabled = true, }: UsePredictionPriceParameters = {}) => { return useQuery({ From 71151cf141eb4c01d3b3d62d23cf8ed36e0215da Mon Sep 17 00:00:00 2001 From: Chef Penguin Date: Tue, 9 Jul 2024 16:17:21 +0530 Subject: [PATCH 02/13] chore: update function for source price --- .../AIPredictions/AILiveRoundCard.tsx | 8 ++-- .../Predictions/hooks/usePredictionPrice.ts | 40 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx index 5937026717497..e4bdaaf5a0aa5 100644 --- a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx +++ b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx @@ -9,7 +9,7 @@ import { useGetBufferSeconds } from 'state/predictions/hooks' import { NodeLedger, NodeRound } from 'state/types' import styled from 'styled-components' import { getNowInSeconds } from 'utils/getNowInSeconds' -import { usePredictionPrice, usePredictionPriceMutation } from 'views/Predictions/hooks/usePredictionPrice' +import { usePredictionPrice, usePredictionPriceUpdate } from 'views/Predictions/hooks/usePredictionPrice' import { useConfig } from '../../../context/ConfigProvider' import PositionTag from '../../PositionTag' import { LockPriceRow, PrizePoolRow, RoundResultBox } from '../../RoundResult' @@ -60,7 +60,7 @@ export const AILiveRoundCard: React.FC 0) { const refreshPriceTimeout = setTimeout(() => { - mutateAsync({ + updatePriceFromSource({ currencyA: config?.token.symbol, }) }, (secondsToClose - REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE) * 1000) @@ -126,7 +126,7 @@ export const AILiveRoundCard: React.FC diff --git a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts index de5315dc2ba41..4449811b3af3d 100644 --- a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts +++ b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts @@ -1,4 +1,4 @@ -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' +import { useQuery, useQueryClient } from '@tanstack/react-query' import { BINANCE_DATA_API, PREDICTION_PRICE_API } from 'config/constants/endpoints' import { PriceApiWhitelistedCurrency } from 'config/constants/prediction/price' @@ -27,29 +27,29 @@ const DEFAULT_CURRENCY_B: PriceApiWhitelistedCurrency = 'USDT' const DEFAULT_POLLING_INTERVAL = 5_000 /** - * Mutate the price directly from the source API if + * Fetch the price directly from the source API if * Live Price is needed urgently */ -export const usePredictionPriceMutation = () => { +export const usePredictionPriceUpdate = () => { const queryClient = useQueryClient() - return useMutation({ - mutationFn: async ({ - currencyA = DEFAULT_CURRENCY_A, - currencyB = DEFAULT_CURRENCY_B, - }: UsePredictionPriceParameters) => { - return fetch(`${BINANCE_DATA_API}/v3/ticker/price?symbol=${currencyA}${currencyB}`) - .then((res) => res.json()) - .then((data) => ({ - price: parseFloat(data.price), - currencyA, - currencyB, - })) - }, - onSuccess: (data, { currencyA = DEFAULT_CURRENCY_A, currencyB = DEFAULT_CURRENCY_B }) => { - queryClient.setQueryData(['price', currencyA, currencyB], data) - }, - }) + const updatePriceFromSource = async ({ + currencyA = DEFAULT_CURRENCY_A, + currencyB = DEFAULT_CURRENCY_B, + }: UsePredictionPriceParameters) => + fetch(`${BINANCE_DATA_API}/v3/ticker/price?symbol=${currencyA}${currencyB}`) + .then((res) => res.json()) + .then((result) => ({ + price: parseFloat(result.price), + currencyA, + currencyB, + })) + .then((data) => { + queryClient.setQueryData(['price', currencyA, currencyB], data) + return data + }) + + return { updatePriceFromSource } } export const usePredictionPrice = ({ From a9602b849cb90cf649cc371b043dd420a5aba2e2 Mon Sep 17 00:00:00 2001 From: Chef Penguin Date: Tue, 9 Jul 2024 16:30:26 +0530 Subject: [PATCH 03/13] chore: useCallback --- .../Predictions/hooks/usePredictionPrice.ts | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts index 4449811b3af3d..40a29608d81da 100644 --- a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts +++ b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts @@ -1,6 +1,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query' import { BINANCE_DATA_API, PREDICTION_PRICE_API } from 'config/constants/endpoints' import { PriceApiWhitelistedCurrency } from 'config/constants/prediction/price' +import { useCallback } from 'react' interface UsePredictionPriceParameters { /** Default: ETH */ @@ -33,21 +34,21 @@ const DEFAULT_POLLING_INTERVAL = 5_000 export const usePredictionPriceUpdate = () => { const queryClient = useQueryClient() - const updatePriceFromSource = async ({ - currencyA = DEFAULT_CURRENCY_A, - currencyB = DEFAULT_CURRENCY_B, - }: UsePredictionPriceParameters) => - fetch(`${BINANCE_DATA_API}/v3/ticker/price?symbol=${currencyA}${currencyB}`) - .then((res) => res.json()) - .then((result) => ({ - price: parseFloat(result.price), - currencyA, - currencyB, - })) - .then((data) => { - queryClient.setQueryData(['price', currencyA, currencyB], data) - return data - }) + const updatePriceFromSource = useCallback( + async ({ currencyA = DEFAULT_CURRENCY_A, currencyB = DEFAULT_CURRENCY_B }: UsePredictionPriceParameters) => + fetch(`${BINANCE_DATA_API}/v3/ticker/price?symbol=${currencyA}${currencyB}`) + .then((res) => res.json()) + .then((result) => ({ + price: parseFloat(result.price), + currencyA, + currencyB, + })) + .then((data) => { + queryClient.setQueryData(['price', currencyA, currencyB], data) + return data + }), + [queryClient], + ) return { updatePriceFromSource } } From d1385406305fa273941f4e9eca4ac96afa4a12cd Mon Sep 17 00:00:00 2001 From: Chef Penguin Date: Wed, 14 Aug 2024 16:05:16 +0530 Subject: [PATCH 04/13] chore: use alternate source --- .../AIPredictions/AILiveRoundCard.tsx | 24 ++++++--- .../Predictions/hooks/usePredictionPrice.ts | 49 +++++++------------ 2 files changed, 34 insertions(+), 39 deletions(-) diff --git a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx index e4bdaaf5a0aa5..1ed00dadac5dd 100644 --- a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx +++ b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx @@ -3,13 +3,13 @@ import { BetPosition } from '@pancakeswap/prediction' import { Card, CardBody, Flex, PlayCircleOutlineIcon, Text, useTooltip } from '@pancakeswap/uikit' import { formatBigInt, formatNumber } from '@pancakeswap/utils/formatBalance' import RoundProgress from 'components/RoundProgress' -import { useEffect, useMemo, useState } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' import { getHasRoundFailed } from 'state/predictions/helpers' import { useGetBufferSeconds } from 'state/predictions/hooks' import { NodeLedger, NodeRound } from 'state/types' import styled from 'styled-components' import { getNowInSeconds } from 'utils/getNowInSeconds' -import { usePredictionPrice, usePredictionPriceUpdate } from 'views/Predictions/hooks/usePredictionPrice' +import { usePredictionPrice } from 'views/Predictions/hooks/usePredictionPrice' import { useConfig } from '../../../context/ConfigProvider' import PositionTag from '../../PositionTag' import { LockPriceRow, PrizePoolRow, RoundResultBox } from '../../RoundResult' @@ -39,7 +39,7 @@ interface AILiveRoundCardProps { formattedBearMultiplier: string } -const REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE = 2 +const REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE = 3 export const AILiveRoundCard: React.FC> = ({ round, @@ -54,13 +54,15 @@ export const AILiveRoundCard: React.FC { + // Fetch live price before round ends + setFetchAlternate(true) + setTimeout(() => { + setFetchAlternate(false) + }, REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE * 1000) + }, []) + useEffect(() => { const secondsToClose = closeTimestamp ? closeTimestamp - getNowInSeconds() : 0 if (secondsToClose > 0) { const refreshPriceTimeout = setTimeout(() => { - updatePriceFromSource({ - currencyA: config?.token.symbol, - }) + refreshLivePrice() }, (secondsToClose - REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE) * 1000) const calculatingPhaseTimeout = setTimeout(() => { @@ -126,7 +134,7 @@ export const AILiveRoundCard: React.FC diff --git a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts index 40a29608d81da..b555e7449091b 100644 --- a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts +++ b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts @@ -1,7 +1,6 @@ -import { useQuery, useQueryClient } from '@tanstack/react-query' +import { useQuery } from '@tanstack/react-query' import { BINANCE_DATA_API, PREDICTION_PRICE_API } from 'config/constants/endpoints' import { PriceApiWhitelistedCurrency } from 'config/constants/prediction/price' -import { useCallback } from 'react' interface UsePredictionPriceParameters { /** Default: ETH */ @@ -14,6 +13,8 @@ interface UsePredictionPriceParameters { pollingInterval?: number enabled?: boolean + + useAlternateSource?: boolean } interface PriceResponse { @@ -27,43 +28,29 @@ const DEFAULT_CURRENCY_A: PriceApiWhitelistedCurrency = 'ETH' const DEFAULT_CURRENCY_B: PriceApiWhitelistedCurrency = 'USDT' const DEFAULT_POLLING_INTERVAL = 5_000 -/** - * Fetch the price directly from the source API if - * Live Price is needed urgently - */ -export const usePredictionPriceUpdate = () => { - const queryClient = useQueryClient() - - const updatePriceFromSource = useCallback( - async ({ currencyA = DEFAULT_CURRENCY_A, currencyB = DEFAULT_CURRENCY_B }: UsePredictionPriceParameters) => - fetch(`${BINANCE_DATA_API}/v3/ticker/price?symbol=${currencyA}${currencyB}`) - .then((res) => res.json()) - .then((result) => ({ - price: parseFloat(result.price), - currencyA, - currencyB, - })) - .then((data) => { - queryClient.setQueryData(['price', currencyA, currencyB], data) - return data - }), - [queryClient], - ) - - return { updatePriceFromSource } -} - export const usePredictionPrice = ({ currencyA = DEFAULT_CURRENCY_A, currencyB = DEFAULT_CURRENCY_B, pollingInterval = DEFAULT_POLLING_INTERVAL, enabled = true, + useAlternateSource = false, }: UsePredictionPriceParameters = {}) => { return useQuery({ - queryKey: ['price', currencyA, currencyB], + queryKey: ['price', currencyA, currencyB, useAlternateSource], queryFn: async () => - fetch(`${PREDICTION_PRICE_API}/?currencyA=${currencyA}¤cyB=${currencyB}`).then((res) => res.json()), - refetchInterval: pollingInterval, + useAlternateSource + ? fetch(`${BINANCE_DATA_API}/v3/ticker/price?symbol=${currencyA}${currencyB}`) + .then((res) => res.json()) + .then((result) => ({ + price: parseFloat(result.price), + currencyA, + currencyB, + })) + : fetch(`${PREDICTION_PRICE_API}/?currencyA=${currencyA}¤cyB=${currencyB}`).then((res) => res.json()), + refetchInterval: () => { + if (useAlternateSource) return false + return pollingInterval + }, retry: 2, initialData: { price: 0, From bfb6b969b3c19e8e337a2586d0b2445da2e32dc5 Mon Sep 17 00:00:00 2001 From: Chef Penguin Date: Wed, 14 Aug 2024 16:43:24 +0530 Subject: [PATCH 05/13] chore: remove unnecessary dependency, increase live price time --- .../components/RoundCard/AIPredictions/AILiveRoundCard.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx index 1ed00dadac5dd..e72b94ba069f5 100644 --- a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx +++ b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx @@ -114,7 +114,7 @@ export const AILiveRoundCard: React.FC { setFetchAlternate(false) - }, REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE * 1000) + }, REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE * 2 * 1000) }, []) useEffect(() => { @@ -134,7 +134,7 @@ export const AILiveRoundCard: React.FC From 682416d474b3b3fd0c44894fc196ae0ed763e8af Mon Sep 17 00:00:00 2001 From: Chef Penguin Date: Thu, 15 Aug 2024 21:15:33 +0530 Subject: [PATCH 06/13] chore: one-liner --- apps/web/src/views/Predictions/hooks/usePredictionPrice.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts index b555e7449091b..704e6a283e624 100644 --- a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts +++ b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts @@ -47,10 +47,7 @@ export const usePredictionPrice = ({ currencyB, })) : fetch(`${PREDICTION_PRICE_API}/?currencyA=${currencyA}¤cyB=${currencyB}`).then((res) => res.json()), - refetchInterval: () => { - if (useAlternateSource) return false - return pollingInterval - }, + refetchInterval: () => (useAlternateSource ? false : pollingInterval), retry: 2, initialData: { price: 0, From 1a3e317b24715fbcaa8574a46da478a01c69bf4d Mon Sep 17 00:00:00 2001 From: Chef Penguin Date: Thu, 15 Aug 2024 21:32:29 +0530 Subject: [PATCH 07/13] chore: reset refresh time before close --- .../components/RoundCard/AIPredictions/AILiveRoundCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx index e72b94ba069f5..c85b979864876 100644 --- a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx +++ b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx @@ -39,7 +39,7 @@ interface AILiveRoundCardProps { formattedBearMultiplier: string } -const REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE = 3 +const REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE = 2 export const AILiveRoundCard: React.FC> = ({ round, From 3ecc849f66fc2551ec5e8eda699caa1d620dc42b Mon Sep 17 00:00:00 2001 From: memoyil <2213635+memoyil@users.noreply.github.com> Date: Mon, 19 Aug 2024 04:28:13 +0200 Subject: [PATCH 08/13] fix: Useref to prevent price jumps when using alternate source --- .../RoundCard/AIPredictions/AILiveRoundCard.tsx | 12 ++++++------ .../Predictions/hooks/usePredictionPrice.ts | 16 +++++++++------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx index c85b979864876..c2fe66504b00f 100644 --- a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx +++ b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx @@ -54,14 +54,13 @@ export const AILiveRoundCard: React.FC { // Fetch live price before round ends - setFetchAlternate(true) + currentUseAlternateSource.current = true + refetch() setTimeout(() => { - setFetchAlternate(false) + currentUseAlternateSource.current = false }, REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE * 2 * 1000) - }, []) + }, [currentUseAlternateSource, refetch]) useEffect(() => { const secondsToClose = closeTimestamp ? closeTimestamp - getNowInSeconds() : 0 diff --git a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts index 704e6a283e624..ee5785dda912c 100644 --- a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts +++ b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts @@ -1,6 +1,7 @@ import { useQuery } from '@tanstack/react-query' import { BINANCE_DATA_API, PREDICTION_PRICE_API } from 'config/constants/endpoints' import { PriceApiWhitelistedCurrency } from 'config/constants/prediction/price' +import { useRef } from 'react' interface UsePredictionPriceParameters { /** Default: ETH */ @@ -13,8 +14,6 @@ interface UsePredictionPriceParameters { pollingInterval?: number enabled?: boolean - - useAlternateSource?: boolean } interface PriceResponse { @@ -33,12 +32,13 @@ export const usePredictionPrice = ({ currencyB = DEFAULT_CURRENCY_B, pollingInterval = DEFAULT_POLLING_INTERVAL, enabled = true, - useAlternateSource = false, }: UsePredictionPriceParameters = {}) => { - return useQuery({ - queryKey: ['price', currencyA, currencyB, useAlternateSource], + const currentUseAlternateSource = useRef(false) + + const queryResult = useQuery({ + queryKey: ['price', currencyA, currencyB], queryFn: async () => - useAlternateSource + currentUseAlternateSource.current ? fetch(`${BINANCE_DATA_API}/v3/ticker/price?symbol=${currencyA}${currencyB}`) .then((res) => res.json()) .then((result) => ({ @@ -47,7 +47,7 @@ export const usePredictionPrice = ({ currencyB, })) : fetch(`${PREDICTION_PRICE_API}/?currencyA=${currencyA}¤cyB=${currencyB}`).then((res) => res.json()), - refetchInterval: () => (useAlternateSource ? false : pollingInterval), + refetchInterval: () => (currentUseAlternateSource.current ? false : pollingInterval), retry: 2, initialData: { price: 0, @@ -56,4 +56,6 @@ export const usePredictionPrice = ({ }, enabled, }) + + return { ...queryResult, currentUseAlternateSource } } From 7a5ed032189a7e1c5af9f10873f8baafed12b432 Mon Sep 17 00:00:00 2001 From: memoyil <2213635+memoyil@users.noreply.github.com> Date: Mon, 19 Aug 2024 04:31:02 +0200 Subject: [PATCH 09/13] fix: Remove settimeout to avoid memory leak --- .../components/RoundCard/AIPredictions/AILiveRoundCard.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx index c2fe66504b00f..aec84ff32b9cc 100644 --- a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx +++ b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx @@ -112,9 +112,6 @@ export const AILiveRoundCard: React.FC { - currentUseAlternateSource.current = false - }, REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE * 2 * 1000) }, [currentUseAlternateSource, refetch]) useEffect(() => { From 86084bc7e2dfb0161ffe69ecc62b42bcba29a606 Mon Sep 17 00:00:00 2001 From: memoyil <2213635+memoyil@users.noreply.github.com> Date: Mon, 19 Aug 2024 12:17:11 +0200 Subject: [PATCH 10/13] refactor: Put ref to provider increase refresh to 3 sec --- .../AIPredictions/AILiveRoundCard.tsx | 20 +++++++++---------- .../context/PredictionConfigProviders.tsx | 14 +++++++++++-- .../Predictions/hooks/usePredictionPrice.ts | 17 ++++++++-------- packages/prediction/src/type.ts | 5 +++++ 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx index aec84ff32b9cc..82cde86a768a8 100644 --- a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx +++ b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx @@ -39,7 +39,7 @@ interface AILiveRoundCardProps { formattedBearMultiplier: string } -const REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE = 2 +const REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE = 3 export const AILiveRoundCard: React.FC> = ({ round, @@ -58,7 +58,6 @@ export const AILiveRoundCard: React.FC { - // Fetch live price before round ends - currentUseAlternateSource.current = true - refetch() - }, [currentUseAlternateSource, refetch]) - useEffect(() => { const secondsToClose = closeTimestamp ? closeTimestamp - getNowInSeconds() : 0 if (secondsToClose > 0) { const refreshPriceTimeout = setTimeout(() => { - refreshLivePrice() + // Fetch live price before round ends + if (config?.ai?.useAlternateSource) { + config.ai.useAlternateSource.current = true + refetch() + } }, (secondsToClose - REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE) * 1000) const calculatingPhaseTimeout = setTimeout(() => { @@ -128,10 +125,13 @@ export const AILiveRoundCard: React.FC { clearTimeout(refreshPriceTimeout) clearTimeout(calculatingPhaseTimeout) + if (config?.ai?.useAlternateSource) { + config.ai.useAlternateSource.current = false + } } } return undefined - }, [closeTimestamp, refreshLivePrice]) + }, [closeTimestamp, config, refetch]) if (hasRoundFailed) { return diff --git a/apps/web/src/views/Predictions/context/PredictionConfigProviders.tsx b/apps/web/src/views/Predictions/context/PredictionConfigProviders.tsx index ee5539550198e..9a0a32e2ed27d 100644 --- a/apps/web/src/views/Predictions/context/PredictionConfigProviders.tsx +++ b/apps/web/src/views/Predictions/context/PredictionConfigProviders.tsx @@ -5,7 +5,7 @@ import makeStore from 'contexts/LocalRedux/makeStore' import { useActiveChainId } from 'hooks/useActiveChainId' import _toUpper from 'lodash/toUpper' import { useRouter } from 'next/router' -import { useEffect, useMemo, useState } from 'react' +import { useEffect, useMemo, useRef, useState } from 'react' import reducers, { initialState } from 'state/predictions' import { usePredictionConfigs } from 'views/Predictions/hooks/usePredictionConfigs' import { usePredictionToken } from 'views/Predictions/hooks/usePredictionToken' @@ -17,6 +17,7 @@ const PredictionConfigProviders = ({ children }) => { const predictionConfigs = usePredictionConfigs() const [selectedPickedToken, setSelectedPickedToken] = useState('') const [prevSelectedToken, setPrevSelectedToken] = usePredictionToken() + const useAlternateSourceRef = useRef(false) const supportedSymbol = useMemo(() => (predictionConfigs ? Object.keys(predictionConfigs) : []), [predictionConfigs]) @@ -63,7 +64,16 @@ const PredictionConfigProviders = ({ children }) => { return selectedPickedToken || supportedSymbol?.[0] }, [chainId, prevSelectedToken, selectedPickedToken, supportedSymbol]) - const config = useMemo(() => predictionConfigs?.[selectedToken], [predictionConfigs, selectedToken]) + const config = useMemo(() => { + const selected = predictionConfigs?.[selectedToken] + if (selected?.ai) { + return { + ...selected, + ai: { ...selected.ai, useAlternateSource: useAlternateSourceRef }, + } + } + return selected + }, [predictionConfigs, selectedToken]) const store = useMemo(() => makeStore(reducers, initialState, config), [config]) diff --git a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts index ee5785dda912c..a7a383496e93b 100644 --- a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts +++ b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts @@ -1,7 +1,7 @@ import { useQuery } from '@tanstack/react-query' import { BINANCE_DATA_API, PREDICTION_PRICE_API } from 'config/constants/endpoints' import { PriceApiWhitelistedCurrency } from 'config/constants/prediction/price' -import { useRef } from 'react' +import { useConfig } from '../context/ConfigProvider' interface UsePredictionPriceParameters { /** Default: ETH */ @@ -33,12 +33,12 @@ export const usePredictionPrice = ({ pollingInterval = DEFAULT_POLLING_INTERVAL, enabled = true, }: UsePredictionPriceParameters = {}) => { - const currentUseAlternateSource = useRef(false) + const config = useConfig() - const queryResult = useQuery({ + return useQuery({ queryKey: ['price', currencyA, currencyB], - queryFn: async () => - currentUseAlternateSource.current + queryFn: async () => { + return config?.ai?.useAlternateSource?.current ? fetch(`${BINANCE_DATA_API}/v3/ticker/price?symbol=${currencyA}${currencyB}`) .then((res) => res.json()) .then((result) => ({ @@ -46,8 +46,9 @@ export const usePredictionPrice = ({ currencyA, currencyB, })) - : fetch(`${PREDICTION_PRICE_API}/?currencyA=${currencyA}¤cyB=${currencyB}`).then((res) => res.json()), - refetchInterval: () => (currentUseAlternateSource.current ? false : pollingInterval), + : fetch(`${PREDICTION_PRICE_API}/?currencyA=${currencyA}¤cyB=${currencyB}`).then((res) => res.json()) + }, + refetchInterval: () => (config?.ai?.useAlternateSource?.current ? false : pollingInterval), retry: 2, initialData: { price: 0, @@ -56,6 +57,4 @@ export const usePredictionPrice = ({ }, enabled, }) - - return { ...queryResult, currentUseAlternateSource } } diff --git a/packages/prediction/src/type.ts b/packages/prediction/src/type.ts index f6eb54ed28f1e..8654d7fbacdde 100644 --- a/packages/prediction/src/type.ts +++ b/packages/prediction/src/type.ts @@ -29,8 +29,13 @@ export enum PredictionsChartView { Pyth = 'Pyth Oracle', } +interface MutableRefObject { + current: T +} + type AIPredictionConfig = { aiPriceDecimals?: number + useAlternateSource?: MutableRefObject } export interface PredictionConfig { From 998e9500262e21306447eaf961a97f8b0b342c98 Mon Sep 17 00:00:00 2001 From: memoyil <2213635+memoyil@users.noreply.github.com> Date: Mon, 19 Aug 2024 12:41:20 +0200 Subject: [PATCH 11/13] fix: Reduce back to 2 sec --- .../components/RoundCard/AIPredictions/AILiveRoundCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx index 82cde86a768a8..4618fbbc2d672 100644 --- a/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx +++ b/apps/web/src/views/Predictions/components/RoundCard/AIPredictions/AILiveRoundCard.tsx @@ -39,7 +39,7 @@ interface AILiveRoundCardProps { formattedBearMultiplier: string } -const REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE = 3 +const REFRESH_PRICE_BEFORE_SECONDS_TO_CLOSE = 2 export const AILiveRoundCard: React.FC> = ({ round, From 5b2223b3cc7ce6f038d10de66838c0f6b45e8b09 Mon Sep 17 00:00:00 2001 From: Chef Penguin Date: Mon, 19 Aug 2024 16:34:43 +0530 Subject: [PATCH 12/13] chore: change mobile cta on prediction stripe --- .../PhishingWarningBanner/AIPredictionStripe.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/web/src/components/PhishingWarningBanner/AIPredictionStripe.tsx b/apps/web/src/components/PhishingWarningBanner/AIPredictionStripe.tsx index 98d17056ac08a..40c470a392e22 100644 --- a/apps/web/src/components/PhishingWarningBanner/AIPredictionStripe.tsx +++ b/apps/web/src/components/PhishingWarningBanner/AIPredictionStripe.tsx @@ -48,13 +48,13 @@ export const AIPrediction = ({ - {t('Learn More')} - + {t('Participate Now')} + From 5b5f01dbeb0ea194018eac8caac28d58ef415e71 Mon Sep 17 00:00:00 2001 From: memoyil <2213635+memoyil@users.noreply.github.com> Date: Mon, 19 Aug 2024 20:43:10 +0200 Subject: [PATCH 13/13] fix: Price api url --- apps/web/src/views/Predictions/hooks/usePredictionPrice.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts index a7a383496e93b..4a7972cf222df 100644 --- a/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts +++ b/apps/web/src/views/Predictions/hooks/usePredictionPrice.ts @@ -46,7 +46,7 @@ export const usePredictionPrice = ({ currencyA, currencyB, })) - : fetch(`${PREDICTION_PRICE_API}/?currencyA=${currencyA}¤cyB=${currencyB}`).then((res) => res.json()) + : fetch(`${PREDICTION_PRICE_API}?currencyA=${currencyA}¤cyB=${currencyB}`).then((res) => res.json()) }, refetchInterval: () => (config?.ai?.useAlternateSource?.current ? false : pollingInterval), retry: 2,