diff --git a/package.json b/package.json index 3d87f0b88..d8e4f1ece 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,10 @@ "@ethersproject/constants": "^5.5.0", "@fontsource/ibm-plex-mono": "^4.5.13", "@fontsource/inter": "^4.5.10", - "@keep-network/keep-core": "development", - "@keep-network/keep-ecdsa": "development", - "@keep-network/random-beacon": "development", - "@keep-network/tbtc": "development", + "@keep-network/keep-core": "^1.8.1-sepolia.0", + "@keep-network/keep-ecdsa": "^1.9.0-sepolia.0", + "@keep-network/random-beacon": "^2.1.0-sepolia.1", + "@keep-network/tbtc": "^1.1.2-sepolia.0", "@keep-network/tbtc-v2.ts": "^2.4.1", "@ledgerhq/connect-kit-loader": "1.1.8", "@ledgerhq/wallet-api-client": "^1.2.0", @@ -31,7 +31,7 @@ "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", "@threshold-network/components": "development", - "@threshold-network/solidity-contracts": "development", + "@threshold-network/solidity-contracts": "^1.3.0-sepolia.0", "@types/jest": "^27.0.1", "@types/node": "^16.9.1", "@types/numeral": "^2.0.2", diff --git a/src/hooks/useFetchStakingRewards.ts b/src/hooks/useFetchStakingRewards.ts index a54259031..45baed2b3 100644 --- a/src/hooks/useFetchStakingRewards.ts +++ b/src/hooks/useFetchStakingRewards.ts @@ -12,6 +12,8 @@ import { setInterimRewards } from "../store/rewards" import { selectStakingProviders } from "../store/staking" import { BigNumber } from "ethers" import { Zero } from "@ethersproject/constants" +import { useMulticall } from "../web3/hooks/useMulticall" +import { ContractCall } from "../threshold-ts/multicall" interface StakingRewards { [stakingProvider: string]: string @@ -25,6 +27,16 @@ export const useFetchStakingRewards = () => { ) const dispatch = useDispatch() + const cumulativeClaimedCalls: ContractCall[] = stakingProviders.map( + (stakingProvider) => ({ + address: merkleDropContract!.address, + interface: merkleDropContract!.interface!, + method: "cumulativeClaimed", + args: [stakingProvider], + }) + ) + const fetchCumulativeClaims = useMulticall(cumulativeClaimedCalls) + useEffect(() => { const fetch = async () => { if ( @@ -35,52 +47,56 @@ export const useFetchStakingRewards = () => { return } - const claimedEvents = await getContractPastEvents(merkleDropContract, { - eventName: "Claimed", - fromBlock: DEPLOYMENT_BLOCK, - filterParams: [stakingProviders], - }) + // TODO: + // - Integration of new Merkle contract + TACo automated rewards here. + // TLDR: stakingRewards = merkle_rewards + taco_rewards + // See https://github.com/threshold-network/token-dashboard/issues/756 + // - There's a more efficient way to check Merkle's claimed rewards. + // See https://github.com/threshold-network/token-dashboard/issues/765 + // - Note also that TACo rewards now accrue on each block. They can be + // calculated via TACoApp.availableRewards(address _stakingProvider) - 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 cumulativeClaimedResults = await fetchCumulativeClaims() + console.log(cumulativeClaimedResults) + + const claimedAmountToStakingProvider = stakingProviders.reduce( + (acc, stakingProvider, index) => { + acc[getAddress(stakingProvider)] = + cumulativeClaimedResults[index].toString() + return acc }, - {} + {} as { [stakingProvider: string]: string } ) + console.log(claimedAmountToStakingProvider) - const claimedRewardsInCurrentMerkleRoot = new Set( - claimedEvents - .filter((_) => _.args?.merkleRoot === rewardsData.merkleRoot) - .map((_) => getAddress(_.args?.stakingProvider as string)) - ) + // 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 (!(stakingProvider in (rewardsData as RewardsJSONData).claims)) { // 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. + // provider it means this staking provider has no Merkle rewards continue } - const { amount } = (rewardsData as RewardsJSONData).claims[ stakingProvider ] + const claimedAmount = + claimedAmountToStakingProvider[stakingProvider] || "0" + if (BigNumber.from(amount).eq(BigNumber.from(claimedAmount))) { + // if the claimed amount is equal to the amount of rewards available, then skip + continue + } + // TODO: ^ But there's going to be TACo rewards + + // 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. + // TODO: ^ Same, there can be TACo rewards const claimableAmount = BigNumber.from(amount).sub( claimedAmountToStakingProvider[stakingProvider] || Zero ) @@ -96,5 +112,12 @@ export const useFetchStakingRewards = () => { } fetch() - }, [stakingProviders, merkleDropContract, hasFetched, isFetching, dispatch]) + }, [ + stakingProviders, + merkleDropContract, + hasFetched, + isFetching, + dispatch, + fetchCumulativeClaims, + ]) } diff --git a/src/web3/hooks/useClaimMerkleRewardsTransaction.ts b/src/web3/hooks/useClaimMerkleRewardsTransaction.ts index 371b25b71..29578e2d0 100644 --- a/src/web3/hooks/useClaimMerkleRewardsTransaction.ts +++ b/src/web3/hooks/useClaimMerkleRewardsTransaction.ts @@ -34,6 +34,11 @@ export const useClaimMerkleRewardsTransaction = ( ]) } + // TODO: + // - This only signals no Merkle rewards, but there may be TACo rewards + // - We can still call the new Merkle contract with a claim with an empty + // merkle proof, signalling to not try to claim Merkle rewards. This + // will still try to claim TACo rewards automatically. if (availableRewardsToClaim.length === 0) { throw new Error("No rewards to claim.") } diff --git a/src/web3/hooks/useMerkleDropContract.ts b/src/web3/hooks/useMerkleDropContract.ts index abdf09f57..d6b733f04 100644 --- a/src/web3/hooks/useMerkleDropContract.ts +++ b/src/web3/hooks/useMerkleDropContract.ts @@ -6,13 +6,15 @@ import { AddressZero } from "../utils" export const DEPLOYMENT_BLOCK = supportedChainId === "1" ? 15146501 : 0 +// TODO: +// - Update new MerkleRewards contract address here const CONTRACT_ADDRESSESS = { // https://etherscan.io/address/0xea7ca290c7811d1cc2e79f8d706bd05d8280bd37 [ChainID.Ethereum.valueOf().toString()]: "0xeA7CA290c7811d1cC2e79f8d706bD05d8280BD37", - // https://sepolia.etherscan.io/address/0x4621a14bbB5a53f79Ea532bdc032b8ACc383B153 + // https://sepolia.etherscan.io/address/0xBF807283ef74616065A5595ACa49b25A569A33c6 [ChainID.Sepolia.valueOf().toString()]: - "0x4621a14bbB5a53f79Ea532bdc032b8ACc383B153", + "0xBF807283ef74616065A5595ACa49b25A569A33c6", // TODO: Set local address- how to resolve it in local network? [ChainID.Localhost.valueOf().toString()]: AddressZero, } as Record diff --git a/yarn.lock b/yarn.lock index fb9c7583d..de2660551 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3327,26 +3327,10 @@ "@openzeppelin/upgrades" "^2.7.2" openzeppelin-solidity "2.4.0" -"@keep-network/keep-core@1.8.0-dev.5": - version "1.8.0-dev.5" - resolved "https://registry.yarnpkg.com/@keep-network/keep-core/-/keep-core-1.8.0-dev.5.tgz#8b4d08ec437f29c94723ee54fcf76456ba5408c3" - integrity sha512-QVkpO5X28Vczj/xHezV0z2UuMw8QFaR3C8x/d6+3adedsL3nCxgveIGTUcXSuYpBqfx0v4/xT+9bIK7BwLkGPw== - dependencies: - "@openzeppelin/upgrades" "^2.7.2" - openzeppelin-solidity "2.4.0" - -"@keep-network/keep-core@1.8.1-goerli.0": - version "1.8.1-goerli.0" - resolved "https://registry.yarnpkg.com/@keep-network/keep-core/-/keep-core-1.8.1-goerli.0.tgz#238485aab51902021d42357bf59695225002f0ab" - integrity sha512-h3La/RqbyEZjBBPg8V+pcRFo3UpWZUF4CxWfXHZnUR4PnkZKnIDrTNFQPhpV2uYFZwrbJxTR9mzOq/DOAiXPwA== - dependencies: - "@openzeppelin/upgrades" "^2.7.2" - openzeppelin-solidity "2.4.0" - -"@keep-network/keep-core@>1.8.1-dev <1.8.1-goerli", "@keep-network/keep-core@development": - version "1.8.1-dev.0" - resolved "https://registry.yarnpkg.com/@keep-network/keep-core/-/keep-core-1.8.1-dev.0.tgz#d95864b25800214de43d8840376a68336cb12055" - integrity sha512-gFXkgN4PYOYCZ14AskL7fZHEFW5mu3BDd+TJKBuKZc1q9CgRMOK+dxpJnSctxmSH1tV+Ln9v9yqlSkfPCoiBHw== +"@keep-network/keep-core@1.8.1-sepolia.0", "@keep-network/keep-core@^1.8.1-sepolia.0": + version "1.8.1-sepolia.0" + resolved "https://registry.yarnpkg.com/@keep-network/keep-core/-/keep-core-1.8.1-sepolia.0.tgz#62fc477ea0f5c0a44f67eefbdc1219fbe261b4c3" + integrity sha512-dHdZQR/PWO7Cw8M/GawmsJ5mhaiBOTdd4cUb1DF9fEjUY/4AVrd2F7c39CkrqGCF598ve46hhQWoRLLgtiAv2A== dependencies: "@openzeppelin/upgrades" "^2.7.2" openzeppelin-solidity "2.4.0" @@ -3361,22 +3345,12 @@ "@openzeppelin/upgrades" "^2.7.2" openzeppelin-solidity "2.3.0" -"@keep-network/keep-ecdsa@>1.9.0-dev <1.9.0-ropsten": - version "1.9.0-goerli.0" - resolved "https://registry.yarnpkg.com/@keep-network/keep-ecdsa/-/keep-ecdsa-1.9.0-goerli.0.tgz#ce58b6639062bb4f73a257557aebb16447889e08" - integrity sha512-EA/oTcxmia5nznQ35ub9/5xBqBK4T+78oWYxASCc+THdPLalzriSAtQ517R4QnvkHi82NFhJjZH8WBoRXniddA== +"@keep-network/keep-ecdsa@1.9.0-sepolia.0", "@keep-network/keep-ecdsa@^1.9.0-sepolia.0": + version "1.9.0-sepolia.0" + resolved "https://registry.yarnpkg.com/@keep-network/keep-ecdsa/-/keep-ecdsa-1.9.0-sepolia.0.tgz#33d0fcf512193d2b701e92efcfa08de97064f779" + integrity sha512-+hWE8ZzafsElA6xTrVK/XbEpomhiPJDzKO085OJ5GJE6qzx/MGZ5J+EwD3KR+5/1+K+gtVwowF/Q39pgj+jNoQ== dependencies: - "@keep-network/keep-core" "1.8.1-goerli.0" - "@keep-network/sortition-pools" "1.2.0-dev.1" - "@openzeppelin/upgrades" "^2.7.2" - openzeppelin-solidity "2.3.0" - -"@keep-network/keep-ecdsa@development": - version "1.9.0-dev.1" - resolved "https://registry.yarnpkg.com/@keep-network/keep-ecdsa/-/keep-ecdsa-1.9.0-dev.1.tgz#7522b47dd639ddd7479a0e71dc328a9e0bba7cae" - integrity sha512-FRIDejTUiQO7c9gBXgjtTp2sXkEQKFBBqVjYoZE20OCGRxbgum9FbgD/B5RWIctBy4GGr5wJHnA1789iaK3X6A== - dependencies: - "@keep-network/keep-core" "1.8.0-dev.5" + "@keep-network/keep-core" "1.8.1-sepolia.0" "@keep-network/sortition-pools" "1.2.0-dev.1" "@openzeppelin/upgrades" "^2.7.2" openzeppelin-solidity "2.3.0" @@ -3399,15 +3373,15 @@ "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" "@threshold-network/solidity-contracts" "1.2.1" -"@keep-network/random-beacon@development": - version "2.1.0-dev.10" - resolved "https://registry.yarnpkg.com/@keep-network/random-beacon/-/random-beacon-2.1.0-dev.10.tgz#61c9d3e98257f40292264f4b9e1991acdc11f3c3" - integrity sha512-NJtmjrzFimL20bul6g8lKxUPNc+lpiu9BJ3uheJOCWDL5vQ+hJGctmWqd63mvtjgO8Ks9IQsDg9wpValzSzGXg== +"@keep-network/random-beacon@^2.1.0-sepolia.1": + version "2.1.0-sepolia.1" + resolved "https://registry.yarnpkg.com/@keep-network/random-beacon/-/random-beacon-2.1.0-sepolia.1.tgz#3debde13d5f365883d88b3c1d279cc7d21984d58" + integrity sha512-dj6j6/msv1BqMtPbVoLo4cMhbtf4jLhKjkXmJoBXU2KYWW9wBlRB06M4DZPfUhhW8L7/1eaFJJIINATt26wBjA== dependencies: - "@keep-network/sortition-pools" "^2.0.0-pre.16" - "@openzeppelin/contracts" "^4.6.0" + "@keep-network/sortition-pools" "github:keep-network/sortition-pools#test-fork" + "@openzeppelin/contracts" "4.7.3" "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" - "@threshold-network/solidity-contracts" "1.3.0-dev.5" + "@threshold-network/solidity-contracts" "1.3.0-sepolia.0" "@keep-network/sortition-pools@1.1.2": version "1.1.2" @@ -3423,7 +3397,7 @@ dependencies: "@openzeppelin/contracts" "^2.4.0" -"@keep-network/sortition-pools@2.0.0", "@keep-network/sortition-pools@^2.0.0-pre.16": +"@keep-network/sortition-pools@2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@keep-network/sortition-pools/-/sortition-pools-2.0.0.tgz#04e29ec756d74e00d13505a3e2a7763b06d7a08d" integrity sha512-82pDOKcDBvHBFblCt0ALVr6qC6mxk339ZqnCfYx1zIPaPhzkw1RKOv28AqPoqzhzcdqLIoPh8g9RS/M2Lplh1A== @@ -3431,6 +3405,13 @@ "@openzeppelin/contracts" "^4.3.2" "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" +"@keep-network/sortition-pools@github:keep-network/sortition-pools#test-fork": + version "2.1.0-pre" + resolved "https://codeload.github.com/keep-network/sortition-pools/tar.gz/a41007f4c818864cdca0b6a6446424c071157ced" + dependencies: + "@openzeppelin/contracts" "^4.3.2" + "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" + "@keep-network/tbtc-v2.ts@^2.4.1": version "2.4.1" resolved "https://registry.yarnpkg.com/@keep-network/tbtc-v2.ts/-/tbtc-v2.ts-2.4.1.tgz#177046b32859fe5ad429f52c081e3cac994d3700" @@ -3473,13 +3454,13 @@ "@summa-tx/relay-sol" "^2.0.2" openzeppelin-solidity "2.3.0" -"@keep-network/tbtc@development": - version "1.1.2-dev.1" - resolved "https://registry.yarnpkg.com/@keep-network/tbtc/-/tbtc-1.1.2-dev.1.tgz#dd1e734c0fed50474c74d7170c8749127231d1f9" - integrity sha512-IRa0j1D7JBG8UpduaFxkaq2Ii6F61HhNMUBmxr7kAIZwj/yx8sYXWi921mn0L2Z+hAYNcwEUVhCM91VKQH29pQ== +"@keep-network/tbtc@^1.1.2-sepolia.0": + version "1.1.2-sepolia.0" + resolved "https://registry.yarnpkg.com/@keep-network/tbtc/-/tbtc-1.1.2-sepolia.0.tgz#6ef5f511a5ce80133f892f564c81b45afb9eaec9" + integrity sha512-p5H728tyG/Frli3N0//u4JiqFxiuW4uzMrMmnJFO7azBJPhdwEALhHRsIX6BNkVH2/NRnmu3MQYksqNnUYM6Bg== dependencies: "@celo/contractkit" "^1.0.2" - "@keep-network/keep-ecdsa" ">1.9.0-dev <1.9.0-ropsten" + "@keep-network/keep-ecdsa" "1.9.0-sepolia.0" "@summa-tx/bitcoin-spv-sol" "^3.1.0" "@summa-tx/relay-sol" "^2.0.2" openzeppelin-solidity "2.3.0" @@ -3746,6 +3727,11 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz#90d9e47bacfd8693bfad0ac8a394645575528d05" integrity sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA== +"@openzeppelin/contracts@4.7.3": + version "4.7.3" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.3.tgz#939534757a81f8d69cc854c7692805684ff3111e" + integrity sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw== + "@openzeppelin/contracts@^2.4.0": version "2.5.1" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-2.5.1.tgz#c76e3fc57aa224da3718ec351812a4251289db31" @@ -4406,12 +4392,12 @@ "@openzeppelin/contracts-upgradeable" "~4.5.2" "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" -"@threshold-network/solidity-contracts@1.3.0-dev.5", "@threshold-network/solidity-contracts@development": - version "1.3.0-dev.5" - resolved "https://registry.yarnpkg.com/@threshold-network/solidity-contracts/-/solidity-contracts-1.3.0-dev.5.tgz#f7a2727d627a10218f0667bc0d33e19ed8f87fdc" - integrity sha512-AInTKQkJ0PKa32q2m8GnZFPYEArsnvOwhIFdBFaHdq9r4EGyqHMf4YY1WjffkheBZ7AQ0DNA8Lst30kBoQd0SA== +"@threshold-network/solidity-contracts@1.3.0-sepolia.0", "@threshold-network/solidity-contracts@^1.3.0-sepolia.0": + version "1.3.0-sepolia.0" + resolved "https://registry.yarnpkg.com/@threshold-network/solidity-contracts/-/solidity-contracts-1.3.0-sepolia.0.tgz#9a2401094ca267844e08d1a5be1214d32bd99f93" + integrity sha512-FmRsi+WZAG805kpPYRWAeMbEDRDH44Af+q8UuyVKpjJh5ObcNz9MPGESeYflE1o8MsNpY1mfxZBY6olXPR/LCw== dependencies: - "@keep-network/keep-core" ">1.8.1-dev <1.8.1-goerli" + "@keep-network/keep-core" "1.8.1-sepolia.0" "@openzeppelin/contracts" "~4.5.0" "@openzeppelin/contracts-upgradeable" "~4.5.2" "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf"