Skip to content

Commit e3da0f1

Browse files
refactor(web): refactor-logic
1 parent 364ad1f commit e3da0f1

File tree

4 files changed

+92
-103
lines changed

4 files changed

+92
-103
lines changed

web/src/hooks/usePNKData.tsx

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { useAccount } from "wagmi";
2+
3+
import { DEFAULT_CHAIN } from "consts/chains";
4+
5+
import { REFETCH_INTERVAL } from "src/consts";
6+
import { isUndefined } from "src/utils";
7+
8+
import {
9+
klerosCoreAddress,
10+
useReadPnkAllowance,
11+
useReadPnkBalanceOf,
12+
useReadSortitionModuleGetJurorBalance,
13+
} from "./contracts/generated";
14+
15+
interface UsePnkDataParams {
16+
courtId?: string;
17+
}
18+
19+
/**
20+
* @description hook to provide user's pnk data. (pnk balance, pnk allowance, jurorBalance for provided courtId)
21+
* @param param0 optional court Id to fetch juror balance for. Defaults to 0
22+
*/
23+
export const usePnkData = ({ courtId = "0" }: UsePnkDataParams) => {
24+
const { address } = useAccount();
25+
const queryConfig = {
26+
enabled: !isUndefined(address),
27+
refetchInterval: REFETCH_INTERVAL,
28+
};
29+
30+
const { data: balance } = useReadPnkBalanceOf({
31+
query: queryConfig,
32+
args: [address!],
33+
});
34+
35+
const { data: jurorBalance } = useReadSortitionModuleGetJurorBalance({
36+
query: queryConfig,
37+
args: [address ?? "0x", BigInt(courtId)],
38+
});
39+
40+
const { data: allowance, refetch: refetchAllowance } = useReadPnkAllowance({
41+
query: queryConfig,
42+
args: [address ?? "0x", klerosCoreAddress[DEFAULT_CHAIN]],
43+
});
44+
45+
return { balance, jurorBalance, allowance, refetchAllowance };
46+
};

web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx

+4-18
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ import styled, { css } from "styled-components";
33

44
import { useParams } from "react-router-dom";
55
import { useDebounce } from "react-use";
6-
import { useAccount } from "wagmi";
76

8-
import { REFETCH_INTERVAL } from "consts/index";
9-
import { useReadSortitionModuleGetJurorBalance, useReadPnkBalanceOf } from "hooks/contracts/generated";
107
import { useParsedAmount } from "hooks/useParsedAmount";
8+
import { usePnkData } from "hooks/usePNKData";
119
import { commify, uncommify } from "utils/commify";
1210
import { formatPNK, roundNumberDown } from "utils/format";
1311
import { isUndefined } from "utils/index";
@@ -82,22 +80,10 @@ const InputDisplay: React.FC<IInputDisplay> = ({ action, amount, setAmount }) =>
8280
const parsedAmount = useParsedAmount(uncommify(debouncedAmount) as `${number}`);
8381

8482
const { id } = useParams();
85-
const { address } = useAccount();
86-
const { data: balance } = useReadPnkBalanceOf({
87-
query: {
88-
enabled: !isUndefined(address),
89-
refetchInterval: REFETCH_INTERVAL,
90-
},
91-
args: [address ?? "0x"],
92-
});
83+
const { balance, jurorBalance } = usePnkData({ courtId: id });
84+
9385
const parsedBalance = formatPNK(balance ?? 0n, 0, true);
94-
const { data: jurorBalance } = useReadSortitionModuleGetJurorBalance({
95-
query: {
96-
enabled: !isUndefined(address),
97-
refetchInterval: REFETCH_INTERVAL,
98-
},
99-
args: [address ?? "0x", BigInt(id ?? "0")],
100-
});
86+
10187
const parsedStake = formatPNK(jurorBalance?.[2] ?? 0n, 0, true);
10288
const isStaking = useMemo(() => action === ActionType.stake, [action]);
10389

web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx

+17-85
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
import React, { useCallback, useEffect, useMemo, useState } from "react";
2-
import styled, { useTheme } from "styled-components";
2+
import styled, { DefaultTheme, useTheme } from "styled-components";
33

44
import { useParams } from "react-router-dom";
55
import { type TransactionReceipt } from "viem";
6-
import { useAccount, usePublicClient } from "wagmi";
6+
import { usePublicClient } from "wagmi";
77

88
import { type _TimelineItem1, Button } from "@kleros/ui-components-library";
99

