Skip to content

Commit d6ab674

Browse files
committed
Merge branch 'main' of https://github.com/PotLock/potlock-nextjs-app into 317-bug-fix-project-registration-fllow
2 parents b234589 + dc15fdb commit d6ab674

File tree

17 files changed

+219
-140
lines changed

17 files changed

+219
-140
lines changed

src/common/contracts/core/voting/hooks.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,12 @@ export const useUniqueVoters = ({ enabled = true, electionId }: BasicElectionQue
114114
);
115115

116116
export const usePotElections = ({ enabled = true, potId }: ByPotId & ConditionalActivation) => {
117-
const { data: elections, isLoading } = useElections({ enabled });
117+
const { data: elections, ...queryResult } = useElections({ enabled });
118118

119119
return {
120-
isLoading,
120+
...queryResult,
121121

122-
elections: elections?.filter(
122+
data: elections?.filter(
123123
({ election_type }) =>
124124
typeof election_type === "object" && "Pot" in election_type && election_type.Pot === potId,
125125
),
@@ -130,10 +130,12 @@ export const useActivePotElections = ({
130130
enabled = true,
131131
potId,
132132
}: ByPotId & ConditionalActivation) => {
133-
const { data: activeElections } = useActiveElections({ enabled });
133+
const { data: activeElections, ...queryResult } = useActiveElections({ enabled });
134134

135135
return {
136-
activeElections: activeElections?.filter(
136+
...queryResult,
137+
138+
data: activeElections?.filter(
137139
([_electionId, { election_type }]) =>
138140
typeof election_type === "object" && "Pot" in election_type && election_type.Pot === potId,
139141
),

src/common/lib/format.ts

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export { formatNearAmount, parseNearAmount };
99
export const indivisibleUnitsToBigNum = (amount: IndivisibleUnits, decimals: number) =>
1010
Big(amount).div(Big(10).pow(decimals));
1111

12+
export const bigNumToIndivisible = (amount: Big.Big, decimals: number): IndivisibleUnits =>
13+
amount.mul(Big(10).pow(decimals)).toFixed().toString();
14+
1215
// TODO: Adjust all consuming code with custom precision
1316
export const indivisibleUnitsToFloat = (
1417
amount: IndivisibleUnits,

src/entities/pot/hooks/feature-flags.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ import { ByPotId } from "@/common/api/indexer";
44
import { votingContractHooks } from "@/common/contracts/core/voting";
55

66
export const usePotFeatureFlags = ({ potId }: ByPotId) => {
7-
const { isLoading: isPotExtensionConfigLoading, elections } = votingContractHooks.usePotElections(
8-
{
7+
const { isLoading: isPotExtensionConfigLoading, data: elections } =
8+
votingContractHooks.usePotElections({
99
potId,
10-
},
11-
);
10+
});
1211

1312
return useMemo(
1413
() => ({
1514
isPotExtensionConfigLoading,
1615
hasProportionalFundingMechanism: (elections?.length ?? 0) > 0,
1716
}),
17+
1818
[isPotExtensionConfigLoading, elections?.length],
1919
);
2020
};

src/entities/voting-round/components/ResultsTable.tsx

+51-50
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { cn } from "@/common/ui/utils";
1414
import { VotingRoundVoteRow } from "./VoteRow";
1515
import { VotingRoundWinnerRow } from "./WinnerRow";
1616
import { useVotingRoundResults } from "../hooks/results";
17-
import { sortByAccumulatedWeight } from "../utils/weight";
1817

1918
export type VotingRoundResultsTableProps = ByPotId & {};
2019

@@ -26,63 +25,65 @@ export const VotingRoundResultsTable: React.FC<VotingRoundResultsTableProps> = (
2625
() =>
2726
roundResults.data === undefined
2827
? null
29-
: sortByAccumulatedWeight(values(roundResults.data.winners), "desc").map(
30-
(winner, index) => (
31-
<AccordionItem key={winner.accountId} value={winner.accountId}>
32-
<AccordionTrigger
33-
className={cn("py-0 underline-offset-4 hover:bg-[#FEF6EE]", {
34-
"bg-neutral-50/40": expandedRows.includes(winner.accountId),
35-
})}
28+
: values(roundResults.data.winners).map((winner) => (
29+
<AccordionItem
30+
key={winner.accountId}
31+
value={winner.accountId}
32+
style={{ order: winner.rank }}
33+
>
34+
<AccordionTrigger
35+
className={cn("py-0 underline-offset-4 hover:bg-[#FEF6EE]", {
36+
"bg-neutral-50/40": expandedRows.includes(winner.accountId),
37+
})}
38+
>
39+
<VotingRoundWinnerRow key={winner.accountId} data={winner} rank={winner.rank} />
40+
</AccordionTrigger>
41+
42+
<AccordionContent className="gap-3 bg-neutral-50/40 px-6 pt-3">
43+
<div
44+
className={cn(
45+
"flex justify-between text-nowrap rounded-lg",
46+
"bg-neutral-50 text-xs text-neutral-500",
47+
)}
3648
>
37-
<VotingRoundWinnerRow key={winner.accountId} data={winner} rank={index + 1} />
38-
</AccordionTrigger>
39-
40-
<AccordionContent className="gap-3 bg-neutral-50/40 px-6 pt-3">
4149
<div
42-
className={cn(
43-
"flex justify-between text-nowrap rounded-lg",
44-
"bg-neutral-50 text-xs text-neutral-500",
45-
)}
50+
className={"mr-a inline-flex h-10 items-center justify-start gap-2 px-4 py-2"}
4651
>
47-
<div
48-
className={"mr-a inline-flex h-10 items-center justify-start gap-2 px-4 py-2"}
49-
>
50-
<span className="font-600 uppercase leading-none">{"Voters"}</span>
52+
<span className="font-600 uppercase leading-none">{"Voters"}</span>
53+
</div>
54+
55+
<div className="hidden md:flex">
56+
<div className="flex h-10 items-center px-4 py-2">
57+
<span className="font-600 w-80 text-end uppercase leading-none">
58+
{"Weight amplifiers"}
59+
</span>
5160
</div>
5261

53-
<div className="hidden md:flex">
54-
<div className="flex h-10 items-center px-4 py-2">
55-
<span className="font-600 w-80 text-end uppercase leading-none">
56-
{"Weight amplifiers"}
57-
</span>
58-
</div>
59-
60-
<div className="flex h-10 items-center px-4 py-2">
61-
<span className="font-600 w-14 text-end uppercase leading-none">
62-
{"Weight"}
63-
</span>
64-
</div>
65-
66-
<span className="flex h-10 items-center px-4 py-2">
67-
<span className="w-50 font-600 text-end uppercase leading-none">
68-
{"Timestamp"}
69-
</span>
62+
<div className="flex h-10 items-center px-4 py-2">
63+
<span className="font-600 w-14 text-end uppercase leading-none">
64+
{"Weight"}
7065
</span>
7166
</div>
72-
</div>
7367

74-
{winner.votes.map((vote) => (
75-
<VotingRoundVoteRow
76-
key={vote.timestamp + vote.voter}
77-
compact
78-
data={vote}
79-
{...{ potId }}
80-
/>
81-
))}
82-
</AccordionContent>
83-
</AccordionItem>
84-
),
85-
),
68+
<span className="flex h-10 items-center px-4 py-2">
69+
<span className="w-50 font-600 text-end uppercase leading-none">
70+
{"Timestamp"}
71+
</span>
72+
</span>
73+
</div>
74+
</div>
75+
76+
{winner.votes.map((vote) => (
77+
<VotingRoundVoteRow
78+
key={vote.timestamp + vote.voter}
79+
compact
80+
data={vote}
81+
{...{ potId }}
82+
/>
83+
))}
84+
</AccordionContent>
85+
</AccordionItem>
86+
)),
8687

8788
[expandedRows, potId, roundResults.data],
8889
);

src/entities/voting-round/components/WinnerRow.tsx

+16-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { useCallback } from "react";
33
import { CheckedState } from "@radix-ui/react-checkbox";
44
import { Dot } from "lucide-react";
55

6-
import { NATIVE_TOKEN_ID } from "@/common/constants";
6+
import { NATIVE_TOKEN_DECIMALS, NATIVE_TOKEN_ID } from "@/common/constants";
7+
import { indivisibleUnitsToFloat } from "@/common/lib";
78
import {
89
Checkbox,
910
LabeledIcon,
@@ -90,15 +91,27 @@ export const VotingRoundWinnerRow: React.FC<VotingRoundWinnerRowProps> = ({
9091
<TooltipTrigger>
9192
<LabeledIcon
9293
positioning="icon-text"
93-
caption={`~ ${estimatedPayoutAmount.toFixed(2)}`}
94+
caption={`~ ${indivisibleUnitsToFloat(
95+
estimatedPayoutAmount,
96+
NATIVE_TOKEN_DECIMALS,
97+
2,
98+
)}`}
9499
classNames={{ root: "w-50 justify-end", caption: "font-600" }}
95100
>
96101
{token && <TokenIcon size="xs" tokenId={token.tokenId} />}
97102
</LabeledIcon>
98103
</TooltipTrigger>
99104

100105
<TooltipContent>
101-
<span className="font-600">{`${estimatedPayoutAmount} ${token?.metadata.symbol}`}</span>
106+
<span className="font-600">
107+
{`${indivisibleUnitsToFloat(
108+
estimatedPayoutAmount,
109+
NATIVE_TOKEN_DECIMALS,
110+
NATIVE_TOKEN_DECIMALS,
111+
)}
112+
113+
${token?.metadata.symbol ?? "..."}`}
114+
</span>
102115
</TooltipContent>
103116
</Tooltip>
104117
</div>

src/entities/voting-round/components/Leaderboard.tsx src/entities/voting-round/components/leaderboard.tsx

+13-19
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
import { useMemo } from "react";
2-
31
import { values } from "remeda";
42

53
import { type ByPotId } from "@/common/api/indexer";
6-
import { NATIVE_TOKEN_ID } from "@/common/constants";
4+
import { NATIVE_TOKEN_DECIMALS, NATIVE_TOKEN_ID } from "@/common/constants";
5+
import { indivisibleUnitsToFloat } from "@/common/lib";
76
import { LabeledIcon, Skeleton } from "@/common/ui/components";
87
import { cn } from "@/common/ui/utils";
98
import { AccountHandle, AccountProfilePicture } from "@/entities/_shared/account";
109
import { TokenIcon } from "@/entities/_shared/token";
1110

1211
import { useVotingRoundResults } from "../hooks/results";
13-
import { sortByAccumulatedWeight } from "../utils/weight";
1412

1513
const VotingRoundLeaderboardItemsPlaceholder = () =>
1614
Array.from({ length: 3 }).map((_, index) => (
@@ -22,37 +20,29 @@ export type VotingRoundLeaderboardProps = ByPotId & {};
2220
export const VotingRoundLeaderboard: React.FC<VotingRoundLeaderboardProps> = ({ potId }) => {
2321
const votingRoundResults = useVotingRoundResults({ potId });
2422

25-
const leadingPositions = useMemo(
26-
() =>
27-
votingRoundResults.data === undefined
28-
? []
29-
: sortByAccumulatedWeight(values(votingRoundResults.data.winners), "desc").slice(0, 3),
30-
31-
[votingRoundResults.data],
32-
);
33-
3423
return (
35-
<div className="md:max-w-126.5 flex w-full flex-col gap-3 rounded-3xl bg-neutral-50 p-3">
24+
<div className="md:max-w-126.5 flex h-60 w-full flex-col gap-3 overflow-y-scroll rounded-3xl bg-neutral-50 p-3">
3625
{votingRoundResults.data === undefined && <VotingRoundLeaderboardItemsPlaceholder />}
3726

3827
{votingRoundResults.data !== undefined &&
39-
leadingPositions.map(
40-
({ accountId, votes, accumulatedWeight, estimatedPayoutAmount }, index) => {
28+
values(votingRoundResults.data.winners).map(
29+
({ rank, accountId, votes, accumulatedWeight, estimatedPayoutAmount }) => {
4130
return (
4231
<div
4332
key={accountId}
4433
className={cn(
45-
"elevation-low inline-flex h-16 items-center justify-start gap-2 md:gap-6",
34+
"elevation-low inline-flex h-16 min-h-16 items-center justify-start gap-2 md:gap-6",
4635
"bg-background overflow-hidden rounded-2xl p-3",
4736
)}
37+
style={{ order: rank }}
4838
>
4939
<div
5040
className={cn(
5141
"flex h-8 w-8 shrink-0 items-center justify-center",
5242
"rounded-full border border-neutral-200",
5343
)}
5444
>
55-
<span className="text-right text-xs font-medium leading-none">{index + 1}</span>
45+
<span className="text-right text-xs font-medium leading-none">{rank}</span>
5646
</div>
5747

5848
<div className="flex h-10 shrink grow basis-0 items-center justify-start gap-4">
@@ -83,7 +73,11 @@ export const VotingRoundLeaderboard: React.FC<VotingRoundLeaderboardProps> = ({
8373
>
8474
<LabeledIcon
8575
positioning="icon-text"
86-
caption={estimatedPayoutAmount.toFixed(2)}
76+
caption={indivisibleUnitsToFloat(
77+
estimatedPayoutAmount,
78+
NATIVE_TOKEN_DECIMALS,
79+
2,
80+
)}
8781
classNames={{
8882
caption: "font-600 text-sm gap-1.5 text-nowrap",
8983
}}

src/entities/voting-round/hooks/results.ts

+20-6
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import { useCallback, useMemo } from "react";
33
import { values } from "remeda";
44

55
import { indexer } from "@/common/api/indexer";
6-
import { NATIVE_TOKEN_DECIMALS } from "@/common/constants";
6+
import { NATIVE_TOKEN_DECIMALS, NATIVE_TOKEN_ID } from "@/common/constants";
7+
import { potContractHooks } from "@/common/contracts/core/pot";
78
import { type ElectionId, votingContractHooks } from "@/common/contracts/core/voting";
89
import { indivisibleUnitsToBigNum } from "@/common/lib";
910
import type { ConditionalActivation } from "@/common/types";
11+
import { useToken } from "@/entities/_shared";
1012
import { usePotFeatureFlags } from "@/entities/pot";
1113

1214
import { useVotingRoundResultsStore } from "../model/results";
@@ -18,12 +20,22 @@ export const useVotingRoundResults = ({
1820
potId,
1921
enabled = true,
2022
}: VotingRoundKey & ConditionalActivation) => {
21-
const { data: pot } = indexer.usePot({ enabled, potId });
23+
const { data: potConfig } = potContractHooks.useConfig({ enabled, potId });
2224
const { hasProportionalFundingMechanism } = usePotFeatureFlags({ potId });
25+
26+
const { data: matchingPoolToken } = useToken({
27+
enabled: potConfig !== undefined,
28+
29+
tokenId:
30+
potConfig !== undefined && "matching_pool_token_id" in potConfig
31+
? ((potConfig?.matching_pool_token_id as string) ?? NATIVE_TOKEN_ID)
32+
: NATIVE_TOKEN_ID,
33+
});
34+
2335
// TODO: Implement mechanism config storage ( Pots V2 milestone )
2436
const mechanismConfig = VOTING_ROUND_CONFIG_MPDAO;
2537

26-
const votingRound = useVotingRound({
38+
const { data: votingRound } = useVotingRound({
2739
enabled: enabled && hasProportionalFundingMechanism,
2840
potId,
2941
});
@@ -61,13 +73,13 @@ export const useVotingRoundResults = ({
6173
if (
6274
enabled &&
6375
hasProportionalFundingMechanism &&
64-
pot &&
76+
potConfig &&
77+
matchingPoolToken &&
6578
votingRound &&
6679
votes &&
6780
voterAccountList &&
6881
voterStatsSnapshot
6982
) {
70-
// Recalculate results if votes have changed
7183
if (!resultsCache || resultsCache.totalVoteCount !== votes.length) {
7284
store.revalidate({
7385
electionId: votingRound.electionId,
@@ -77,9 +89,11 @@ export const useVotingRoundResults = ({
7789
voterStatsSnapshot: voterStatsSnapshot.results,
7890

7991
matchingPoolBalance: indivisibleUnitsToBigNum(
80-
pot.matching_pool_balance,
92+
potConfig.matching_pool_balance,
8193
NATIVE_TOKEN_DECIMALS,
8294
),
95+
96+
matchingPoolTokenMetadata: matchingPoolToken.metadata,
8397
});
8498
}
8599
}

0 commit comments

Comments
 (0)