-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathuseFetchStakingRewards.ts
100 lines (88 loc) · 3.27 KB
/
useFetchStakingRewards.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { useEffect } from "react"
import { useSelector, useDispatch } from "react-redux"
import {
useMerkleDropContract,
DEPLOYMENT_BLOCK,
} from "../web3/hooks/useMerkleDropContract"
import rewardsData from "../merkle-drop/rewards.json"
import { getContractPastEvents, getAddress } from "../web3/utils"
import { RewardsJSONData } from "../types"
import { RootState } from "../store"
import { setInterimRewards } from "../store/rewards"
import { selectStakingProviders } from "../store/staking"
import { BigNumber } from "ethers"
import { Zero } from "@ethersproject/constants"
interface StakingRewards {
[stakingProvider: string]: string
}
export const useFetchStakingRewards = () => {
const merkleDropContract = useMerkleDropContract()
const stakingProviders = useSelector(selectStakingProviders)
const { hasFetched, isFetching } = useSelector(
(state: RootState) => state.rewards.interim
)
const dispatch = useDispatch()
useEffect(() => {
const fetch = async () => {
if (
!merkleDropContract ||
stakingProviders.length === 0 ||
(hasFetched && !isFetching)
) {
return
}
const claimedEvents = await getContractPastEvents(merkleDropContract, {
eventName: "Claimed",
fromBlock: DEPLOYMENT_BLOCK,
filterParams: [stakingProviders],
})
const claimedAmountToStakingProvider = claimedEvents.reduce(
(
reducer: { [stakingProvider: string]: string },
event
): { [stakingProvider: string]: string } => {
const stakingProvider = getAddress(
event.args?.stakingProvider as string
)
const prevAmount = BigNumber.from(reducer[stakingProvider] || Zero)
reducer[stakingProvider] = prevAmount
.add(event.args?.amount as string)
.toString()
return reducer
},
{}
)
const claimedRewardsInCurrentMerkleRoot = new Set(
claimedEvents
.filter((_) => _.args?.merkleRoot === rewardsData.merkleRoot)
.map((_) => getAddress(_.args?.stakingProvider as string))
)
const stakingRewards: StakingRewards = {}
for (const stakingProvider of stakingProviders) {
if (
!rewardsData.claims.hasOwnProperty(stakingProvider) ||
claimedRewardsInCurrentMerkleRoot.has(stakingProvider)
) {
// If the JSON file doesn't contain proofs for a given staking
// provider it means this staking provider has no rewards- we can skip
// this iteration. If the `Claimed` event exists with a current merkle
// root for a given staking provider it means that rewards have
// already been claimed- we can skip this iteration.
continue
}
const { amount } = (rewardsData as RewardsJSONData).claims[
stakingProvider
]
const claimableAmount = BigNumber.from(amount).sub(
claimedAmountToStakingProvider[stakingProvider] || Zero
)
if (claimableAmount.lte(Zero)) {
continue
}
stakingRewards[stakingProvider] = claimableAmount.toString()
}
dispatch(setInterimRewards(stakingRewards))
}
fetch()
}, [stakingProviders, merkleDropContract, hasFetched, isFetching, dispatch])
}