Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Pool performance data to batches. Per-page fetching, pool join subset. #2057

Merged
merged 42 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
6276a75
remove all pools badge
Apr 3, 2024
3df128c
convert pool reward points to batches
Apr 3, 2024
be4c500
simplify PoolList name
Apr 3, 2024
db11e9e
remove throttle behaviour for pool list
Apr 3, 2024
edac3bc
fix poolSearchFilter type
Apr 3, 2024
0701b20
some pool list tidy up
Apr 3, 2024
957aa62
default pool filters to context defaults
Apr 3, 2024
12fbd65
back to tab 0 on network change.
Apr 3, 2024
a9cbb1c
useEffect for data fetching working
Apr 3, 2024
f0cc547
move pool list tab & fetching state to contexts
Apr 3, 2024
ea7069b
rm log
Apr 3, 2024
c72273a
rm poolRewardPointsFetched, use pool_list batch
Apr 3, 2024
f3e7fca
prepare fetch status to include hash
Apr 3, 2024
f7d85bb
store addresses with fetchd data
Apr 3, 2024
58c7a90
exit fetch if addresses change
Apr 3, 2024
ea5ab9f
set as synced if no addresses
Apr 3, 2024
3ddfe21
expose startGetPoolPerformance
Apr 3, 2024
a89a80d
pool_page sync begining to work
Apr 3, 2024
01708bb
start pool_page performance fetch
Apr 3, 2024
eecce12
support multi-validator pool performance
Apr 3, 2024
88c6498
move era metadata to fetched record
Apr 3, 2024
dbb7bc1
prepare for pool join batch
Apr 3, 2024
aa8ab4b
remove TODO
Apr 3, 2024
1a55751
comment
Apr 3, 2024
5774b3e
fix
Apr 3, 2024
c29cc9f
fetch subset of pool data for join
Apr 3, 2024
32cd1dc
remove browse pools button
Apr 3, 2024
73a1f18
improve naming
Apr 4, 2024
01559e0
better naming for getters
Apr 4, 2024
095832d
add find pools loader
Apr 4, 2024
dd6a4ba
decrease pool subset, click to initiate pool find
Apr 4, 2024
a06ca33
fix selectedPoolId logic
Apr 4, 2024
bc26d0e
remove log
Apr 4, 2024
0b7c9f6
decrease max points eras to 10
Apr 4, 2024
35f2b55
remove render throttle from lists
Apr 4, 2024
3cfb8f2
iterms per page per list type
Apr 4, 2024
4f96243
css fix
Apr 4, 2024
f62c3f9
add readyToJoinPool
Apr 4, 2024
4d13aff
use Line instead of Bar
Apr 4, 2024
d44d264
amend dark secondary
Apr 4, 2024
d09a8ba
Update src/locale/cn/library.json
Apr 4, 2024
d2283ab
fix
Apr 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import type { Provider } from 'hooks/withProviders';
import { withProviders } from 'hooks/withProviders';
import { CommunityProvider } from 'contexts/Community';
import { OverlayProvider } from 'kits/Overlay/Provider';
import { JoinPoolsProvider } from 'contexts/Pools/JoinPools';

