From 1f12bb26e0ad2bf7f49f6f75369d5568792977b5 Mon Sep 17 00:00:00 2001 From: Alex Shorsher Date: Mon, 11 Apr 2022 22:51:43 -0400 Subject: [PATCH 1/2] add token pool cache Signed-off-by: Alex Shorsher --- src/App.tsx | 31 +++++++++------ src/contexts/PoolContext.tsx | 25 ++++++++++++ src/interfaces/api.ts | 4 ++ src/pages/Tokens/views/Balances.tsx | 42 +++++++++++++++++--- src/pages/Tokens/views/Dashboard.tsx | 58 +++++++++++++++++++++++++--- src/pages/Tokens/views/Pools.tsx | 5 ++- 6 files changed, 141 insertions(+), 24 deletions(-) create mode 100644 src/contexts/PoolContext.tsx diff --git a/src/App.tsx b/src/App.tsx index 37e6df06..3b216b5a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -30,11 +30,13 @@ import { } from './components/Snackbar/MessageSnackbar'; import { ApplicationContext } from './contexts/ApplicationContext'; import { SnackbarContext } from './contexts/SnackbarContext'; +import { PoolContext } from './contexts/PoolContext'; import { FF_EVENTS, INamespace, INewEventSet, IStatus, + ITokenPool, NAMESPACES_PATH, } from './interfaces'; import { FF_Paths } from './interfaces/constants'; @@ -61,6 +63,9 @@ const App: React.FC = () => { const [nodeID, setNodeID] = useState(''); const [nodeName, setNodeName] = useState(''); const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws'; + const [poolCache, setPoolCache] = useState>( + new Map() + ); // Event Context const [newEvents, setNewEvents] = useState(makeNewEventMap()); const [lastRefreshTime, setLastRefresh] = useState( @@ -191,18 +196,20 @@ const App: React.FC = () => { - - - - - - - - + + + + + + + + + + ); diff --git a/src/contexts/PoolContext.tsx b/src/contexts/PoolContext.tsx new file mode 100644 index 00000000..36a169ae --- /dev/null +++ b/src/contexts/PoolContext.tsx @@ -0,0 +1,25 @@ +// Copyright © 2022 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { createContext, Dispatch, SetStateAction } from 'react'; +import { ITokenPool } from '../interfaces'; + +export interface IPoolContext { + poolCache: Map; + setPoolCache: Dispatch>>; +} + +export const PoolContext = createContext({} as IPoolContext); diff --git a/src/interfaces/api.ts b/src/interfaces/api.ts index fc28a5bd..42089257 100644 --- a/src/interfaces/api.ts +++ b/src/interfaces/api.ts @@ -515,6 +515,10 @@ export interface ITokenBalance { updated: string; } +export interface ITokenBalanceWithPoolName extends ITokenBalance { + poolName: string; +} + export interface ITokenConnector { [key: string]: string; } diff --git a/src/pages/Tokens/views/Balances.tsx b/src/pages/Tokens/views/Balances.tsx index f7d62e0c..2fde7cce 100644 --- a/src/pages/Tokens/views/Balances.tsx +++ b/src/pages/Tokens/views/Balances.tsx @@ -36,10 +36,13 @@ import { IDataTableRecord, IPagedTokenBalanceResponse, ITokenBalance, + ITokenPool, + ITokenBalanceWithPoolName, } from '../../../interfaces'; import { DEFAULT_PADDING, DEFAULT_PAGE_LIMITS } from '../../../theme'; -import { fetchCatcher, getFFTime } from '../../../utils'; +import { fetchCatcher, fetchWithCredentials, getFFTime } from '../../../utils'; import { hasTransferEvent } from '../../../utils/wsEvents'; +import { PoolContext } from '../../../contexts/PoolContext'; export const KEY_POOL_DELIM = '||'; @@ -51,10 +54,13 @@ export const TokensBalances: () => JSX.Element = () => { useContext(FilterContext); const { slideID, setSlideSearchParam } = useContext(SlideContext); const { reportFetchError } = useContext(SnackbarContext); + const { poolCache, setPoolCache } = useContext(PoolContext); const { t } = useTranslation(); const [isMounted, setIsMounted] = useState(false); // Token balances - const [tokenBalances, setTokenBalances] = useState(); + const [tokenBalances, setTokenBalances] = useState< + ITokenBalanceWithPoolName[] + >([]); // Token balances totals const [tokenBalancesTotal, setTokenBalancesTotal] = useState(0); const [viewBalance, setViewBalance] = useState(); @@ -68,6 +74,24 @@ export const TokensBalances: () => JSX.Element = () => { }; }, []); + const fetchPool = async ( + namespace: string, + id: string + ): Promise => { + if (poolCache.has(id)) { + return poolCache.get(id); + } + const response = await fetchWithCredentials( + `/api/v1/namespaces/${namespace}/tokens/pools/${id}` + ); + if (!response.ok) { + return undefined; + } + const pool: ITokenPool = await response.json(); + poolCache.set(id, pool); + return pool; + }; + useEffect(() => { if (isMounted && slideID) { // Expected structure: || @@ -104,9 +128,16 @@ export const TokensBalances: () => JSX.Element = () => { dateFilter.filterString }${filterString ?? ''}` ) - .then((tokenBalancesRes: IPagedTokenBalanceResponse) => { - setTokenBalances(tokenBalancesRes.items); + .then(async (tokenBalancesRes: IPagedTokenBalanceResponse) => { setTokenBalancesTotal(tokenBalancesRes.total); + for (const item of tokenBalancesRes.items) { + const pool = await fetchPool(selectedNamespace, item.pool); + const balance = { + ...item, + poolName: pool ? pool.name : item.pool, + }; + setTokenBalances((tokenBalances) => [...tokenBalances, balance]); + } }) .catch((err) => { reportFetchError(err); @@ -129,6 +160,7 @@ export const TokensBalances: () => JSX.Element = () => { t('connector'), t('updated'), ]; + const tokenBalanceRecords: IDataTableRecord[] | undefined = tokenBalances?.map((balance, idx) => ({ key: idx.toString(), @@ -140,7 +172,7 @@ export const TokensBalances: () => JSX.Element = () => { value: , }, { - value: , + value: , }, { value: , diff --git a/src/pages/Tokens/views/Dashboard.tsx b/src/pages/Tokens/views/Dashboard.tsx index de7c712c..f21ce771 100644 --- a/src/pages/Tokens/views/Dashboard.tsx +++ b/src/pages/Tokens/views/Dashboard.tsx @@ -34,6 +34,7 @@ import { MediumCardTable } from '../../../components/Tables/MediumCardTable'; import { DataTable } from '../../../components/Tables/Table'; import { ApplicationContext } from '../../../contexts/ApplicationContext'; import { DateFilterContext } from '../../../contexts/DateFilterContext'; +import { PoolContext } from '../../../contexts/PoolContext'; import { SlideContext } from '../../../contexts/SlideContext'; import { SnackbarContext } from '../../../contexts/SnackbarContext'; import { @@ -49,6 +50,7 @@ import { IPagedTokenTransferResponse, ISmallCard, ITokenBalance, + ITokenBalanceWithPoolName, ITokenPool, ITokenTransfer, POOLS_PATH, @@ -63,7 +65,12 @@ import { DEFAULT_PAGE_LIMITS, DEFAULT_SPACING, } from '../../../theme'; -import { fetchCatcher, getFFTime, jsNumberForAddress } from '../../../utils'; +import { + fetchCatcher, + fetchWithCredentials, + getFFTime, + jsNumberForAddress, +} from '../../../utils'; import { isHistogramEmpty, makeColorArray, @@ -80,6 +87,7 @@ export const TokensDashboard: () => JSX.Element = () => { const { dateFilter } = useContext(DateFilterContext); const { slideID, setSlideSearchParam } = useContext(SlideContext); const { reportFetchError } = useContext(SnackbarContext); + const { poolCache, setPoolCache } = useContext(PoolContext); const navigate = useNavigate(); const [isMounted, setIsMounted] = useState(false); // Small cards @@ -100,7 +108,9 @@ export const TokensDashboard: () => JSX.Element = () => { // Transfer types histogram const [transferHistData, setTransferHistData] = useState(); // Token accounts - const [tokenBalances, setTokenBalances] = useState(); + const [tokenBalances, setTokenBalances] = useState< + ITokenBalanceWithPoolName[] + >([]); // Token pools const [tokenPools, setTokenPools] = useState(); // Token transfers @@ -124,6 +134,24 @@ export const TokensDashboard: () => JSX.Element = () => { }; }, []); + const fetchPool = async ( + namespace: string, + id: string + ): Promise => { + if (poolCache.has(id)) { + return poolCache.get(id); + } + const response = await fetchWithCredentials( + `/api/v1/namespaces/${namespace}/tokens/pools/${id}` + ); + if (!response.ok) { + return undefined; + } + const pool: ITokenPool = await response.json(); + poolCache.set(id, pool); + return pool; + }; + useEffect(() => { if (isMounted && slideID) { // Expected structure: || @@ -268,7 +296,7 @@ export const TokensDashboard: () => JSX.Element = () => { value: , }, { - value: , + value: , }, { value: , @@ -389,7 +417,14 @@ export const TokensDashboard: () => JSX.Element = () => { `${FF_Paths.nsPrefix}/${selectedNamespace}${FF_Paths.tokenPools}` ) .then((pools: ITokenPool[]) => { - isMounted && setTokenPools(pools); + if (isMounted) { + setTokenPools(pools); + pools.map((pool) => { + setPoolCache( + (poolCache) => new Map(poolCache.set(pool.id, pool)) + ); + }); + } }) .catch((err) => { reportFetchError(err); @@ -397,8 +432,19 @@ export const TokensDashboard: () => JSX.Element = () => { fetchCatcher( `${FF_Paths.nsPrefix}/${selectedNamespace}${FF_Paths.tokenBalances}` ) - .then((balances: ITokenBalance[]) => { - isMounted && setTokenBalances(balances); + .then(async (balances: ITokenBalance[]) => { + for (const balance of balances) { + const pool = await fetchPool(selectedNamespace, balance.pool); + const balanceWithPoolName = { + ...balance, + poolName: pool ? pool.name : balance.pool, + }; + isMounted && + setTokenBalances((tokenBalances) => [ + ...tokenBalances, + balanceWithPoolName, + ]); + } }) .catch((err) => { reportFetchError(err); diff --git a/src/pages/Tokens/views/Pools.tsx b/src/pages/Tokens/views/Pools.tsx index b86c62f7..d081c5d0 100644 --- a/src/pages/Tokens/views/Pools.tsx +++ b/src/pages/Tokens/views/Pools.tsx @@ -42,6 +42,7 @@ import { import { DEFAULT_PADDING, DEFAULT_PAGE_LIMITS } from '../../../theme'; import { fetchCatcher, getFFTime, jsNumberForAddress } from '../../../utils'; import { hasPoolEvent } from '../../../utils/wsEvents'; +import { PoolContext } from '../../../contexts/PoolContext'; export const TokensPools: () => JSX.Element = () => { const { newEvents, lastRefreshTime, clearNewEvents, selectedNamespace } = @@ -50,6 +51,7 @@ export const TokensPools: () => JSX.Element = () => { const { filterAnchor, setFilterAnchor, filterString } = useContext(FilterContext); const { reportFetchError } = useContext(SnackbarContext); + const { poolCache } = useContext(PoolContext); const { t } = useTranslation(); const navigate = useNavigate(); const [isMounted, setIsMounted] = useState(false); @@ -57,7 +59,6 @@ export const TokensPools: () => JSX.Element = () => { const [tokenPools, setTokenPools] = useState(); // Token pools totals const [tokenPoolsTotal, setTokenPoolsTotal] = useState(0); - const [currentPage, setCurrentPage] = useState(0); const [rowsPerPage, setRowsPerPage] = useState(DEFAULT_PAGE_LIMITS[1]); @@ -68,6 +69,8 @@ export const TokensPools: () => JSX.Element = () => { }; }, []); + console.log(poolCache); + // Token pools useEffect(() => { isMounted && From 1f2dc31c4e583b019676622b4e64c594ebd01d71 Mon Sep 17 00:00:00 2001 From: Alex Shorsher Date: Tue, 12 Apr 2022 09:19:30 -0400 Subject: [PATCH 2/2] fetchPool as a util, approval pool caching - Moved `fetchPool()` to the utility folder for reuse - Added pool caching to token approval page & slide Signed-off-by: Alex Shorsher --- src/components/Lists/ApprovalList.tsx | 10 ++--- src/components/Slides/ApprovalSlide.tsx | 4 +- src/components/Slides/EventSlide.tsx | 35 ++++++++++++++++- src/interfaces/api.ts | 4 ++ src/pages/Tokens/views/Approvals.tsx | 52 ++++++++++++++++++++----- src/pages/Tokens/views/Balances.tsx | 28 ++++--------- src/pages/Tokens/views/Dashboard.tsx | 27 ++++--------- src/pages/Tokens/views/Pools.tsx | 4 -- src/utils/fetches.ts | 23 +++++++++++ 9 files changed, 123 insertions(+), 64 deletions(-) diff --git a/src/components/Lists/ApprovalList.tsx b/src/components/Lists/ApprovalList.tsx index c8e023a4..594fb813 100644 --- a/src/components/Lists/ApprovalList.tsx +++ b/src/components/Lists/ApprovalList.tsx @@ -1,7 +1,7 @@ import { useContext, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ApplicationContext } from '../../contexts/ApplicationContext'; -import { ITokenApproval } from '../../interfaces'; +import { ITokenApprovalWithPoolName } from '../../interfaces'; import { IDataListItem } from '../../interfaces/lists'; import { FFCopyButton } from '../Buttons/CopyButton'; import { PoolButton } from '../Buttons/PoolButton'; @@ -11,7 +11,7 @@ import { FFListTimestamp } from './FFListTimestamp'; import { FFSkeletonList } from './FFSkeletonList'; interface Props { - approval?: ITokenApproval; + approval?: ITokenApprovalWithPoolName; } export const ApprovalList: React.FC = ({ approval }) => { @@ -39,11 +39,11 @@ export const ApprovalList: React.FC = ({ approval }) => { }, { label: t('pool'), - value: , + value: , button: ( <> - - + + ), }, diff --git a/src/components/Slides/ApprovalSlide.tsx b/src/components/Slides/ApprovalSlide.tsx index 16d62382..ace0ea22 100644 --- a/src/components/Slides/ApprovalSlide.tsx +++ b/src/components/Slides/ApprovalSlide.tsx @@ -17,7 +17,7 @@ import { Grid } from '@mui/material'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { ITokenApproval } from '../../interfaces'; +import { ITokenApprovalWithPoolName } from '../../interfaces'; import { DEFAULT_PADDING } from '../../theme'; import { getShortHash } from '../../utils'; import { ApprovalList } from '../Lists/ApprovalList'; @@ -25,7 +25,7 @@ import { DisplaySlide } from './DisplaySlide'; import { SlideHeader } from './SlideHeader'; interface Props { - approval: ITokenApproval; + approval: ITokenApprovalWithPoolName; open: boolean; onClose: () => void; } diff --git a/src/components/Slides/EventSlide.tsx b/src/components/Slides/EventSlide.tsx index cb37193d..95bf5b8f 100644 --- a/src/components/Slides/EventSlide.tsx +++ b/src/components/Slides/EventSlide.tsx @@ -25,9 +25,11 @@ import { FF_Paths, IData, IEvent, + ITokenApproval, + ITokenApprovalWithPoolName, } from '../../interfaces'; import { DEFAULT_PADDING } from '../../theme'; -import { fetchCatcher } from '../../utils'; +import { fetchCatcher, fetchPool } from '../../utils'; import { BlockchainEventAccordion } from '../Accordions/BlockchainEventAccordion'; import { JsonViewAccordion } from '../Accordions/JsonViewerAccordion'; import { MessageAccordion } from '../Accordions/MessageAccordion'; @@ -45,6 +47,7 @@ import { TxList } from '../Lists/TxList'; import { DisplaySlide } from './DisplaySlide'; import { SlideHeader } from './SlideHeader'; import { SlideSectionHeader } from './SlideSectionHeader'; +import { PoolContext } from '../../contexts/PoolContext'; interface Props { event: IEvent; @@ -56,9 +59,12 @@ export const EventSlide: React.FC = ({ event, open, onClose }) => { const { t } = useTranslation(); const { selectedNamespace } = useContext(ApplicationContext); const { reportFetchError } = useContext(SnackbarContext); + const { poolCache, setPoolCache } = useContext(PoolContext); const [enrichedEvent, setEnrichedEvent] = useState(); const [messageData, setMessageData] = useState(); const { txID } = useParams<{ txID: string }>(); + const [approvalWithName, setApprovalWithName] = + useState(); const [isMounted, setIsMounted] = useState(false); useEffect(() => { @@ -100,6 +106,31 @@ export const EventSlide: React.FC = ({ event, open, onClose }) => { } }, [enrichedEvent, isMounted]); + useEffect(() => { + if (enrichedEvent && isMounted && enrichedEvent['tokenApproval']) { + fetchPoolName(enrichedEvent.tokenApproval).then( + (approvalWithName: ITokenApprovalWithPoolName) => { + setApprovalWithName(approvalWithName); + } + ); + } + }, [enrichedEvent, isMounted]); + + const fetchPoolName = async ( + approval: ITokenApproval + ): Promise => { + const pool = await fetchPool( + selectedNamespace, + approval.pool, + poolCache, + setPoolCache + ); + return { + ...approval, + poolName: pool ? pool.name : approval.pool, + }; + }; + return ( <> @@ -199,7 +230,7 @@ export const EventSlide: React.FC = ({ event, open, onClose }) => { <> - + )} diff --git a/src/interfaces/api.ts b/src/interfaces/api.ts index 42089257..9e98f585 100644 --- a/src/interfaces/api.ts +++ b/src/interfaces/api.ts @@ -505,6 +505,10 @@ export interface ITokenApproval { blockchainEvent: string; } +export interface ITokenApprovalWithPoolName extends ITokenApproval { + poolName: string; +} + export interface ITokenBalance { pool: string; uri: string; diff --git a/src/pages/Tokens/views/Approvals.tsx b/src/pages/Tokens/views/Approvals.tsx index 8412241d..c0ce3d2b 100644 --- a/src/pages/Tokens/views/Approvals.tsx +++ b/src/pages/Tokens/views/Approvals.tsx @@ -36,10 +36,12 @@ import { IDataTableRecord, IPagedTokenApprovalResponse, ITokenApproval, + ITokenApprovalWithPoolName, } from '../../../interfaces'; import { DEFAULT_PADDING, DEFAULT_PAGE_LIMITS } from '../../../theme'; -import { fetchCatcher, getFFTime } from '../../../utils'; +import { fetchCatcher, fetchPool, getFFTime } from '../../../utils'; import { hasApprovalEvent } from '../../../utils/wsEvents'; +import { PoolContext } from '../../../contexts/PoolContext'; export const TokensApprovals: () => JSX.Element = () => { const { newEvents, lastRefreshTime, clearNewEvents, selectedNamespace } = @@ -49,13 +51,17 @@ export const TokensApprovals: () => JSX.Element = () => { useContext(FilterContext); const { slideID, setSlideSearchParam } = useContext(SlideContext); const { reportFetchError } = useContext(SnackbarContext); + const { poolCache, setPoolCache } = useContext(PoolContext); const { t } = useTranslation(); const [isMounted, setIsMounted] = useState(false); // Token approvals - const [tokenApprovals, setTokenApprovals] = useState(); + const [tokenApprovals, setTokenApprovals] = useState< + ITokenApprovalWithPoolName[] + >([]); // Token approvals totals const [tokenApprovalsTotal, setTokenApprovalsTotal] = useState(0); - const [viewApproval, setViewApproval] = useState(); + const [viewApproval, setViewApproval] = + useState(); const [currentPage, setCurrentPage] = useState(0); const [rowsPerPage, setRowsPerPage] = useState(DEFAULT_PAGE_LIMITS[1]); @@ -72,10 +78,21 @@ export const TokensApprovals: () => JSX.Element = () => { fetchCatcher( `${FF_Paths.nsPrefix}/${selectedNamespace}${FF_Paths.tokenApprovals}?localid=${slideID}` ) - .then((approvalRes: ITokenApproval[]) => { - isMounted && - approvalRes.length === 1 && - setViewApproval(approvalRes[0]); + .then(async (approvalRes: ITokenApproval[]) => { + if (isMounted && approvalRes.length === 1) { + const item = approvalRes[0]; + const pool = await fetchPool( + selectedNamespace, + item.pool, + poolCache, + setPoolCache + ); + const approvalWithPoolName: ITokenApprovalWithPoolName = { + ...item, + poolName: pool ? pool.name : item.pool, + }; + setViewApproval(approvalWithPoolName); + } }) .catch((err) => { reportFetchError(err); @@ -93,8 +110,23 @@ export const TokensApprovals: () => JSX.Element = () => { dateFilter.filterString }${filterString ?? ''}` ) - .then((tokenApprovalRes: IPagedTokenApprovalResponse) => { - setTokenApprovals(tokenApprovalRes.items); + .then(async (tokenApprovalRes: IPagedTokenApprovalResponse) => { + for (const item of tokenApprovalRes.items) { + const pool = await fetchPool( + selectedNamespace, + item.pool, + poolCache, + setPoolCache + ); + const approval: ITokenApprovalWithPoolName = { + ...item, + poolName: pool ? pool.name : item.pool, + }; + setTokenApprovals((tokenApprovals) => [ + ...tokenApprovals, + approval, + ]); + } setTokenApprovalsTotal(tokenApprovalRes.total); }) .catch((err) => { @@ -133,7 +165,7 @@ export const TokensApprovals: () => JSX.Element = () => { value: , }, { - value: , + value: , }, { value: , diff --git a/src/pages/Tokens/views/Balances.tsx b/src/pages/Tokens/views/Balances.tsx index 2fde7cce..fc6b7f19 100644 --- a/src/pages/Tokens/views/Balances.tsx +++ b/src/pages/Tokens/views/Balances.tsx @@ -36,11 +36,10 @@ import { IDataTableRecord, IPagedTokenBalanceResponse, ITokenBalance, - ITokenPool, ITokenBalanceWithPoolName, } from '../../../interfaces'; import { DEFAULT_PADDING, DEFAULT_PAGE_LIMITS } from '../../../theme'; -import { fetchCatcher, fetchWithCredentials, getFFTime } from '../../../utils'; +import { fetchCatcher, fetchPool, getFFTime } from '../../../utils'; import { hasTransferEvent } from '../../../utils/wsEvents'; import { PoolContext } from '../../../contexts/PoolContext'; @@ -74,24 +73,6 @@ export const TokensBalances: () => JSX.Element = () => { }; }, []); - const fetchPool = async ( - namespace: string, - id: string - ): Promise => { - if (poolCache.has(id)) { - return poolCache.get(id); - } - const response = await fetchWithCredentials( - `/api/v1/namespaces/${namespace}/tokens/pools/${id}` - ); - if (!response.ok) { - return undefined; - } - const pool: ITokenPool = await response.json(); - poolCache.set(id, pool); - return pool; - }; - useEffect(() => { if (isMounted && slideID) { // Expected structure: || @@ -131,7 +112,12 @@ export const TokensBalances: () => JSX.Element = () => { .then(async (tokenBalancesRes: IPagedTokenBalanceResponse) => { setTokenBalancesTotal(tokenBalancesRes.total); for (const item of tokenBalancesRes.items) { - const pool = await fetchPool(selectedNamespace, item.pool); + const pool = await fetchPool( + selectedNamespace, + item.pool, + poolCache, + setPoolCache + ); const balance = { ...item, poolName: pool ? pool.name : item.pool, diff --git a/src/pages/Tokens/views/Dashboard.tsx b/src/pages/Tokens/views/Dashboard.tsx index f21ce771..1cbf404e 100644 --- a/src/pages/Tokens/views/Dashboard.tsx +++ b/src/pages/Tokens/views/Dashboard.tsx @@ -67,7 +67,7 @@ import { } from '../../../theme'; import { fetchCatcher, - fetchWithCredentials, + fetchPool, getFFTime, jsNumberForAddress, } from '../../../utils'; @@ -134,24 +134,6 @@ export const TokensDashboard: () => JSX.Element = () => { }; }, []); - const fetchPool = async ( - namespace: string, - id: string - ): Promise => { - if (poolCache.has(id)) { - return poolCache.get(id); - } - const response = await fetchWithCredentials( - `/api/v1/namespaces/${namespace}/tokens/pools/${id}` - ); - if (!response.ok) { - return undefined; - } - const pool: ITokenPool = await response.json(); - poolCache.set(id, pool); - return pool; - }; - useEffect(() => { if (isMounted && slideID) { // Expected structure: || @@ -434,7 +416,12 @@ export const TokensDashboard: () => JSX.Element = () => { ) .then(async (balances: ITokenBalance[]) => { for (const balance of balances) { - const pool = await fetchPool(selectedNamespace, balance.pool); + const pool = await fetchPool( + selectedNamespace, + balance.pool, + poolCache, + setPoolCache + ); const balanceWithPoolName = { ...balance, poolName: pool ? pool.name : balance.pool, diff --git a/src/pages/Tokens/views/Pools.tsx b/src/pages/Tokens/views/Pools.tsx index d081c5d0..2e96e47e 100644 --- a/src/pages/Tokens/views/Pools.tsx +++ b/src/pages/Tokens/views/Pools.tsx @@ -42,7 +42,6 @@ import { import { DEFAULT_PADDING, DEFAULT_PAGE_LIMITS } from '../../../theme'; import { fetchCatcher, getFFTime, jsNumberForAddress } from '../../../utils'; import { hasPoolEvent } from '../../../utils/wsEvents'; -import { PoolContext } from '../../../contexts/PoolContext'; export const TokensPools: () => JSX.Element = () => { const { newEvents, lastRefreshTime, clearNewEvents, selectedNamespace } = @@ -51,7 +50,6 @@ export const TokensPools: () => JSX.Element = () => { const { filterAnchor, setFilterAnchor, filterString } = useContext(FilterContext); const { reportFetchError } = useContext(SnackbarContext); - const { poolCache } = useContext(PoolContext); const { t } = useTranslation(); const navigate = useNavigate(); const [isMounted, setIsMounted] = useState(false); @@ -69,8 +67,6 @@ export const TokensPools: () => JSX.Element = () => { }; }, []); - console.log(poolCache); - // Token pools useEffect(() => { isMounted && diff --git a/src/utils/fetches.ts b/src/utils/fetches.ts index d68fd278..46c792e2 100644 --- a/src/utils/fetches.ts +++ b/src/utils/fetches.ts @@ -1,3 +1,6 @@ +import { Dispatch, SetStateAction } from 'react'; +import { ITokenPool } from '../interfaces'; + export const fetchWithCredentials = ( resource: string, options?: RequestInit @@ -48,3 +51,23 @@ export const summarizeFetchError = async ( } return message; }; + +export const fetchPool = async ( + namespace: string, + id: string, + poolCache: Map, + setPoolCache: Dispatch>> +): Promise => { + if (poolCache.has(id)) { + return poolCache.get(id); + } + const response = await fetchWithCredentials( + `/api/v1/namespaces/${namespace}/tokens/pools/${id}` + ); + if (!response.ok) { + return undefined; + } + const pool: ITokenPool = await response.json(); + setPoolCache((poolCache) => new Map(poolCache.set(pool.id, pool))); + return pool; +};