Skip to content

Commit 8f076f1

Browse files
committed
Detect existing justification document
1 parent 4fcce37 commit 8f076f1

File tree

4 files changed

+40
-18
lines changed

4 files changed

+40
-18
lines changed

src/features/proportional-funding/hooks/payout-justification.ts

+24-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useCallback, useMemo } from "react";
22

33
import { isNonNullish } from "remeda";
4+
import useSWR from "swr";
45

56
import type { ByPotId } from "@/common/api/indexer";
67
import { potContractHooks } from "@/common/contracts/core/pot";
@@ -9,7 +10,8 @@ import { usePotAuthorization } from "@/entities/pot";
910
import { useVotingRoundResults } from "@/entities/voting-round";
1011

1112
import { publishPayoutJustification } from "../model/effects";
12-
import { pfPayoutChallengeToJustification } from "../utils/converters";
13+
import type { PFPayoutJustificationV1 } from "../model/types";
14+
import { pfPayoutChallengeToJustificationUrl } from "../utils/converters";
1315

1416
export type PFPayoutJustificationParams = ByPotId & {
1517
onPublishSuccess?: () => void;
@@ -31,12 +33,23 @@ export const usePFPayoutJustification = ({
3133
mutate: refetchPayoutChallenges,
3234
} = potContractHooks.usePayoutChallenges({ potId });
3335

34-
const currentJustification = useMemo(
35-
() => potPayoutChallengeList?.map(pfPayoutChallengeToJustification).find(isNonNullish),
36+
const documentUrl = useMemo(
37+
() => potPayoutChallengeList?.map(pfPayoutChallengeToJustificationUrl).find(isNonNullish),
3638
[potPayoutChallengeList],
3739
);
3840

39-
const isPublished = useMemo(() => isNonNullish(currentJustification), [currentJustification]);
41+
const { isLoading: isDocumentLoading, data: document } = useSWR(
42+
["payout-justification", documentUrl],
43+
44+
([_queryKeyHead, urlQueryKey]) =>
45+
urlQueryKey === undefined
46+
? undefined
47+
: fetch(urlQueryKey)
48+
.then((res) => res.json())
49+
.then((data: PFPayoutJustificationV1) => data),
50+
);
51+
52+
const isLoading = votingRound.isLoading || isPayoutChallengeListLoading || isDocumentLoading;
4053

4154
const publish = useCallback(() => {
4255
if (viewer.isSignedIn && votingRound.data !== undefined) {
@@ -67,14 +80,16 @@ export const usePFPayoutJustification = ({
6780
return !viewer.isSignedIn || (!votingRound.isLoading && votingRound.data === undefined)
6881
? {
6982
isLoading: false as const,
70-
isPublished: false,
7183
data: undefined,
7284
publish: undefined,
7385
}
7486
: {
75-
isLoading: votingRound.isLoading || isPayoutChallengeListLoading,
76-
isPublished,
77-
data: currentJustification,
78-
publish: isPublished || !viewerPower.isAdminOrGreater ? undefined : publish,
87+
isLoading,
88+
data: document,
89+
90+
publish:
91+
!isLoading && document === undefined && viewerPower.isAdminOrGreater
92+
? publish
93+
: undefined,
7994
};
8095
};

src/features/proportional-funding/model/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ export type PFPayoutJustificationInputs = ByPotId & {
66
votingRoundResult: VotingRoundElectionResult;
77
challengerAccountId: AccountId;
88
};
9+
10+
export type PFPayoutJustificationV1 = VotingRoundElectionResult;
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import type { Challenge } from "@/common/contracts/core/pot";
2-
import type { VotingRoundElectionResult } from "@/entities/voting-round";
32

4-
// TODO: Extract and validate URL as URL
5-
export const pfPayoutChallengeToJustification = (challenge: Challenge) => {
3+
export const pfPayoutChallengeToJustificationUrl = (challenge: Challenge) => {
64
try {
75
const data = JSON.parse(challenge.reason) as Record<string, unknown>;
86

9-
return "PayoutJustification" in data
10-
? (data.PayoutJustification as VotingRoundElectionResult)
11-
: null;
12-
} catch {
13-
console.error("Failed to parse challenge reason as JSON object");
7+
if ("PayoutJustification" in data) {
8+
return new URL(data.PayoutJustification as string).toString();
9+
} else return null;
10+
} catch (error) {
11+
if (error instanceof SyntaxError) {
12+
console.error("Failed to parse payout justification as JSON object");
13+
} else {
14+
console.error("PayoutJustification is not a valid URL");
15+
}
16+
1417
return null;
1518
}
1619
};

src/layout/pot/components/layout-hero.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,9 @@ export const PotLayoutHero: React.FC<PotLayoutHeroProps> = ({
223223

224224
{viewerAbilities.canChallengePayouts && (
225225
<>
226-
{hasPFMechanism && !pfPayoutJustification.isPublished ? null : (
226+
{hasPFMechanism &&
227+
!pfPayoutJustification.isLoading &&
228+
pfPayoutJustification.data === undefined ? null : (
227229
<Button onClick={onChallengePayoutsClick}>
228230
{activeChallenge === undefined ? "Challenge Payouts" : "Update Challenge"}
229231
</Button>

0 commit comments

Comments
 (0)