export const Providers = () => {
const {
Expand Down Expand Up @@ -83,6 +84,7 @@ export const Providers = () => {
FastUnstakeProvider,
PayoutsProvider,
PoolPerformanceProvider,
JoinPoolsProvider,
SetupProvider,
MenuProvider,
TooltipProvider,
Expand Down
11 changes: 6 additions & 5 deletions src/canvas/JoinPool/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,20 @@ export const Header = ({
autoSelected,
setActiveTab,
setSelectedPoolId,
setSelectedPoolCount,
}: JoinPoolHeaderProps) => {
const { t } = useTranslation();
const { closeCanvas } = useOverlay().canvas;

// Randomly select a new pool to display.
const handleChooseNewPool = () => {
// Trigger refresh of memoied selected bonded pool.
setSelectedPoolCount((prev: number) => prev + 1);
// Remove current pool from filtered so it is not selected again.
const filteredPools = filteredBondedPools.filter(
(pool) => String(pool.id) !== String(bondedPool.id)
);

// Randomly select a filtered bonded pool and set it as the selected pool.
const index = Math.ceil(Math.random() * filteredBondedPools.length - 1);
setSelectedPoolId(filteredBondedPools[index].id);
const index = Math.ceil(Math.random() * filteredPools.length - 1);
setSelectedPoolId(filteredPools[index].id);
};

return (
Expand Down
4 changes: 3 additions & 1 deletion src/canvas/JoinPool/Overview/PerformanceGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ export const PerformanceGraph = ({ bondedPool }: OverviewSectionProps) => {
const { mode } = useTheme();
const { openHelp } = useHelp();
const { colors } = useNetwork().networkData;
const { poolRewardPoints } = usePoolPerformance();
const { getPoolRewardPoints } = usePoolPerformance();

const poolRewardPoints = getPoolRewardPoints('pool_join');
const rawEraRewardPoints = poolRewardPoints[bondedPool.addresses.stash] || {};

// Ref to the graph container.
Expand Down
50 changes: 30 additions & 20 deletions src/canvas/JoinPool/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,35 @@ import { CanvasFullScreenWrapper } from 'canvas/Wrappers';
import { useOverlay } from 'kits/Overlay/Provider';
import { JoinPoolInterfaceWrapper } from './Wrappers';
import { useBondedPools } from 'contexts/Pools/BondedPools';
import { useMemo, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { Header } from './Header';
import { Overview } from './Overview';
import { Nominations } from './Nominations';
import { usePoolPerformance } from 'contexts/Pools/PoolPerformance';
import { MaxEraRewardPointsEras } from 'consts';
import { useStaking } from 'contexts/Staking';
import { useJoinPools } from 'contexts/Pools/JoinPools';

export const JoinPool = () => {
const {
closeCanvas,
config: { options },
} = useOverlay().canvas;
const { eraStakers } = useStaking();
const { poolRewardPoints } = usePoolPerformance();
const { poolsForJoin } = useJoinPools();
const { getPoolRewardPoints } = usePoolPerformance();
const { poolsMetaData, bondedPools } = useBondedPools();
const poolRewardPoints = getPoolRewardPoints('pool_join');

// The active canvas tab.
const [activeTab, setActiveTab] = useState<number>(0);

// Trigger re-render when chosen selected pool is incremented.
const [selectedPoolCount, setSelectedPoolCount] = useState<number>(0);

// Filter bonded pools to only those that are open and that have active daily rewards for the last
// `MaxEraRewardPointsEras` eras. The second filter checks if the pool is in `eraStakers` for the
// active era.
const filteredBondedPools = useMemo(
() =>
bondedPools
poolsForJoin
.filter((pool) => {
// Fetch reward point data for the pool.
const rawEraRewardPoints =
Expand All @@ -53,28 +53,39 @@ export const JoinPool = () => {
staker.others.find(({ who }) => who !== pool.addresses.stash)
)
),
[bondedPools, poolRewardPoints]
[poolsForJoin, poolRewardPoints]
);

// The bonded pool to display. Use the provided `poolId`, or assign a random eligible filtered
// pool otherwise. Re-fetches when the selected pool count is incremented.
const bondedPool = useMemo(
const initialSelectedPoolId = useMemo(
() =>
options?.poolId
? bondedPools.find(({ id }) => id === options.poolId)
: filteredBondedPools[
(filteredBondedPools.length * Math.random()) << 0
],
[selectedPoolCount]
options?.poolId ||
filteredBondedPools[(filteredBondedPools.length * Math.random()) << 0]
.id ||
0,
[]
);

// The selected bonded pool id.
// The selected bonded pool id. Assigns a random id if one is not provided.
const [selectedPoolId, setSelectedPoolId] = useState<number>(
bondedPool?.id || 0
initialSelectedPoolId
);

// The bonded pool to display. Use the provided `poolId`, or assign a random eligible filtered
// pool otherwise. Re-fetches when the selected pool count is incremented.
const bondedPool = useMemo(
() => bondedPools.find(({ id }) => id === selectedPoolId),
[selectedPoolId]
);

// Close canvas if no pool id is selected.
useEffect(() => {
if (selectedPoolId === 0) {
closeCanvas();
}
}, [selectedPoolId]);

// Ensure bonded pool exists before rendering. Canvas should close if this is the case.
if (!bondedPool) {
closeCanvas();
return null;
}

Expand All @@ -86,7 +97,6 @@ export const JoinPool = () => {
setSelectedPoolId={setSelectedPoolId}
bondedPool={bondedPool}
metadata={poolsMetaData[selectedPoolId]}
setSelectedPoolCount={setSelectedPoolCount}
autoSelected={options?.poolId === undefined}
filteredBondedPools={filteredBondedPools}
/>
Expand Down
1 change: 0 additions & 1 deletion src/canvas/JoinPool/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export interface JoinPoolHeaderProps {
autoSelected: boolean;
setActiveTab: (tab: number) => void;
setSelectedPoolId: Dispatch<SetStateAction<number>>;
setSelectedPoolCount: Dispatch<SetStateAction<number>>;
}

export interface NominationsProps {
Expand Down
38 changes: 6 additions & 32 deletions src/canvas/PoolMembers/Lists/Default.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// SPDX-License-Identifier: GPL-3.0-only

import { isNotZero } from '@w3ux/utils';
import { useEffect, useRef, useState } from 'react';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { listItemsPerBatch, listItemsPerPage } from 'library/List/defaults';
import { poolMembersPerPage } from 'library/List/defaults';
import { useApi } from 'contexts/Api';
import { usePoolMembers } from 'contexts/Pools/PoolMembers';
import { List, ListStatusHeader, Wrapper as ListWrapper } from 'library/List';
Expand All @@ -20,7 +20,6 @@ export const MembersListInner = ({
pagination,
batchKey,
members: initialMembers,
disableThrottle = false,
}: DefaultMembersListProps) => {
const { t } = useTranslation('pages');
const { isReady, activeEra } = useApi();
Expand All @@ -29,9 +28,6 @@ export const MembersListInner = ({
// current page
const [page, setPage] = useState<number>(1);

// current render iteration
const [renderIteration, setRenderIterationState] = useState<number>(1);

// default list of validators
const [membersDefault, setMembersDefault] =
useState<PoolMember[]>(initialMembers);
Expand All @@ -42,26 +38,13 @@ export const MembersListInner = ({
// is this the initial fetch
const [fetched, setFetched] = useState<Sync>('unsynced');

// render throttle iteration
const renderIterationRef = useRef(renderIteration);
const setRenderIteration = (iter: number) => {
renderIterationRef.current = iter;
setRenderIterationState(iter);
};

// pagination
const totalPages = Math.ceil(members.length / listItemsPerPage);
const pageEnd = page * listItemsPerPage - 1;
const pageStart = pageEnd - (listItemsPerPage - 1);

// render batch
const batchEnd = Math.min(
renderIteration * listItemsPerBatch - 1,
listItemsPerPage
);
const totalPages = Math.ceil(members.length / poolMembersPerPage);
const pageEnd = page * poolMembersPerPage - 1;
const pageStart = pageEnd - (poolMembersPerPage - 1);

// get throttled subset or entire list
const listMembers = members.slice(pageStart).slice(0, listItemsPerPage);
const listMembers = members.slice(pageStart).slice(0, poolMembersPerPage);

// handle validator list bootstrapping
const setupMembersList = () => {
Expand All @@ -85,15 +68,6 @@ export const MembersListInner = ({
}
}, [isReady, fetched, activeEra.index]);

// Render throttle.
useEffect(() => {
if (!(batchEnd >= pageEnd || disableThrottle)) {
setTimeout(() => {
setRenderIteration(renderIterationRef.current + 1);
}, 500);
}
}, [renderIterationRef.current]);

return !members.length ? null : (
<ListWrapper>
<List $flexBasisLarge={'33.33%'}>
Expand Down
36 changes: 5 additions & 31 deletions src/canvas/PoolMembers/Lists/FetchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { listItemsPerBatch, listItemsPerPage } from 'library/List/defaults';
import { poolMembersPerPage } from 'library/List/defaults';
import { usePlugins } from 'contexts/Plugins';
import { useActivePool } from 'contexts/Pools/ActivePool';
import { usePoolMembers } from 'contexts/Pools/PoolMembers';
Expand All @@ -21,7 +21,6 @@ import { SubscanController } from 'controllers/SubscanController';
export const MembersListInner = ({
pagination,
batchKey,
disableThrottle = false,
memberCount,
}: FetchpageMembersListProps) => {
const { t } = useTranslation('pages');
Expand All @@ -40,26 +39,10 @@ export const MembersListInner = ({
// current page.
const [page, setPage] = useState<number>(1);

// current render iteration.
const [renderIteration, setRenderIterationState] = useState<number>(1);

// render throttle iteration.
const renderIterationRef = useRef(renderIteration);
const setRenderIteration = (iter: number) => {
renderIterationRef.current = iter;
setRenderIterationState(iter);
};

// pagination
const totalPages = Math.ceil(Number(memberCount) / listItemsPerPage);
const pageEnd = listItemsPerPage - 1;
const pageStart = pageEnd - (listItemsPerPage - 1);

// render batch
const batchEnd = Math.min(
renderIteration * listItemsPerBatch - 1,
listItemsPerPage
);
const totalPages = Math.ceil(Number(memberCount) / poolMembersPerPage);
const pageEnd = poolMembersPerPage - 1;
const pageStart = pageEnd - (poolMembersPerPage - 1);

// handle validator list bootstrapping
const fetchingMemberList = useRef<boolean>(false);
Expand All @@ -85,7 +68,7 @@ export const MembersListInner = ({
// get throttled subset or entire list
const listMembers = poolMembersApi
.slice(pageStart)
.slice(0, listItemsPerPage);
.slice(0, poolMembersPerPage);

// Refetch list when page changes.
useEffect(() => {
Expand All @@ -109,15 +92,6 @@ export const MembersListInner = ({
}
}, [fetchedPoolMembersApi, activePool]);

// Render throttle.
useEffect(() => {
if (!(batchEnd >= pageEnd || disableThrottle)) {
setTimeout(() => {
setRenderIteration(renderIterationRef.current + 1);
}, 500);
}
}, [renderIterationRef.current]);

return (
<ListWrapper>
<List $flexBasisLarge={'33.33%'}>
Expand Down
1 change: 0 additions & 1 deletion src/canvas/PoolMembers/Lists/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import type { AnyJson } from 'types';
export interface MembersListProps {
pagination: boolean;
batchKey: string;
disableThrottle?: boolean;
selectToggleable?: boolean;
}

Expand Down
2 changes: 1 addition & 1 deletion src/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ export const TipsThresholdMedium = 1200;
* Misc Values
*/
export const MaxPayoutDays = 60;
export const MaxEraRewardPointsEras = 14;
export const MaxEraRewardPointsEras = 10;
16 changes: 15 additions & 1 deletion src/contexts/Filters/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-only
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function */

import type { FiltersContextInterface } from './types';
import type { FilterItem, FiltersContextInterface } from './types';

export const defaultFiltersInterface: FiltersContextInterface = {
getFilters: (type, group) => [],
Expand All @@ -18,3 +18,17 @@ export const defaultFiltersInterface: FiltersContextInterface = {
applyFilters: (type, g, l, f) => {},
applyOrder: (g, l, f) => {},
};

export const defaultIncludes: FilterItem[] = [
{
key: 'pools',
filters: ['active'],
},
];

export const defaultExcludes: FilterItem[] = [
{
key: 'pools',
filters: ['locked', 'destroying'],
},
];
10 changes: 7 additions & 3 deletions src/contexts/Filters/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
import type { ReactNode } from 'react';
import { createContext, useContext, useState } from 'react';
import type { AnyFunction, AnyJson } from 'types';
import { defaultFiltersInterface } from './defaults';
import {
defaultExcludes,
defaultFiltersInterface,
defaultIncludes,
} from './defaults';
import type {
FilterItem,
FilterItems,
Expand All @@ -24,10 +28,10 @@ export const useFilters = () => useContext(FiltersContext);

export const FiltersProvider = ({ children }: { children: ReactNode }) => {
// groups along with their includes
const [includes, setIncludes] = useState<FilterItems>([]);
const [includes, setIncludes] = useState<FilterItems>(defaultIncludes);

// groups along with their excludes.
const [excludes, setExcludes] = useState<FilterItems>([]);
const [excludes, setExcludes] = useState<FilterItems>(defaultExcludes);

// groups along with their order.
const [orders, setOrders] = useState<FilterOrders>([]);
Expand Down
4 changes: 3 additions & 1 deletion src/contexts/Pools/BondedPools/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ export const defaultBondedPoolsContext: BondedPoolsContextState = {
getPoolNominationStatusCode: (statuses) => '',
getAccountPoolRoles: (address) => null,
replacePoolRoles: (poolId, roleEdits) => {},
poolSearchFilter: (filteredPools, searchTerm) => {},
poolSearchFilter: (filteredPools, searchTerm) => [],
bondedPools: [],
poolsMetaData: {},
poolsNominations: {},
updatePoolNominations: (id, nominations) => {},
poolListActiveTab: 'Active',
setPoolListActiveTab: (tab) => {},
};
Loading
Loading