1010
import { DEFAULT_CHAIN } from "consts/chains";
11-
import { REFETCH_INTERVAL } from "consts/index";
1211
import {
1312
klerosCoreAddress,
1413
useSimulateKlerosCoreSetStake,
1514
useWriteKlerosCoreSetStake,
16-
useReadPnkBalanceOf,
1715
useSimulatePnkIncreaseAllowance,
1816
useWritePnkIncreaseAllowance,
19-
useReadSortitionModuleGetJurorBalance,
20-
useReadPnkAllowance,
2117
} from "hooks/contracts/generated";
2218
import { useCourtDetails } from "hooks/queries/useCourtDetails";
19+
import { usePnkData } from "hooks/usePNKData";
2320
import { formatETH } from "utils/format";
2421
import { isUndefined } from "utils/index";
2522
import { parseWagmiError } from "utils/parseWagmiError";
23+
import { refetchWithRetry } from "utils/refecthWithRetry";
2624

2725
import { EnsureChain } from "components/EnsureChain";
2826

@@ -51,35 +49,14 @@ interface IActionButton {
5149

5250
const StakeWithdrawButton: React.FC<IActionButton> = ({ amount, parsedAmount, action, setErrorMsg, setAmount }) => {
5351
const { id } = useParams();
54-
const { address } = useAccount();
5552
const theme = useTheme();
5653
const [isPopupOpen, setIsPopupOpen] = useState(false);
5754
const [isSuccess, setIsSuccess] = useState(false);
5855
const [popupStepsState, setPopupStepsState] = useState<[_TimelineItem1, ..._TimelineItem1[]]>();
5956

6057
const { data: courtDetails } = useCourtDetails(id);
61-
const { data: balance } = useReadPnkBalanceOf({
62-
query: {
63-
enabled: !isUndefined(address),
64-
refetchInterval: REFETCH_INTERVAL,
65-
},
66-
args: [address!],
67-
});
58+
const { balance, jurorBalance, allowance, refetchAllowance } = usePnkData({ courtId: id });
6859

69-
const { data: jurorBalance } = useReadSortitionModuleGetJurorBalance({
70-
query: {
71-
enabled: !isUndefined(address),
72-
refetchInterval: REFETCH_INTERVAL,
73-
},
74-
args: [address ?? "0x", BigInt(id ?? 0)],
75-
});
76-
const { data: allowance, refetch: refetchAllowance } = useReadPnkAllowance({
77-
query: {
78-
enabled: !isUndefined(address),
79-
refetchInterval: REFETCH_INTERVAL,
80-
},
81-
args: [address ?? "0x", klerosCoreAddress[DEFAULT_CHAIN]],
82-
});
8360
const publicClient = usePublicClient();
8461

8562
const isStaking = action === ActionType.stake;
@@ -134,60 +111,40 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({ amount, parsedAmount, ac
134111
(config?: typeof setStakeConfig, approvalHash?: `0x${string}`) => {
135112
const isWithdraw = action === ActionType.withdraw;
136113
const requestData = config?.request ?? setStakeConfig?.request;
114+
const commonArgs: [string, DefaultTheme, `0x${string}` | undefined] = [amount, theme, approvalHash];
137115

138116
if (requestData && publicClient) {
139117
setPopupStepsState(
140-
getStakeSteps(
141-
isWithdraw ? StakeSteps.WithdrawInitiate : StakeSteps.StakeInitiate,
142-
amount,
143-
theme,
144-
approvalHash
145-
)
118+
getStakeSteps(isWithdraw ? StakeSteps.WithdrawInitiate : StakeSteps.StakeInitiate, ...commonArgs)
146119
);
147120

148121
setStake(requestData)
149122
.then(async (hash) => {
150123
setPopupStepsState(
151-
getStakeSteps(
152-
isWithdraw ? StakeSteps.WithdrawPending : StakeSteps.StakePending,
153-
amount,
154-
theme,
155-
approvalHash,
156-
hash
157-
)
124+
getStakeSteps(isWithdraw ? StakeSteps.WithdrawPending : StakeSteps.StakePending, ...commonArgs, hash)
158125
);
159126
await publicClient.waitForTransactionReceipt({ hash, confirmations: 2 }).then((res: TransactionReceipt) => {
160127
const status = res.status === "success";
161128
if (status) {
162129
setPopupStepsState(
163130
getStakeSteps(
164131
isWithdraw ? StakeSteps.WithdrawConfirmed : StakeSteps.StakeConfirmed,
165-
amount,
166-
theme,
167-
approvalHash,
132+
...commonArgs,
168133
hash
169134
)
170135
);
171136
setIsSuccess(true);
172137
} else
173138
setPopupStepsState(
174-
getStakeSteps(
175-
isWithdraw ? StakeSteps.WithdrawFailed : StakeSteps.StakeFailed,
176-
amount,
177-
theme,
178-
approvalHash,
179-
hash
180-
)
139+
getStakeSteps(isWithdraw ? StakeSteps.WithdrawFailed : StakeSteps.StakeFailed, ...commonArgs, hash)
181140
);
182141
});
183142
})
184143
.catch((err) => {
185144
setPopupStepsState(
186145
getStakeSteps(
187146
isWithdraw ? StakeSteps.WithdrawFailed : StakeSteps.StakeFailed,
188-
amount,
189-
theme,
190-
approvalHash,
147+
...commonArgs,
191148
undefined,
192149
err
193150
)
@@ -201,11 +158,12 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({ amount, parsedAmount, ac
201158
const handleClick = useCallback(() => {
202159
setIsPopupOpen(true);
203160
if (isAllowance && increaseAllowanceConfig && publicClient) {
204-
setPopupStepsState(getStakeSteps(StakeSteps.ApproveInitiate, amount, theme));
161+
const commonArgs: [string, DefaultTheme] = [amount, theme];
162+
setPopupStepsState(getStakeSteps(StakeSteps.ApproveInitiate, ...commonArgs));
205163

206164
increaseAllowance(increaseAllowanceConfig.request)
207165
.then(async (hash) => {
208-
setPopupStepsState(getStakeSteps(StakeSteps.ApprovePending, amount, theme, hash));
166+
setPopupStepsState(getStakeSteps(StakeSteps.ApprovePending, ...commonArgs, hash));
209167

210168
await publicClient
211169
.waitForTransactionReceipt({ hash, confirmations: 2 })
@@ -220,8 +178,7 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({ amount, parsedAmount, ac
220178
setPopupStepsState(
221179
getStakeSteps(
222180
StakeSteps.ApproveFailed,
223-
amount,
224-
theme,
181+
...commonArgs,
225182
hash,
226183
undefined,
227184
new Error("Something went wrong. Please restart the process.")
@@ -230,11 +187,11 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({ amount, parsedAmount, ac
230187
else {
231188
handleStake(refetchData.data, hash);
232189
}
233-
} else setPopupStepsState(getStakeSteps(StakeSteps.ApproveFailed, amount, theme, hash));
190+
} else setPopupStepsState(getStakeSteps(StakeSteps.ApproveFailed, ...commonArgs, hash));
234191
});
235192
})
236193
.catch((err) => {
237-
setPopupStepsState(getStakeSteps(StakeSteps.ApproveFailed, amount, theme, undefined, undefined, err));
194+
setPopupStepsState(getStakeSteps(StakeSteps.ApproveFailed, ...commonArgs, undefined, undefined, err));
238195
});
239196
} else {
240197
handleStake();
@@ -308,29 +265,4 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({ amount, parsedAmount, ac
308265
);
309266
};
310267

311-
async function refetchWithRetry<T>(fn: () => Promise<T>, retryCount = 5, retryDelay = 2000) {
312-
let attempts = 0;
313-
314-
while (attempts < retryCount) {
315-
try {
316-
const returnData = await fn();
317-
318-
//@ts-expect-error data does exist
319-
if (returnData && returnData?.data !== undefined) {
320-
return returnData;
321-
}
322-
} catch (error) {
323-
console.error(`Attempt ${attempts + 1} failed with error:`, error);
324-
}
325-
326-
attempts++;
327-
328-
if (attempts >= retryCount) {
329-
return;
330-
}
331-
332-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
333-
}
334-
return;
335-
}
336268
export default StakeWithdrawButton;

web/src/utils/refecthWithRetry.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
export async function refetchWithRetry<T>(fn: () => Promise<T>, retryCount = 5, retryDelay = 2000) {
2+
let attempts = 0;
3+
4+
while (attempts < retryCount) {
5+
try {
6+
const returnData = await fn();
7+
8+
//@ts-expect-error data does exist
9+
if (returnData && returnData?.data !== undefined) {
10+
return returnData;
11+
}
12+
} catch (error) {
13+
console.error(`Attempt ${attempts + 1} failed with error:`, error);
14+
}
15+
16+
attempts++;
17+
18+
if (attempts >= retryCount) {
19+
return;
20+
}
21+
22+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
23+
}
24+
return;
25+
}

0 commit comments

Comments
 (0)