diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 0b9eaa7c9a..0f80ebb7bd 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -114,7 +114,7 @@ jobs: VITE_TAG: ${{ needs.prepare.outputs.image_tag }} CURRENT_BRANCH: ${{ needs.prepare.outputs.current_branch }} NODE_OPTIONS: '--max_old_space_size=4096' - run: yarn build-prod + run: yarn build - name: Docker build and push uses: docker/build-push-action@v2 diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx index 5bc03efde8..97c0986133 100644 --- a/src/components/Button/index.tsx +++ b/src/components/Button/index.tsx @@ -83,6 +83,11 @@ const disabledPrimary = css<{ export const ButtonPrimary = styled(Base)` background-color: ${({ theme }) => theme.primary}; color: ${({ theme }) => theme.textReverse}; + &:hover { + color: ${({ theme }) => theme.textReverse}; + filter: brightness(0.8); + } + &:active { box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.1, theme.primary)}; background-color: ${({ theme }) => darken(0.1, theme.primary)}; diff --git a/src/components/ClassicElasticTab.tsx b/src/components/ClassicElasticTab.tsx index e6202f2a5e..e8285f4efc 100644 --- a/src/components/ClassicElasticTab.tsx +++ b/src/components/ClassicElasticTab.tsx @@ -45,10 +45,18 @@ function ClassicElasticTab() { const upToMedium = useMedia(`(max-width: ${MEDIA_WIDTHS.upToMedium}px)`) - const showLegacyExplicit = upToMedium ? false : isFarmpage ? shouldShowFarmTab : shouldShowPositionTab - const dontShowLegacy = [ChainId.ZKEVM, ChainId.BASE, ChainId.LINEA].includes(chainId) + const showLegacyExplicit = + upToMedium || dontShowLegacy ? false : isFarmpage ? shouldShowFarmTab : shouldShowPositionTab + + useEffect(() => { + if (dontShowLegacy && tab === VERSION.ELASTIC_LEGACY) { + const newQs = { ...qs, tab: VERSION.ELASTIC } + navigate({ search: stringify(newQs) }, { replace: true }) + } + }, [tab, dontShowLegacy, navigate, qs]) + const legacyTag = (small?: boolean) => ( | undefined feeValue1: CurrencyAmount | undefined }) { - const { account } = useActiveWeb3React() + const { account, networkInfo } = useActiveWeb3React() const { library } = useWeb3React() const theme = useTheme() const token0Shown = feeValue0?.currency || position.pool.token0 @@ -108,12 +110,18 @@ export default function ProAmmFee({ const { userInfo } = useElasticFarmsV2() const info = userInfo?.find(item => item.nftId.toString() === tokenId.toString()) const address = info?.farmAddress + + const isFarmV21 = (networkInfo as EVMNetworkInfo).elastic['farmV2.1S'] + ?.map(item => item.toLowerCase()) + .includes(address?.toLowerCase()) + const farmV2Contract = useContract(address, FarmV2ABI) + const farmV21Contract = useContract(address, FarmV21ABI) const collectFeeFromFarmContract = async () => { const isInFarmV2 = !!info - const contract = isInFarmV2 ? farmV2Contract : farmContract + const contract = isInFarmV2 ? (isFarmV21 ? farmV21Contract : farmV2Contract) : farmContract if (!contract || !feeValue0 || !feeValue1) { setAttemptingTxn(false) @@ -125,14 +133,28 @@ export default function ProAmmFee({ const amount1Min = feeValue1.subtract(feeValue1.multiply(basisPointsToPercent(allowedSlippage))) try { const params = isInFarmV2 - ? [ - info.fId, - [tokenId.toString()], - amount0Min.quotient.toString(), - amount1Min.quotient.toString(), - deadline?.toString(), - true, - ] + ? isFarmV21 + ? [ + info.fId, + [tokenId.toString()], + amount0Min.quotient.toString(), + amount1Min.quotient.toString(), + deadline?.toString(), + buildFlagsForFarmV21({ + isClaimFee: !!feeValue0?.greaterThan('0') && !!feeValue1?.greaterThan('0'), + isSyncFee: !!feeValue0?.greaterThan('0') && !!feeValue1?.greaterThan('0'), + isClaimReward: false, + isReceiveNative: true, + }), + ] + : [ + info.fId, + [tokenId.toString()], + amount0Min.quotient.toString(), + amount1Min.quotient.toString(), + deadline?.toString(), + true, + ] : [ [tokenId.toString()], amount0Min.quotient.toString(), diff --git a/src/constants/abis/v2/farmv2.1.json b/src/constants/abis/v2/farmv2.1.json new file mode 100644 index 0000000000..3cff91c838 --- /dev/null +++ b/src/constants/abis/v2/farmv2.1.json @@ -0,0 +1,1474 @@ +[ + { + "inputs": [ + { + "internalType": "contract IERC721", + "name": "_nft", + "type": "address" + }, + { + "internalType": "contract IKSElasticLMHelper", + "name": "_helper", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EmergencyEnabled", + "type": "error" + }, + { + "inputs": [], + "name": "Expired", + "type": "error" + }, + { + "inputs": [], + "name": "FailToAdd", + "type": "error" + }, + { + "inputs": [], + "name": "FailToRemove", + "type": "error" + }, + { + "inputs": [], + "name": "FarmNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "Forbidden", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFarm", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInput", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRange", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReward", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTime", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidityNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "NotOwner", + "type": "error" + }, + { + "inputs": [], + "name": "PhaseSettled", + "type": "error" + }, + { + "inputs": [], + "name": "PositionNotEligible", + "type": "error" + }, + { + "inputs": [], + "name": "RangeNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "RangeNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "StakeNotFound", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rangeId", + "type": "uint256" + } + ], + "name": "ActivateRange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "poolAddress", + "type": "address" + }, + { + "components": [ + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint32", + "name": "weight", + "type": "uint32" + } + ], + "indexed": false, + "internalType": "struct IKSElasticLMV2.RangeInput[]", + "name": "ranges", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "startTime", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "endTime", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardAmount", + "type": "uint256" + } + ], + "internalType": "struct IKSElasticLMV2.RewardInput[]", + "name": "rewards", + "type": "tuple[]" + } + ], + "indexed": false, + "internalType": "struct IKSElasticLMV2.PhaseInput", + "name": "phase", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "address", + "name": "farmingToken", + "type": "address" + } + ], + "name": "AddFarm", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "startTime", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "endTime", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardAmount", + "type": "uint256" + } + ], + "internalType": "struct IKSElasticLMV2.RewardInput[]", + "name": "rewards", + "type": "tuple[]" + } + ], + "indexed": false, + "internalType": "struct IKSElasticLMV2.PhaseInput", + "name": "phase", + "type": "tuple" + } + ], + "name": "AddPhase", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint32", + "name": "weight", + "type": "uint32" + } + ], + "indexed": false, + "internalType": "struct IKSElasticLMV2.RangeInput", + "name": "range", + "type": "tuple" + } + ], + "name": "AddRange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nftId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ClaimReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "nftIds", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ClaimReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rangeId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "nftIds", + "type": "uint256[]" + }, + { + "indexed": true, + "internalType": "address", + "name": "depositer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "rewardAmounts", + "type": "uint256[]" + } + ], + "name": "ExpandEndTimeAndRewards", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fId", + "type": "uint256" + } + ], + "name": "ForceClosePhase", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rangeId", + "type": "uint256" + } + ], + "name": "RemoveRange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "enableOrDisable", + "type": "bool" + } + ], + "name": "UpdateEmergency", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "grantOrRevoke", + "type": "bool" + } + ], + "name": "UpdateGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IKSElasticLMHelper", + "name": "helper", + "type": "address" + } + ], + "name": "UpdateHelper", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nftId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "name": "UpdateLiquidity", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "grantOrRevoke", + "type": "bool" + } + ], + "name": "UpdateOperator", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "farmingTokenCode", + "type": "bytes" + } + ], + "name": "UpdateTokenCode", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256[]", + "name": "nftIds", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "nftId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "WithdrawEmergency", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "WithdrawUnusedRewards", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rangeId", + "type": "uint256" + } + ], + "name": "activateRange", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "poolAddress", + "type": "address" + }, + { + "components": [ + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint32", + "name": "weight", + "type": "uint32" + } + ], + "internalType": "struct IKSElasticLMV2.RangeInput[]", + "name": "ranges", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "startTime", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "endTime", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardAmount", + "type": "uint256" + } + ], + "internalType": "struct IKSElasticLMV2.RewardInput[]", + "name": "rewards", + "type": "tuple[]" + } + ], + "internalType": "struct IKSElasticLMV2.PhaseInput", + "name": "phase", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "isUsingToken", + "type": "bool" + } + ], + "name": "addFarm", + "outputs": [ + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rangeId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "nftIds", + "type": "uint256[]" + } + ], + "name": "addLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "startTime", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "endTime", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardAmount", + "type": "uint256" + } + ], + "internalType": "struct IKSElasticLMV2.RewardInput[]", + "name": "rewards", + "type": "tuple[]" + } + ], + "internalType": "struct IKSElasticLMV2.PhaseInput", + "name": "phaseInput", + "type": "tuple" + } + ], + "name": "addPhase", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint32", + "name": "weight", + "type": "uint32" + } + ], + "internalType": "struct IKSElasticLMV2.RangeInput", + "name": "range", + "type": "tuple" + } + ], + "name": "addRange", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "nftIds", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "flags", + "type": "uint8" + } + ], + "name": "claimFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "nftIds", + "type": "uint256[]" + } + ], + "name": "claimReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rangeId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "nftIds", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disableLogic", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "emergencyEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "enableLogic", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "farmCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + } + ], + "name": "forceClosePhase", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getDepositedNFTs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "listNFTs", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + } + ], + "name": "getFarm", + "outputs": [ + { + "internalType": "address", + "name": "poolAddress", + "type": "address" + }, + { + "components": [ + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint32", + "name": "weight", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "isRemoved", + "type": "bool" + } + ], + "internalType": "struct IKSElasticLMV2.RangeInfo[]", + "name": "ranges", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "startTime", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "endTime", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "isSettled", + "type": "bool" + }, + { + "components": [ + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardAmount", + "type": "uint256" + } + ], + "internalType": "struct IKSElasticLMV2.RewardInput[]", + "name": "rewards", + "type": "tuple[]" + } + ], + "internalType": "struct IKSElasticLMV2.PhaseInfo", + "name": "phase", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "address", + "name": "farmingToken", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "sumRewardPerLiquidity", + "type": "uint256[]" + }, + { + "internalType": "uint32", + "name": "lastTouchedTime", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNft", + "outputs": [ + { + "internalType": "contract IERC721", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "nftId", + "type": "uint256" + } + ], + "name": "getStake", + "outputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rangeId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "lastSumRewardPerLiquidity", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "rewardUnclaimed", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "guardians", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "operators", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "nftId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "liquidity", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "flags", + "type": "uint8" + } + ], + "name": "removeLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rangeId", + "type": "uint256" + } + ], + "name": "removeRange", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "enableOrDisable", + "type": "bool" + } + ], + "name": "updateEmergency", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "grantOrRevoke", + "type": "bool" + } + ], + "name": "updateGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IKSElasticLMHelper", + "name": "_helper", + "type": "address" + } + ], + "name": "updateHelper", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "grantOrRevoke", + "type": "bool" + } + ], + "name": "updateOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_farmingTokenCreationCode", + "type": "bytes" + } + ], + "name": "updateTokenCode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "nftIds", + "type": "uint256[]" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "nftIds", + "type": "uint256[]" + } + ], + "name": "withdrawEmergency", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "withdrawUnusedRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/src/constants/networks/matic.ts b/src/constants/networks/matic.ts index d402f948b4..ef10056686 100644 --- a/src/constants/networks/matic.ts +++ b/src/constants/networks/matic.ts @@ -69,6 +69,7 @@ const maticInfo: EVMNetworkInfo = { '0x3D6AfE2fB73fFEd2E3dD00c501A174554e147a43', '0xf2BcDf38baA52F6b0C1Db5B025DfFf01Ae1d6dBd', ], + 'farmV2.1S': [], }, limitOrder: '*', averageBlockTimeInSeconds: 2.6, diff --git a/src/constants/networks/type.ts b/src/constants/networks/type.ts index 7862039b90..c84e98cbb9 100644 --- a/src/constants/networks/type.ts +++ b/src/constants/networks/type.ts @@ -79,6 +79,7 @@ export interface EVMNetworkInfo extends NetworkInfo { readonly farms: string[] readonly farmv2Quoter?: string readonly farmV2S?: string[] + readonly 'farmV2.1S'?: string[] } readonly limitOrder: null | '*' | EnvKeys[] readonly averageBlockTimeInSeconds: number diff --git a/src/hooks/useElasticLegacy.ts b/src/hooks/useElasticLegacy.ts index 204b1e02e4..fce58b71b2 100644 --- a/src/hooks/useElasticLegacy.ts +++ b/src/hooks/useElasticLegacy.ts @@ -362,8 +362,8 @@ export const useRemoveLiquidityLegacy = ( const { library } = useWeb3React() const { token0, token1, position, usd } = parsePosition(item, chainId, tokenPrices) - const feeValue0 = CurrencyAmount.fromRawAmount(unwrappedToken(token0), feeRewards[item.id][0]) - const feeValue1 = CurrencyAmount.fromRawAmount(unwrappedToken(token1), feeRewards[item.id][1]) + const feeValue0 = CurrencyAmount.fromRawAmount(unwrappedToken(token0), feeRewards[item.id]?.[0] || '0') + const feeValue1 = CurrencyAmount.fromRawAmount(unwrappedToken(token1), feeRewards[item.id]?.[1] || '0') const [allowedSlippage] = useUserSlippageTolerance() const deadline = useTransactionDeadline() diff --git a/src/pages/ElasticLegacy/FarmLegacy.tsx b/src/pages/ElasticLegacy/FarmLegacy.tsx index f62a27ea64..5717e1d3d5 100644 --- a/src/pages/ElasticLegacy/FarmLegacy.tsx +++ b/src/pages/ElasticLegacy/FarmLegacy.tsx @@ -155,7 +155,7 @@ export default function FarmLegacy({ } } - const farmContract = useProMMFarmContract(config[chainId].farmContract || '') + const farmContract = useProMMFarmContract(config[chainId]?.farmContract || '') const handleWithdraw = async () => { setShowConfirmModal('withdraw') diff --git a/src/pages/Farm/ElasticFarmv2/index.tsx b/src/pages/Farm/ElasticFarmv2/index.tsx index 6e0739e432..dfc35cb09f 100644 --- a/src/pages/Farm/ElasticFarmv2/index.tsx +++ b/src/pages/Farm/ElasticFarmv2/index.tsx @@ -84,6 +84,7 @@ export default function ElasticFarmv2({ const rewardTokenAmounts: { [address: string]: CurrencyAmount } = {} userInfo?.forEach(item => { + if (item.farmAddress !== farmAddress) return item.unclaimedRewards.forEach(rw => { const address = rw.currency.isNative ? rw.currency.symbol || 'eth' : rw.currency.wrapped.address if (!rewardTokenAmounts[address]) rewardTokenAmounts[address] = rw @@ -93,6 +94,7 @@ export default function ElasticFarmv2({ const depositedTokenAmounts: { [address: string]: CurrencyAmount } = {} userInfo?.forEach(item => { + if (item.farmAddress !== farmAddress) return const address0 = item.position.amount0.currency.wrapped.address const address1 = item.position.amount1.currency.wrapped.address if (!depositedTokenAmounts[address0]) depositedTokenAmounts[address0] = item.position.amount0 @@ -240,6 +242,7 @@ export default function ElasticFarmv2({ whiteSpace: 'nowrap', height: '38px', padding: '0 12px', + maxWidth: '140px', }} onClick={handleApprove} disabled diff --git a/src/pages/MyEarnings/ElasticPools/SinglePosition/CollectFeesPanel.tsx b/src/pages/MyEarnings/ElasticPools/SinglePosition/CollectFeesPanel.tsx index e5e07b8e62..73a84a6bb2 100644 --- a/src/pages/MyEarnings/ElasticPools/SinglePosition/CollectFeesPanel.tsx +++ b/src/pages/MyEarnings/ElasticPools/SinglePosition/CollectFeesPanel.tsx @@ -13,7 +13,10 @@ import { ButtonOutlined } from 'components/Button' import CurrencyLogo from 'components/CurrencyLogo' import { MouseoverTooltip } from 'components/Tooltip' import PROMM_FARM_ABI from 'constants/abis/v2/farm.json' +import FarmV21ABI from 'constants/abis/v2/farmv2.1.json' import FarmV2ABI from 'constants/abis/v2/farmv2.json' +import { NETWORKS_INFO } from 'constants/networks' +import { EVMNetworkInfo } from 'constants/networks/type' import { useActiveWeb3React, useWeb3React } from 'hooks' import { useProAmmNFTPositionManagerContract } from 'hooks/useContract' import { config } from 'hooks/useElasticLegacy' @@ -27,7 +30,7 @@ import { useTransactionAdder } from 'state/transactions/hooks' import { TRANSACTION_TYPE } from 'state/transactions/type' import { updateChainId } from 'state/user/actions' import { useUserSlippageTolerance } from 'state/user/hooks' -import { basisPointsToPercent, calculateGasMargin } from 'utils' +import { basisPointsToPercent, buildFlagsForFarmV21, calculateGasMargin } from 'utils' import { formatDisplayNumber } from 'utils/numbers' type Props = { @@ -46,6 +49,7 @@ type Props = { const FarmInterface = new Interface(PROMM_FARM_ABI) const FarmV2Interface = new Interface(FarmV2ABI) +const FarmV21Interface = new Interface(FarmV21ABI) const CollectFeesPanel: React.FC = ({ nftId, @@ -141,13 +145,31 @@ const CollectFeesPanel: React.FC = ({ return } + const isFarmV21 = (NETWORKS_INFO[chainId] as EVMNetworkInfo)?.elastic['farmV2.1S'] + ?.map(item => item.toLowerCase()) + .includes(farmAddress.toLowerCase()) + const amount0Min = feeValue0.subtract(feeValue0.multiply(basisPointsToPercent(allowedSlippage))) const amount1Min = feeValue1.subtract(feeValue1.multiply(basisPointsToPercent(allowedSlippage))) try { - const encoded = (fId ? FarmV2Interface : FarmInterface).encodeFunctionData( + const encoded = (fId ? (isFarmV21 ? FarmV21Interface : FarmV2Interface) : FarmInterface).encodeFunctionData( 'claimFee', fId - ? [fId, [nftId], amount0Min.quotient.toString(), amount1Min.quotient.toString(), deadline?.toString(), true] + ? isFarmV21 + ? [ + fId, + [nftId], + amount0Min.quotient.toString(), + amount1Min.quotient.toString(), + deadline?.toString(), + buildFlagsForFarmV21({ + isClaimFee: !!feeValue0?.greaterThan('0') && !!feeValue1?.greaterThan('0'), + isSyncFee: !!feeValue0?.greaterThan('0') && !!feeValue1?.greaterThan('0'), + isClaimReward: false, + isReceiveNative: true, + }), + ] + : [fId, [nftId], amount0Min.quotient.toString(), amount1Min.quotient.toString(), deadline?.toString(), true] : [ [nftId], amount0Min.quotient.toString(), diff --git a/src/pages/MyEarnings/ElasticPools/SinglePosition/PositionView.tsx b/src/pages/MyEarnings/ElasticPools/SinglePosition/PositionView.tsx index 77daf9abe8..efacd484e4 100644 --- a/src/pages/MyEarnings/ElasticPools/SinglePosition/PositionView.tsx +++ b/src/pages/MyEarnings/ElasticPools/SinglePosition/PositionView.tsx @@ -129,7 +129,7 @@ const PositionView: React.FC = props => { }) || [] const farmV2Rewards = - positionEarning.farmV2DepositedPositions?.[0].pendingRewards.map((amount, index) => { + positionEarning.farmV2DepositedPositions?.[0].pendingRewards?.map((amount, index) => { const tokenId = positionEarning.farmV2DepositedPositions?.[0].farmV2.rewards[index].tokenID || '' const token = tokens[tokenId] || new Token(chainId, tokenId, 18, '', '') @@ -275,7 +275,7 @@ const PositionView: React.FC = props => { } /> ) : ( - -- + $0 )} @@ -315,10 +315,12 @@ const PositionView: React.FC = props => { {+positionEarning.pendingRewardUSD ? formatDisplayNumber(positionEarning.pendingRewardUSD, { style: 'currency', significantDigits: 6 }) + : farmRewards?.length + ? '$0' : '--'} } - disabled={!+positionEarning.pendingRewardUSD} + disabled={disabledHarvest} text={ <> {farmRewards?.map((rw, index) => ( diff --git a/src/pages/RemoveLiquidityProAmm/index.tsx b/src/pages/RemoveLiquidityProAmm/index.tsx index fc679f9d45..7b257fd902 100644 --- a/src/pages/RemoveLiquidityProAmm/index.tsx +++ b/src/pages/RemoveLiquidityProAmm/index.tsx @@ -29,13 +29,13 @@ import ProAmmPooledTokens from 'components/ProAmm/ProAmmPooledTokens' import { RowBetween } from 'components/Row' import Slider from 'components/Slider' import { SLIPPAGE_EXPLANATION_URL } from 'components/SlippageWarningNote' -import Toggle from 'components/Toggle' import { MouseoverTooltip, TextDashed } from 'components/Tooltip' import TransactionConfirmationModal, { ConfirmationModalContent, TransactionErrorContent, } from 'components/TransactionConfirmationModal' import { TutorialType } from 'components/Tutorial' +import FarmV21ABI from 'constants/abis/v2/farmv2.1.json' import FarmV2ABI from 'constants/abis/v2/farmv2.json' import { didUserReject } from 'constants/connectors/utils' import { EVMNetworkInfo } from 'constants/networks/type' @@ -55,7 +55,7 @@ import { useTransactionAdder } from 'state/transactions/hooks' import { TRANSACTION_TYPE } from 'state/transactions/type' import { useUserSlippageTolerance } from 'state/user/hooks' import { ExternalLink, MEDIA_WIDTHS, TYPE } from 'theme' -import { basisPointsToPercent, calculateGasMargin, formattedNum, isAddressString } from 'utils' +import { basisPointsToPercent, buildFlagsForFarmV21, calculateGasMargin, formattedNum, isAddressString } from 'utils' import { formatDollarAmount } from 'utils/numbers' import { ErrorName } from 'utils/sentry' import { SLIPPAGE_STATUS, checkRangeSlippage, checkWarningSlippage, formatSlippage } from 'utils/slippage' @@ -148,7 +148,6 @@ export default function RemoveLiquidityProAmm() { function Remove({ tokenId }: { tokenId: BigNumber }) { const { position } = useProAmmPositionsFromTokenId(tokenId) - const [claimFee, setIsClaimFee] = useState(true) const positionManager = useProAmmNFTPositionManagerContract() const theme = useTheme() const { networkInfo, account, chainId, isEVM } = useActiveWeb3React() @@ -160,9 +159,14 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { const isFarmV2 = (networkInfo as EVMNetworkInfo).elastic.farmV2S ?.map(item => item.toLowerCase()) .includes(owner?.toLowerCase()) + const isFarmV21 = (networkInfo as EVMNetworkInfo).elastic['farmV2.1S'] + ?.map(item => item.toLowerCase()) + .includes(owner?.toLowerCase()) const ownByFarm = isEVM - ? (networkInfo as EVMNetworkInfo).elastic.farms.flat().includes(isAddressString(chainId, owner)) || isFarmV2 + ? (networkInfo as EVMNetworkInfo).elastic.farms.flat().includes(isAddressString(chainId, owner)) || + isFarmV2 || + isFarmV21 : false const ownsNFT = owner === account || ownByFarm @@ -265,6 +269,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { const farmV2Address = isFarmV2 ? owner : undefined const farmV2Contract = useContract(farmV2Address, FarmV2ABI) + const farmV21Contract = useContract(isFarmV21 ? owner : undefined, FarmV21ABI) const handleBroadcastRemoveSuccess = (response: TransactionResponse) => { setAttemptingTxn(false) @@ -290,7 +295,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { } const burnFromFarm = async () => { - const contract = isFarmV2 ? farmV2Contract : farmV1Contract + const contract = isFarmV21 ? farmV21Contract : isFarmV2 ? farmV2Contract : farmV1Contract if (!contract || !liquidityValue0 || !liquidityValue1 || !deadline || !positionSDK || !liquidityPercentage) { return @@ -300,14 +305,28 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { const amount0Min = liquidityValue0?.subtract(liquidityValue0.multiply(basisPointsToPercent(allowedSlippage))) const amount1Min = liquidityValue1?.subtract(liquidityValue1.multiply(basisPointsToPercent(allowedSlippage))) - const params = isFarmV2 + const params = isFarmV21 ? [ tokenId.toString(), liquidityPercentage.multiply(positionSDK.liquidity).quotient.toString(), amount0Min.quotient.toString(), amount1Min.quotient.toString(), deadline.toString(), - claimFee && feeValue0?.greaterThan('0'), + buildFlagsForFarmV21({ + isClaimFee: !!feeValue0?.greaterThan('0') && !!feeValue1?.greaterThan('0'), + isSyncFee: !!feeValue0?.greaterThan('0') && !!feeValue1?.greaterThan('0'), + isClaimReward: true, + isReceiveNative: !receiveWETH, + }), + ] + : isFarmV2 + ? [ + tokenId.toString(), + liquidityPercentage.multiply(positionSDK.liquidity).quotient.toString(), + amount0Min.quotient.toString(), + amount1Min.quotient.toString(), + deadline.toString(), + feeValue0?.greaterThan('0'), !receiveWETH, ] : [ @@ -317,7 +336,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { amount1Min.quotient.toString(), deadline.toString(), !receiveWETH, - [claimFee && feeValue0?.greaterThan('0'), true], + [feeValue0?.greaterThan('0'), true], ] const gasEstimation = await contract.estimateGas.removeLiquidity(...params) @@ -381,16 +400,12 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { slippageTolerance: basisPointsToPercent(allowedSlippage), deadline: deadline.toString(), collectOptions: { - expectedCurrencyOwed0: claimFee - ? feeValue0.subtract(feeValue0.multiply(basisPointsToPercent(allowedSlippage))) - : CurrencyAmount.fromRawAmount(feeValue0.currency, 0), - expectedCurrencyOwed1: claimFee - ? feeValue1.subtract(feeValue1.multiply(basisPointsToPercent(allowedSlippage))) - : CurrencyAmount.fromRawAmount(feeValue1.currency, 0), + expectedCurrencyOwed0: feeValue0.subtract(feeValue0.multiply(basisPointsToPercent(allowedSlippage))), + expectedCurrencyOwed1: feeValue1.subtract(feeValue1.multiply(basisPointsToPercent(allowedSlippage))), recipient: account, deadline: deadline.toString(), isRemovingLiquid: true, - havingFee: claimFee && !(feeValue0.equalTo(JSBI.BigInt('0')) && feeValue1.equalTo(JSBI.BigInt('0'))), + havingFee: !(feeValue0.equalTo(JSBI.BigInt('0')) && feeValue1.equalTo(JSBI.BigInt('0'))), }, }) const txn = { @@ -448,8 +463,8 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { Removing {liquidityValue0?.toSignificant(6)} {liquidityValue0?.currency?.symbol} and{' '} {liquidityValue1?.toSignificant(6)} {liquidityValue1?.currency?.symbol} - {claimFee && (feeValue0?.greaterThan(ZERO) || feeValue1?.greaterThan(ZERO)) ?
: ''} - {claimFee && (feeValue0?.greaterThan(ZERO) || feeValue1?.greaterThan(ZERO)) + {feeValue0?.greaterThan(ZERO) || feeValue1?.greaterThan(ZERO) ?
: ''} + {feeValue0?.greaterThan(ZERO) || feeValue1?.greaterThan(ZERO) ? `Collecting fee of ${feeValue0?.toSignificant(6)} ${ feeValue0?.currency?.symbol } and ${feeValue1?.toSignificant(6)} ${feeValue1?.currency?.symbol}` @@ -504,15 +519,13 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { title={t`Remove Amount`} /> {positionSDK ? ( - claimFee ? ( - - ) : null + ) : ( )} @@ -762,18 +775,6 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { /> - - - - Claim Your Fees Earned - - { - setIsClaimFee(prev => !prev) - }} - /> - {slippageStatus === SLIPPAGE_STATUS.HIGH && ( diff --git a/src/state/farms/elasticv2/updater.tsx b/src/state/farms/elasticv2/updater.tsx index 60b073ebe7..f1ddbb20c6 100644 --- a/src/state/farms/elasticv2/updater.tsx +++ b/src/state/farms/elasticv2/updater.tsx @@ -296,7 +296,7 @@ export default function ElasticFarmV2Updater({ interval = true }: { interval?: b const apr = farm.isSettled || +farm.endTime < Date.now() / 1000 || farm.liquidity === '0' ? 0 - : (100 * (totalFarmRewardUsd * +r.weight * 365)) / totalFarmingTime / denominator + : (100 * (totalFarmRewardUsd * +r.weight * 365)) / totalFarmingTime / denominator || 0 return { ...r, diff --git a/src/utils/index.ts b/src/utils/index.ts index 81a45127d0..b49c364c34 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -506,3 +506,22 @@ export const downloadImage = (data: Blob | string | undefined, filename: string) link.click() document.body.removeChild(link) } + +export function buildFlagsForFarmV21({ + isClaimFee, + isSyncFee, + isClaimReward, + isReceiveNative, +}: { + isClaimFee: boolean + isSyncFee: boolean + isClaimReward: boolean + isReceiveNative: boolean +}) { + let flags = 1 + if (isReceiveNative) flags = 1 + if (isClaimFee) flags = flags | (1 << 3) + if (isSyncFee) flags = flags | (1 << 2) + if (isClaimReward) flags = flags | (1 << 1) + return flags +}