From 36f0468d9b41e01e64ae5ac3c227e55b7eaff4a1 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 22 Feb 2022 12:02:27 -0500 Subject: [PATCH 01/72] staking reducer, updater, actions --- src/constants/staking.ts | 7 ++++ src/state/staking/actions.ts | 6 +-- src/state/staking/hooks.ts | 1 + src/state/staking/reducer.ts | 64 +++++++++++++++--------------- src/state/staking/updater.ts | 77 +++++++++++++++++++++++------------- 5 files changed, 91 insertions(+), 64 deletions(-) create mode 100644 src/constants/staking.ts diff --git a/src/constants/staking.ts b/src/constants/staking.ts new file mode 100644 index 00000000000..3fd278a3bac --- /dev/null +++ b/src/constants/staking.ts @@ -0,0 +1,7 @@ +import { ChainId } from '@ubeswap/sdk' + +export const ExternalStakingRewards: { [K in ChainId]: string } = { + [ChainId.MAINNET]: '0x0812f6de916667C5aa820E757704c4ac69159529', + [ChainId.ALFAJORES]: '', + [ChainId.BAKLAVA]: '', +} diff --git a/src/state/staking/actions.ts b/src/state/staking/actions.ts index e535b75788d..167f14ce729 100644 --- a/src/state/staking/actions.ts +++ b/src/state/staking/actions.ts @@ -1,6 +1,6 @@ import { createAction } from '@reduxjs/toolkit' -import { StakingState } from './reducer' +import { IStakingState, IUserStakingState } from './reducer' -export const updateStaking = createAction<{ stakingInfo: StakingState }>('staking/update') -export const updateSNX = createAction<{ rewardRate: JSBI; leftToClaim: JSBI }>('staking/updateSNX') +export const updateStaking = createAction<{ stakingState: IStakingState }>('staking/update') +export const updateStakingUser = createAction<{ userStakingState: IUserStakingState }>('staking/updateUser') diff --git a/src/state/staking/hooks.ts b/src/state/staking/hooks.ts index 243c278e281..e7088634dff 100644 --- a/src/state/staking/hooks.ts +++ b/src/state/staking/hooks.ts @@ -47,6 +47,7 @@ export type SNXRewardInfo = { avgApr?: Percent userRewardRate?: TokenAmount } + export function calculateBoostedBalance( votingPower: JSBI, totalVotingPower: JSBI, diff --git a/src/state/staking/reducer.ts b/src/state/staking/reducer.ts index eaba067f089..e99f41a365c 100644 --- a/src/state/staking/reducer.ts +++ b/src/state/staking/reducer.ts @@ -1,55 +1,53 @@ import { createReducer } from '@reduxjs/toolkit' import { JSBI } from '@ubeswap/sdk' -import { updateSNX, updateStaking } from './actions' +import { updateStaking, updateStakingUser } from './actions' export type VoteLock = { amount: JSBI end: number // UNIX time stamp } -export type SnxRewardsInfo = { - address: string - rewardToken: string - tokenRate?: JSBI - leftToClaim?: JSBI -} - -export type StakingState = { - votingPower: JSBI - totalVotingPower: JSBI - snx?: SnxRewardsInfo - locked?: VoteLock - voteWeightLeft?: JSBI - voteUserPower: JSBI +export type IStakingState = { totalWeight: JSBI totalMobiLocked: JSBI + totalVotingPower: JSBI + externalRewardsRate: JSBI } -const SNX_STATIC: SnxRewardsInfo = { - address: '0x0812f6de916667C5aa820E757704c4ac69159529', - rewardToken: '0x471EcE3750Da237f93B8E339c536989b8978a438', +export type IUserStakingState = { + voteUserPower: JSBI + votingPower: JSBI + claimableExternalRewards: JSBI + lock: VoteLock | null } -const initialState: StakingState = { - votingPower: JSBI.BigInt(0), - totalVotingPower: JSBI.BigInt(0), - voteWeightLeft: JSBI.BigInt(0), - voteUserPower: JSBI.BigInt(0), +const initialStakingState: IStakingState = { totalWeight: JSBI.BigInt(0), totalMobiLocked: JSBI.BigInt(1), - snx: SNX_STATIC, + totalVotingPower: JSBI.BigInt(0), + externalRewardsRate: JSBI.BigInt(0), +} + +const initialUserStakingState: IUserStakingState = { + voteUserPower: JSBI.BigInt(0), + votingPower: JSBI.BigInt(0), + claimableExternalRewards: JSBI.BigInt(0), + lock: null, +} + +const initialState: IStakingState & IUserStakingState = { + ...initialStakingState, + ...initialUserStakingState, } -export default createReducer(initialState, (builder) => { - builder.addCase(updateStaking, (state, { payload: { stakingInfo } }) => ({ +export default createReducer(initialState, (builder) => { + builder.addCase(updateStaking, (state, { payload: { stakingState } }) => ({ + ...state, + ...stakingState, + })) + builder.addCase(updateStakingUser, (state, { payload: { userStakingState } }) => ({ ...state, - ...stakingInfo, + ...userStakingState, })) - builder.addCase(updateSNX, (state, { payload }) => { - if (state.snx) { - state.snx.tokenRate = payload.rewardRate ?? state.snx.tokenRate - state.snx.leftToClaim = payload.leftToClaim ?? state.snx.leftToClaim - } - }) }) diff --git a/src/state/staking/updater.ts b/src/state/staking/updater.ts index 9083d64b653..25c25657e46 100644 --- a/src/state/staking/updater.ts +++ b/src/state/staking/updater.ts @@ -1,56 +1,77 @@ import { JSBI } from '@ubeswap/sdk' +import { ExternalStakingRewards } from 'constants/staking' import { useWeb3Context } from 'hooks' -import { useDispatch, useSelector } from 'react-redux' -import { AppDispatch, AppState } from 'state' +import { useEffect } from 'react' +import { useDispatch } from 'react-redux' +import { AppDispatch } from 'state' import { useSingleCallResult } from 'state/multicall/hooks' +import { CHAIN } from '../../constants' import { useGaugeControllerContract, useMobiContract, useStakingContract, useVotingEscrowContract, } from '../../hooks/useContract' -import { updateSNX, updateStaking } from './actions' +import { updateStaking, updateStakingUser } from './actions' // pools, general staking, general gauges, user staking, user gauges export default function StakingUpdater() { - const snxAddress: string = useSelector((state: AppState) => state.staking.snx.address) const dispatch = useDispatch() const mobiContract = useMobiContract() const votingEscrow = useVotingEscrowContract() const controller = useGaugeControllerContract() - const snxContract = useStakingContract(snxAddress) + const snxContract = useStakingContract(ExternalStakingRewards[CHAIN]) const { address, connected } = useWeb3Context() const votingPower = useSingleCallResult(votingEscrow, 'balanceOf(address)', [connected ? address : undefined]) - const totalVotingPower = useSingleCallResult(votingEscrow, 'totalSupply()') - const totalMobiLocked = useSingleCallResult(mobiContract, 'balanceOf(address)', [votingEscrow?.address ?? undefined]) const locked = useSingleCallResult(votingEscrow, 'locked', [connected ? address : undefined]) + const snxToClaim = useSingleCallResult(snxContract, 'earned(address)', [connected ? address : undefined]) const allocatedPower = useSingleCallResult(controller, 'vote_user_power', [connected ? address : undefined]) + + const totalVotingPower = useSingleCallResult(votingEscrow, 'totalSupply()') const totalWeight = useSingleCallResult(controller, 'get_total_weight') + const totalMobiLocked = useSingleCallResult(mobiContract, 'balanceOf(address)', [votingEscrow?.address ?? undefined]) const snxRewardRate = useSingleCallResult(snxContract, 'rewardRate()') - const snxToClaim = useSingleCallResult(snxContract, 'earned(address)', [connected ? address : undefined]) - dispatch( - updateSNX({ - rewardRate: snxRewardRate?.result ? JSBI.BigInt(snxRewardRate?.result?.[0] ?? '0') : undefined, - leftToClaim: snxToClaim?.result ? JSBI.BigInt(snxToClaim?.result?.[0] ?? '0') : undefined, - }) - ) - dispatch( - updateStaking({ - stakingInfo: { - votingPower: JSBI.BigInt(votingPower?.result?.[0] ?? '0'), - totalVotingPower: JSBI.BigInt(totalVotingPower?.result?.[0] ?? '0'), - locked: { - amount: JSBI.BigInt(locked?.result?.amount ?? '0'), - end: parseInt(locked?.result?.end.toString()) * 1000, // Need unix in milliseconds + useEffect(() => { + connected && + dispatch( + updateStakingUser({ + userStakingState: { + voteUserPower: JSBI.BigInt(allocatedPower?.result?.[0] ?? '0'), + votingPower: JSBI.BigInt(votingPower?.result?.[0] ?? '0'), + claimableExternalRewards: JSBI.BigInt(snxToClaim?.result?.[0] ?? '0'), + lock: { + amount: JSBI.BigInt(locked?.result?.amount ?? '0'), + end: parseInt(locked?.result?.end.toString()) * 1000, // Need unix in milliseconds + }, + }, + }) + ) + dispatch( + updateStaking({ + stakingState: { + totalVotingPower: JSBI.BigInt(totalVotingPower?.result?.[0] ?? '0'), + totalWeight: JSBI.BigInt(totalWeight?.result?.[0] ?? '0'), + totalMobiLocked: JSBI.BigInt(totalMobiLocked?.result?.[0] ?? '0'), + externalRewardsRate: JSBI.BigInt(snxRewardRate?.result?.[0] ?? '0'), }, - voteUserPower: JSBI.BigInt(allocatedPower?.result?.[0] ?? '0'), - totalWeight: JSBI.BigInt(totalWeight?.result?.[0] ?? '0'), - totalMobiLocked: JSBI.BigInt(totalMobiLocked?.result?.[0] ?? '0'), - }, - }) - ) + }) + ) + }, [ + allocatedPower?.result, + connected, + dispatch, + locked?.result?.amount, + locked?.result?.end, + snxRewardRate?.result, + snxToClaim?.result, + totalMobiLocked?.result, + totalVotingPower?.result, + totalWeight?.result, + votingPower?.result, + ]) + return null } From 7edb32ca77431df0224f8af1edd3aef883dc8bb2 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 22 Feb 2022 12:37:15 -0500 Subject: [PATCH 02/72] new external staking rewards hook --- src/hooks/useExternalStakingRewards.ts | 53 ++++++++++++++++++++++++++ src/pages/Staking/VeMobiRewards.tsx | 7 +--- src/state/staking/hooks.ts | 41 ++++++-------------- 3 files changed, 65 insertions(+), 36 deletions(-) create mode 100644 src/hooks/useExternalStakingRewards.ts diff --git a/src/hooks/useExternalStakingRewards.ts b/src/hooks/useExternalStakingRewards.ts new file mode 100644 index 00000000000..f81c31165dd --- /dev/null +++ b/src/hooks/useExternalStakingRewards.ts @@ -0,0 +1,53 @@ +import { JSBI, Percent, TokenAmount } from '@ubeswap/sdk' +import { calcApy } from 'components/earn/StablePoolCard' +import { CELO } from 'constants/tokens' +import { useTokenPrice } from 'state/application/hooks' +import { useStakingState, useStakingStateCombined } from 'state/staking/hooks' + +import { CHAIN } from '../constants' +import { useMobi } from './Tokens' + +const SECONDS_IN_YEAR = JSBI.BigInt(365 * 24 * 60 * 60) +const SECONDS_IN_WEEK = JSBI.BigInt(7 * 24 * 60 * 60) + +export type ExternalRewardInfo = { + rewardRate: TokenAmount + avgApr: Percent +} + +export type ExternalUserRewardInfo = { + userRewardRate: TokenAmount + claimableRewards: TokenAmount +} + +export function useExternalStakingRewards(): ExternalRewardInfo { + const stakingState = useStakingState() + const mobi = useMobi() + const priceOfReward = useTokenPrice(CELO[CHAIN].address) + const priceOfMobi = useTokenPrice(mobi?.address) + const yearlyRate = JSBI.multiply(stakingState.externalRewardsRate, SECONDS_IN_YEAR) + + const avgApr = + priceOfReward && priceOfMobi + ? calcApy(priceOfReward?.multiply(yearlyRate), priceOfMobi?.multiply(stakingState.totalVotingPower))[1] ?? + new Percent('0') + : new Percent('0') + + return { + rewardRate: new TokenAmount(CELO[CHAIN], stakingState.externalRewardsRate), + avgApr, + } +} + +export function useUserExternalStakingRewards(): ExternalUserRewardInfo { + const stakingState = useStakingStateCombined() + const userRateJSBI = JSBI.divide( + JSBI.multiply(SECONDS_IN_WEEK, JSBI.multiply(stakingState.externalRewardsRate, stakingState.votingPower)), + stakingState.totalVotingPower + ) + + return { + userRewardRate: new TokenAmount(CELO[CHAIN], userRateJSBI), + claimableRewards: new TokenAmount(CELO[CHAIN], stakingState.claimableExternalRewards), + } +} diff --git a/src/pages/Staking/VeMobiRewards.tsx b/src/pages/Staking/VeMobiRewards.tsx index ed46b2761a7..595cc4d7433 100644 --- a/src/pages/Staking/VeMobiRewards.tsx +++ b/src/pages/Staking/VeMobiRewards.tsx @@ -1,5 +1,5 @@ import { TransactionResponse } from '@ethersproject/abstract-provider' -import { ButtonEmpty, ButtonPrimary } from 'components/Button' +import { ButtonPrimary } from 'components/Button' import { AutoColumn } from 'components/Column' import Loader from 'components/Loader' import { RowBetween, RowFixed } from 'components/Row' @@ -110,11 +110,6 @@ const Divider = styled.div` opacity: 0.5; ` -const StyledButton = styled(ButtonEmpty)` - margin-left: auto; - margin-right: 0.5rem; -` - export default function VeMobiRewards() { const { rewardToken, rewardRate, avgApr, userRewardRate, leftToClaim, snxAddress } = useSNXRewardInfo() const tokenColor = '#ab9325' //useColor(rewardToken) diff --git a/src/state/staking/hooks.ts b/src/state/staking/hooks.ts index e7088634dff..1b530628b08 100644 --- a/src/state/staking/hooks.ts +++ b/src/state/staking/hooks.ts @@ -1,14 +1,12 @@ import { JSBI, Percent, Token, TokenAmount } from '@ubeswap/sdk' -import { calcApy } from 'components/earn/StablePoolCard' -import { addressToToken, useMobi, useVeMobi } from 'hooks/Tokens' +import { useMobi, useVeMobi } from 'hooks/Tokens' import { useSelector } from 'react-redux' import { AppState } from 'state' -import { useTokenPrice } from 'state/application/hooks' import { getPoolInfo } from 'state/stablePools/hooks' import { StableSwapPool } from 'state/stablePools/reducer' import { getDepositValues } from 'utils/stableSwaps' -import { StakingState } from './reducer' +import { IStakingState, IUserStakingState } from './reducer' const SECONDS_IN_YEAR = JSBI.BigInt(365 * 24 * 60 * 60) const SECONDS_IN_WEEK = JSBI.BigInt(7 * 24 * 60 * 60) @@ -140,7 +138,7 @@ export function usePriceOfDeposits() { } export function useLockEnd(): number { - const lockEnd = useSelector((state) => state.staking?.locked?.end ?? 0) + const lockEnd = useSelector((state) => state.staking?.lock?.end ?? 0) return lockEnd } @@ -149,31 +147,14 @@ export function useVotePowerLeft(): number { return (10000 - parseInt(votePower.toString())) / 100 } -export function useSNXRewardInfo(): SNXRewardInfo { - const stakingInfo = useSelector((state) => state.staking) - const snxInfo = stakingInfo.snx - const mobi = useMobi() +export function useStakingState(): IStakingState { + return useSelector((state) => state.staking) +} - const rewardToken = addressToToken(snxInfo?.rewardToken ?? '') - const priceOfReward = useTokenPrice(snxInfo?.rewardToken) - const priceOfMobi = useTokenPrice(mobi?.address) - if (!snxInfo || !snxInfo.tokenRate) return { snxAddress: snxInfo?.address, rewardToken } - const yearlyRate = JSBI.multiply(snxInfo.tokenRate, SECONDS_IN_YEAR) - const apy = - priceOfReward && priceOfMobi - ? calcApy(priceOfReward?.multiply(yearlyRate), priceOfMobi?.multiply(stakingInfo.totalVotingPower))[1] - : undefined - const rewardRate = new TokenAmount(rewardToken, JSBI.multiply(snxInfo.tokenRate, SECONDS_IN_WEEK)) - const userRateJSBI = JSBI.divide(JSBI.multiply(rewardRate.raw, stakingInfo.votingPower), stakingInfo.totalVotingPower) - //rewardRate.multiply(stakingInfo.votingPower).divide(stakingInfo.totalVotingPower) - const userRewardRate = new TokenAmount(rewardToken, userRateJSBI) +export function useUserStakingState(): IUserStakingState { + return useSelector((state) => state.staking) +} - return { - snxAddress: snxInfo.address, - rewardToken, - rewardRate, - leftToClaim: snxInfo.leftToClaim ? new TokenAmount(rewardToken, snxInfo.leftToClaim) : undefined, - avgApr: apy, - userRewardRate, - } +export function useStakingStateCombined(): IStakingState & IUserStakingState { + return useSelector((state) => state.staking) } From 04611c7346c41b1e2a9bf8e3fa3740bdc71a6971 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 22 Feb 2022 14:46:33 -0500 Subject: [PATCH 03/72] fix references to staking hooks --- src/components/earn/StablePoolCard.tsx | 9 ++++----- src/pages/Staking/LockModal.tsx | 6 +++--- src/pages/Staking/StatsHeader.tsx | 7 +++---- src/pages/Staking/VeMobiRewards.tsx | 28 ++++++++++++++++---------- src/state/staking/hooks.ts | 3 --- 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/components/earn/StablePoolCard.tsx b/src/components/earn/StablePoolCard.tsx index d883711d8e0..fabfccc6a8e 100644 --- a/src/components/earn/StablePoolCard.tsx +++ b/src/components/earn/StablePoolCard.tsx @@ -142,17 +142,16 @@ export function calcApy(rewardPerYear: Fraction, totalStakedAmount: Fraction) { const apyFraction = rewardPerYear .multiply(JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18'))) .divide(totalStakedAmount) - const apy = apyFraction ? new Percent( apyFraction.numerator, JSBI.multiply(apyFraction.denominator, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18'))) ) : undefined - - const dpy = apy - ? new Percent(Math.floor(parseFloat(apy.divide('365').toFixed(10)) * 1_000_000).toFixed(0), '1000000') - : undefined + const dpy = + apy && !apy.equalTo('0') + ? new Percent(Math.floor(parseFloat(apy.divide('365').toFixed(10)) * 1_000_000).toFixed(0), '1000000') + : undefined return [apyFraction, apy, dpy] } diff --git a/src/pages/Staking/LockModal.tsx b/src/pages/Staking/LockModal.tsx index d6234f1976b..00a7ec0d92d 100644 --- a/src/pages/Staking/LockModal.tsx +++ b/src/pages/Staking/LockModal.tsx @@ -1,9 +1,9 @@ import { TransactionResponse } from '@ethersproject/abstract-provider' import { ButtonConfirmed } from 'components/Button' import Loader from 'components/Loader' +import { ExternalStakingRewards } from 'constants/staking' import { useStakingContract } from 'hooks/useContract' import React, { useState } from 'react' -import { useSNXRewardInfo } from 'state/staking/hooks' import { useTransactionAdder } from 'state/transactions/hooks' import styled from 'styled-components' @@ -11,6 +11,7 @@ import { AutoColumn } from '../../components/Column' import Modal from '../../components/Modal' import { LoadingView, SubmittedView } from '../../components/ModalViews' import { RowBetween } from '../../components/Row' +import { CHAIN } from '../../constants' import { CloseIcon, TYPE } from '../../theme' import ExtendLock from './ExtendLock' import IncreaseLockAmount from './IncreaseLockAmount' @@ -42,8 +43,7 @@ const ModifiedWrapper = styled(ContentWrapper)` export default function LockModal({ isOpen, onDismiss, lockType = LockType.initial }: LockModalProps) { // monitor call to help UI loading state - const { snxAddress } = useSNXRewardInfo() - const stakingContract = useStakingContract(snxAddress) + const stakingContract = useStakingContract(ExternalStakingRewards[CHAIN]) const addTransaction = useTransactionAdder() const [hash, setHash] = useState() const [hasSnapshot, setHasSnapshot] = useState(0) diff --git a/src/pages/Staking/StatsHeader.tsx b/src/pages/Staking/StatsHeader.tsx index eab1d1c11dd..0edbbd0d8ee 100644 --- a/src/pages/Staking/StatsHeader.tsx +++ b/src/pages/Staking/StatsHeader.tsx @@ -1,9 +1,9 @@ import Column from 'components/Column' import Loader from 'components/Loader' -import { useMobi } from 'hooks/Tokens' +import { useExternalStakingRewards } from 'hooks/useExternalStakingRewards' import React from 'react' import { isMobile } from 'react-device-detect' -import { MobiStakingInfo, usePriceOfDeposits, useSNXRewardInfo } from 'state/staking/hooks' +import { MobiStakingInfo, usePriceOfDeposits } from 'state/staking/hooks' import { useIsDarkMode } from 'state/user/hooks' import styled from 'styled-components' import { TYPE } from 'theme' @@ -67,8 +67,7 @@ type PropType = { } function StatsHeader({ stakingInfo }: PropType) { const priceOfDeposits = usePriceOfDeposits() - const mobi = useMobi() - const { avgApr } = useSNXRewardInfo() + const { avgApr } = useExternalStakingRewards() const isDarkMode = useIsDarkMode() const displayData = [ diff --git a/src/pages/Staking/VeMobiRewards.tsx b/src/pages/Staking/VeMobiRewards.tsx index 595cc4d7433..9f34642bbbc 100644 --- a/src/pages/Staking/VeMobiRewards.tsx +++ b/src/pages/Staking/VeMobiRewards.tsx @@ -3,15 +3,17 @@ import { ButtonPrimary } from 'components/Button' import { AutoColumn } from 'components/Column' import Loader from 'components/Loader' import { RowBetween, RowFixed } from 'components/Row' +import { ExternalStakingRewards } from 'constants/staking' import { useWeb3Context } from 'hooks' import { useStakingContract } from 'hooks/useContract' +import { useExternalStakingRewards, useUserExternalStakingRewards } from 'hooks/useExternalStakingRewards' import React, { useState } from 'react' -import { useSNXRewardInfo } from 'state/staking/hooks' import { useTransactionAdder } from 'state/transactions/hooks' import styled from 'styled-components' import { TYPE } from 'theme' import { CardNoise, CardSection, DataCard } from '../../components/earn/styled' +import { CHAIN } from '../../constants' const VoteCard = styled(DataCard)` background: radial-gradient(90% 90% at 50% 5%, #3488ec 0%, #35d07f 100%); @@ -111,8 +113,10 @@ const Divider = styled.div` ` export default function VeMobiRewards() { - const { rewardToken, rewardRate, avgApr, userRewardRate, leftToClaim, snxAddress } = useSNXRewardInfo() - const tokenColor = '#ab9325' //useColor(rewardToken) + const { rewardRate, avgApr } = useExternalStakingRewards() + const { userRewardRate, claimableRewards } = useUserExternalStakingRewards() + const snxAddress = ExternalStakingRewards[CHAIN] + const tokenColor = '#ab9325' const { connected } = useWeb3Context() const stakingContract = useStakingContract(snxAddress) const addTransaction = useTransactionAdder() @@ -170,7 +174,7 @@ export default function VeMobiRewards() { - {`${rewardToken.symbol} Rewards`} + {`${rewardRate.token.symbol} Rewards`} @@ -182,7 +186,7 @@ export default function VeMobiRewards() { - {`${rewardToken.symbol} Rate: `} + {`${rewardRate.token.symbol} Rate: `} @@ -191,7 +195,7 @@ export default function VeMobiRewards() { fontSize={[13, 16]} fontWeight={800} color={tokenColor} - >{`${rewardRate.toSignificant(4, { groupSeparator: ',' })} ${rewardToken.symbol} / WEEK`} + >{`${rewardRate.toSignificant(4, { groupSeparator: ',' })} ${rewardRate.token.symbol} / WEEK`} @@ -206,7 +210,9 @@ export default function VeMobiRewards() { fontSize={[13, 16]} fontWeight={800} color={tokenColor} - >{`${userRewardRate.toSignificant(4, { groupSeparator: ',' })} ${rewardToken.symbol} / WEEK`} + >{`${userRewardRate.toSignificant(4, { groupSeparator: ',' })} ${ + rewardRate.token.symbol + } / WEEK`} <> @@ -215,9 +221,9 @@ export default function VeMobiRewards() { */} Available to Claim: - {leftToClaim ? ( - {`${leftToClaim.toSignificant(4, { groupSeparator: ',' })} ${ - rewardToken.symbol + {claimableRewards ? ( + {`${claimableRewards.toSignificant(4, { groupSeparator: ',' })} ${ + rewardRate.token.symbol }`} ) : connected ? ( @@ -231,7 +237,7 @@ export default function VeMobiRewards() { disabled={attempting && !hash} style={{ fontWeight: 700, fontSize: 18, marginBottom: '1rem' }} > - {attempting && !hash ? `Claiming ${leftToClaim?.toFixed(2)} CELO...` : 'CLAIM'} + {attempting && !hash ? `Claiming ${claimableRewards?.toFixed(2)} CELO...` : 'CLAIM'} diff --git a/src/state/staking/hooks.ts b/src/state/staking/hooks.ts index 1b530628b08..634f68dec21 100644 --- a/src/state/staking/hooks.ts +++ b/src/state/staking/hooks.ts @@ -8,9 +8,6 @@ import { getDepositValues } from 'utils/stableSwaps' import { IStakingState, IUserStakingState } from './reducer' -const SECONDS_IN_YEAR = JSBI.BigInt(365 * 24 * 60 * 60) -const SECONDS_IN_WEEK = JSBI.BigInt(7 * 24 * 60 * 60) - export type GaugeSummary = { pool: string poolAddress: string From 963670926bf1e9d2f4801b3e9240a4416d68f079 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 22 Feb 2022 15:58:42 -0500 Subject: [PATCH 04/72] add new redux for just pools --- src/constants/pools.ts | 61 ++++++++++++++-------------- src/state/index.ts | 2 + src/state/mobiusPools/actions.ts | 4 ++ src/state/mobiusPools/hooks.ts | 31 ++++++++++++++ src/state/mobiusPools/reducer.ts | 31 ++++++++++++++ src/state/mobiusPools/updater.ts | 69 ++++++++++++++++++++++++++++++++ src/state/staking/hooks.ts | 43 ++++++++------------ 7 files changed, 183 insertions(+), 58 deletions(-) create mode 100644 src/state/mobiusPools/actions.ts create mode 100644 src/state/mobiusPools/hooks.ts create mode 100644 src/state/mobiusPools/reducer.ts create mode 100644 src/state/mobiusPools/updater.ts diff --git a/src/constants/pools.ts b/src/constants/pools.ts index 9afd64cc670..b5fa3abc018 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -1,5 +1,7 @@ -import { ChainId, cUSD, Percent, Token, TokenAmount } from '@ubeswap/sdk' -import type JSBI from 'jsbi' +import { ChainId, Percent, Token, TokenAmount } from '@ubeswap/sdk' +import JSBI from 'jsbi' + +import { CUSD } from './tokens' export type Fees = { trade: Percent @@ -28,13 +30,23 @@ export interface IExchangeInfo { } export interface IGauge { - exchange: IExchange address: string additionalRewards?: string[] additionalRewardRate?: string[] +} + +export interface IGaugeInfo { isKilled?: boolean } +export interface Volume { + volume: { + total: number + day: number + week: number + } | null +} + export enum Coins { Bitcoin, Ether, @@ -102,7 +114,8 @@ export interface DisplayPool { name: string chain: Chain peg: Peg - pool: IGauge | IExchange + pool: IExchange + gauge: IGauge | null warningType?: WarningType } @@ -126,23 +139,7 @@ export const RECOMMENDED_FEES: Fees = { deposit: new Percent(recommendedFeesRaw.depositFeeNumerator, recommendedFeesRaw.depositFeeDenominator), } -export const Pools: { [K in ChainId]: IExchange[] } = { - [ChainId.MAINNET]: [ - { - address: '0x9F4AdBD0af281C69a582eB2E6fa2A594D4204CAe', - lpToken: new Token( - ChainId.MAINNET, - '0x9438e7281D7E3e99A9dD21e0EAd9c6a254e17ab2', - 18, - 'MobLP', - 'Mobius cUSD/aUST LP' - ), - tokens: [cUSD[ChainId.MAINNET], UST], - }, - ], - [ChainId.ALFAJORES]: [], - [ChainId.BAKLAVA]: [], -} +export const RECOMMENDED_AMP = JSBI.BigInt('100') export const StablePools: { [K in ChainId]: DisplayPool[] } = { [ChainId.MAINNET]: [ @@ -151,17 +148,17 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { chain: Chain.Terra, peg: Dollar, pool: { - exchange: { - address: '0x9F4AdBD0af281C69a582eB2E6fa2A594D4204CAe', - lpToken: new Token( - ChainId.MAINNET, - '0x9438e7281D7E3e99A9dD21e0EAd9c6a254e17ab2', - 18, - 'MobLP', - 'Mobius cUSD/aUST LP' - ), - tokens: [cUSD[ChainId.MAINNET], UST], - }, + address: '0x9F4AdBD0af281C69a582eB2E6fa2A594D4204CAe', + lpToken: new Token( + ChainId.MAINNET, + '0x9438e7281D7E3e99A9dD21e0EAd9c6a254e17ab2', + 18, + 'MobLP', + 'Mobius cUSD/aUST LP' + ), + tokens: [CUSD[ChainId.MAINNET], UST], + }, + gauge: { address: '0x107F94409746E8c8E6eFF139A100D17D9ca7FdfE', additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], additionalRewardRate: ['12000000000000000'], diff --git a/src/state/index.ts b/src/state/index.ts index ad265cd1f07..ff2ae283d97 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -9,6 +9,7 @@ import logs from './logs/slice' import mento from './mento/reducer' import mentoPools from './mentoPools/reducer' import mint from './mint/reducer' +import pools from './mobiusPools/reducer' import multicall from './multicall/reducer' import openSum from './openSum/reducer' import stablePools from './stablePools/reducer' @@ -29,6 +30,7 @@ const store = configureStore({ burn, multicall, stablePools, + pools, mentoPools, mento, claim, diff --git a/src/state/mobiusPools/actions.ts b/src/state/mobiusPools/actions.ts new file mode 100644 index 00000000000..2117f26f051 --- /dev/null +++ b/src/state/mobiusPools/actions.ts @@ -0,0 +1,4 @@ +import { createAction } from '@reduxjs/toolkit' +import { IExchange, IExchangeInfo, Volume } from 'constants/pools' + +export const updatePools = createAction<{ pools: (IExchangeInfo & IExchange & Volume)[] }>('pools/updatePools') diff --git a/src/state/mobiusPools/hooks.ts b/src/state/mobiusPools/hooks.ts new file mode 100644 index 00000000000..9ffd8163b6b --- /dev/null +++ b/src/state/mobiusPools/hooks.ts @@ -0,0 +1,31 @@ +import { IExchangeInfo, Volume } from 'constants/pools' +import { useSelector } from 'react-redux' +import invariant from 'tiny-invariant' + +import { AppState } from '..' + +export function useCurrentPool(exchangeAddress: string): IExchangeInfo | null { + const pools = useSelector((state) => + state.pools.pools.filter((pool) => pool.address === exchangeAddress) + ) + if (pools.length === 0) return null + invariant(pools.length === 1) + return pools[0] +} + +export function usePools(): readonly IExchangeInfo[] { + return useSelector((state) => state.pools.pools) +} + +export function useCurrentPoolVolume(exchangeAddress: string): Volume | null { + const pools = useSelector((state) => + state.pools.pools.filter((pool) => pool.address === exchangeAddress) + ) + if (pools.length === 0) return null + invariant(pools.length === 1) + return pools[0] +} + +export function usePoolsVolume(): readonly Volume[] { + return useSelector((state) => state.pools.pools) +} diff --git a/src/state/mobiusPools/reducer.ts b/src/state/mobiusPools/reducer.ts new file mode 100644 index 00000000000..249218c2a84 --- /dev/null +++ b/src/state/mobiusPools/reducer.ts @@ -0,0 +1,31 @@ +import { createReducer } from '@reduxjs/toolkit' +import { TokenAmount } from '@ubeswap/sdk' +import { IExchange, IExchangeInfo, RECOMMENDED_AMP, RECOMMENDED_FEES, StablePools, Volume } from 'constants/pools' + +import { CHAIN } from '../../constants' +import { updatePools } from './actions' + +export interface Pools { + readonly pools: (IExchangeInfo & IExchange & Volume)[] +} + +function emptyExchangeInfo(exchange: IExchange): IExchangeInfo & IExchange & Volume { + return { + ...exchange, + fees: RECOMMENDED_FEES, + ampFactor: RECOMMENDED_AMP, + lpTotalSupply: new TokenAmount(exchange.lpToken, '0'), + reserves: [new TokenAmount(exchange.tokens[0], '0'), new TokenAmount(exchange.tokens[1], '0')], + volume: null, + } +} + +const initialState: Pools = { + pools: StablePools[CHAIN].map((p) => emptyExchangeInfo(p.pool)), +} + +export default createReducer(initialState, (builder) => + builder.addCase(updatePools, (state, { payload: { pools } }) => { + pools + }) +) diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts new file mode 100644 index 00000000000..e3175eebaf7 --- /dev/null +++ b/src/state/mobiusPools/updater.ts @@ -0,0 +1,69 @@ +import { gql, useQuery } from '@apollo/client' +import { Interface } from '@ethersproject/abi' +import { TokenAmount } from '@ubeswap/sdk' +import { RECOMMENDED_AMP, RECOMMENDED_FEES, StablePools } from 'constants/pools' +import { useEffect } from 'react' +import { useDispatch } from 'react-redux' +import { useBlockNumber } from 'state/application/hooks' +import { useMultipleContractSingleData } from 'state/multicall/hooks' + +import { CHAIN } from '../../constants' +import LP from '../../constants/abis/LPToken.json' +import { AppDispatch } from '../index' +import { updatePools } from './actions' + +const lpInterface = new Interface(LP.abi) + +export function UpdateMento() { + const blockNumber = useBlockNumber() + const dispatch = useDispatch() + const stablePools = StablePools[CHAIN] + const lpTokenAddress = stablePools.map((p) => p.pool.lpToken.address) + const lpTotalSupply = useMultipleContractSingleData(lpTokenAddress, lpInterface, 'totalSupply') + + const query = gql` + { + swaps { + id + A + balances + virtualPrice + dailyVolumes(orderBy: timestamp, orderDirection: desc) { + volume + } + weeklyVolumes(first: 2, orderBy: timestamp, orderDirection: desc) { + volume + } + } + } + ` + const { data, loading, error } = useQuery(query) + + useEffect(() => { + if (loading) return + const inSubgraph: Set = + data?.swaps.reduce((accum: Set, cur: any) => new Set([...accum, cur.id]), new Set()) ?? new Set() + try { + dispatch( + updatePools({ + pools: stablePools.map((displayPool, i) => { + return { + ...displayPool.pool, + fees: RECOMMENDED_FEES, + volume: null, + ampFactor: RECOMMENDED_AMP, + lpTotalSupply: new TokenAmount(displayPool.pool.lpToken, lpTotalSupply[i]?.result?.[0] ?? '0'), + reserves: [ + new TokenAmount(displayPool.pool.tokens[0], '0'), + new TokenAmount(displayPool.pool.tokens[1], '0'), + ], + } + }), + }) + ) + } catch (error) { + console.error(error) + } + }, [loading, data?.swaps, dispatch, stablePools, lpTotalSupply, blockNumber]) + return null +} diff --git a/src/state/staking/hooks.ts b/src/state/staking/hooks.ts index 634f68dec21..6fbacd204f9 100644 --- a/src/state/staking/hooks.ts +++ b/src/state/staking/hooks.ts @@ -34,32 +34,23 @@ export type MobiStakingInfo = { positions?: GaugeSummary[] } -export type SNXRewardInfo = { - snxAddress: string - rewardToken: Token - rewardRate?: TokenAmount - leftToClaim?: TokenAmount - avgApr?: Percent - userRewardRate?: TokenAmount -} - -export function calculateBoostedBalance( - votingPower: JSBI, - totalVotingPower: JSBI, - liquidity: JSBI, - totalLiquidity: JSBI -): JSBI { - let boosted = JSBI.BigInt('0') - if (!JSBI.equal(totalVotingPower, JSBI.BigInt('0'))) - boosted = JSBI.add( - JSBI.divide(JSBI.multiply(JSBI.BigInt(4), liquidity), JSBI.BigInt(10)), - JSBI.divide( - JSBI.multiply(JSBI.BigInt(6), JSBI.multiply(totalLiquidity, votingPower)), - JSBI.multiply(totalVotingPower, JSBI.BigInt(10)) - ) - ) - return JSBI.greaterThan(boosted, liquidity) ? boosted : liquidity -} +// export function calculateBoostedBalance( +// votingPower: JSBI, +// totalVotingPower: JSBI, +// liquidity: JSBI, +// totalLiquidity: JSBI +// ): JSBI { +// let boosted = JSBI.BigInt('0') +// if (!JSBI.equal(totalVotingPower, JSBI.BigInt('0'))) +// boosted = JSBI.add( +// JSBI.divide(JSBI.multiply(JSBI.BigInt(4), liquidity), JSBI.BigInt(10)), +// JSBI.divide( +// JSBI.multiply(JSBI.BigInt(6), JSBI.multiply(totalLiquidity, votingPower)), +// JSBI.multiply(totalVotingPower, JSBI.BigInt(10)) +// ) +// ) +// return JSBI.greaterThan(boosted, liquidity) ? boosted : liquidity +// } export function useMobiStakingInfo(): MobiStakingInfo { const stakingInfo = useSelector((state) => state.staking) From 53610a71e2e6b6c4bad7d799b72c8d80773a5280 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 22 Feb 2022 16:41:53 -0500 Subject: [PATCH 05/72] mobius pool updater --- src/index.tsx | 2 ++ src/state/mobiusPools/updater.ts | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 59cf0be3dad..0939f15868d 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -8,6 +8,7 @@ import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import { HashRouter } from 'react-router-dom' import { UpdateMento } from 'state/mentoPools/updater' +import { UpdatePools } from 'state/mobiusPools/updater' import { UpdateOpenSum } from 'state/openSum/updater' import { BatchUpdateGauges, UpdateVariablePoolInfo } from 'state/stablePools/updater' import StakingUpdater from 'state/staking/updater' @@ -58,6 +59,7 @@ function Updaters() { + diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index e3175eebaf7..3b7c9232dac 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -6,20 +6,25 @@ import { useEffect } from 'react' import { useDispatch } from 'react-redux' import { useBlockNumber } from 'state/application/hooks' import { useMultipleContractSingleData } from 'state/multicall/hooks' +import { BigIntToJSBI } from 'state/stablePools/updater' import { CHAIN } from '../../constants' import LP from '../../constants/abis/LPToken.json' +import SWAP from '../../constants/abis/Swap.json' import { AppDispatch } from '../index' import { updatePools } from './actions' const lpInterface = new Interface(LP.abi) +const SwapInterface = new Interface(SWAP.abi) export function UpdateMento() { const blockNumber = useBlockNumber() const dispatch = useDispatch() const stablePools = StablePools[CHAIN] const lpTokenAddress = stablePools.map((p) => p.pool.lpToken.address) + const poolAddress = stablePools.map((p) => p.pool.address) const lpTotalSupply = useMultipleContractSingleData(lpTokenAddress, lpInterface, 'totalSupply') + const balances = useMultipleContractSingleData(poolAddress, SwapInterface, 'getBalances') const query = gql` { @@ -53,10 +58,12 @@ export function UpdateMento() { volume: null, ampFactor: RECOMMENDED_AMP, lpTotalSupply: new TokenAmount(displayPool.pool.lpToken, lpTotalSupply[i]?.result?.[0] ?? '0'), - reserves: [ - new TokenAmount(displayPool.pool.tokens[0], '0'), - new TokenAmount(displayPool.pool.tokens[1], '0'), - ], + reserves: balances?.[i]?.result?.[0] + ? balances?.[i]?.result?.[0].map( + (amt: BigInt, j: number): TokenAmount => + new TokenAmount(displayPool.pool.tokens[j], BigIntToJSBI(amt)) + ) + : [new TokenAmount(displayPool.pool.tokens[0], '0'), new TokenAmount(displayPool.pool.tokens[1], '0')], } }), }) @@ -64,6 +71,6 @@ export function UpdateMento() { } catch (error) { console.error(error) } - }, [loading, data?.swaps, dispatch, stablePools, lpTotalSupply, blockNumber]) + }, [loading, data?.swaps, dispatch, stablePools, lpTotalSupply, blockNumber, balances]) return null } From 0b47a7d74d83080345be732b28df92da3b8a3cbf Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 22 Feb 2022 16:57:53 -0500 Subject: [PATCH 06/72] partly refactored swap --- src/state/mobiusPools/hooks.ts | 13 ++++++++++++- src/state/mobiusPools/updater.ts | 2 +- src/state/swap/hooks.ts | 25 ++++++++----------------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/state/mobiusPools/hooks.ts b/src/state/mobiusPools/hooks.ts index 9ffd8163b6b..3fa4b879e50 100644 --- a/src/state/mobiusPools/hooks.ts +++ b/src/state/mobiusPools/hooks.ts @@ -4,7 +4,18 @@ import invariant from 'tiny-invariant' import { AppState } from '..' -export function useCurrentPool(exchangeAddress: string): IExchangeInfo | null { +export function useCurrentPool(token0: string, token1: string): IExchangeInfo | null { + const pools = useSelector((state) => + state.pools.pools.filter((pool) => { + const tokens = pool.tokens.map((t) => t.address) + return tokens.includes(token0) && tokens.includes(token1) + }) + ) + if (pools.length === 0) return null + invariant(pools.length === 1) + return pools[0] +} +export function useCurrentPoolAddress(exchangeAddress: string): IExchangeInfo | null { const pools = useSelector((state) => state.pools.pools.filter((pool) => pool.address === exchangeAddress) ) diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index 3b7c9232dac..d648ba4ab57 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -17,7 +17,7 @@ import { updatePools } from './actions' const lpInterface = new Interface(LP.abi) const SwapInterface = new Interface(SWAP.abi) -export function UpdateMento() { +export function UpdatePools() { const blockNumber = useBlockNumber() const dispatch = useDispatch() const stablePools = StablePools[CHAIN] diff --git a/src/state/swap/hooks.ts b/src/state/swap/hooks.ts index c0bc2840f02..417ed33593c 100644 --- a/src/state/swap/hooks.ts +++ b/src/state/swap/hooks.ts @@ -2,6 +2,7 @@ import { parseUnits } from '@ethersproject/units' import { JSBI, Percent, Price, Token, TokenAmount, TradeType } from '@ubeswap/sdk' import { useCallback } from 'react' import { useDispatch, useSelector } from 'react-redux' +import { useCurrentPool, usePools } from 'state/mobiusPools/hooks' import { StableSwapPool } from 'state/stablePools/reducer' import invariant from 'tiny-invariant' import { StableSwapMath } from 'utils/stableSwapMath' @@ -10,7 +11,6 @@ import { useWeb3Context } from '../../hooks' import { useCurrency } from '../../hooks/Tokens' import { isAddress } from '../../utils' import { AppDispatch, AppState } from '../index' -import { useCurrentPool, useMathUtil, usePools } from '../stablePools/hooks' import { useCurrencyBalances } from '../wallet/hooks' import { Field, selectCurrency, setRecipient, switchCurrencies, typeInput } from './actions' @@ -156,8 +156,7 @@ export function useMobiusTradeInfo(): { const pools = usePools() const poolsLoading = pools.length === 0 - const [pool] = useCurrentPool(inputCurrency?.address ?? '', outputCurrency?.address ?? '') - const mathUtil = useMathUtil(pool ?? '') + const pool = useCurrentPool(inputCurrency?.address ?? '', outputCurrency?.address ?? '') const to: string | null = connected ? address : null const relevantTokenBalances = useCurrencyBalances(connected ? address : undefined, [ @@ -186,11 +185,11 @@ export function useMobiusTradeInfo(): { if (!parsedAmount) { inputError = inputError ?? 'Enter an amount' } - if (!pool || pool.loadingPool) { + if (!pool) { inputError = inputError ?? 'Pool Info Loading' } - if (pool && JSBI.equal(pool.lpTotalSupply, JSBI.BigInt('0'))) { + if (pool && JSBI.equal(pool.lpTotalSupply.raw, JSBI.BigInt('0'))) { inputError = inputError ?? 'Insufficient Liquidity' } @@ -206,9 +205,8 @@ export function useMobiusTradeInfo(): { !outputCurrency || !parsedAmount || !pool || - !mathUtil || poolsLoading || - JSBI.equal(pool.lpTotalSupply, JSBI.BigInt('0')) + JSBI.equal(pool.lpTotalSupply.raw, JSBI.BigInt('0')) ) { return { currencies, @@ -218,21 +216,14 @@ export function useMobiusTradeInfo(): { v2Trade: undefined, } } - const { tokens = [] } = pool || {} + const tokens = pool.reserves.map(({ token }) => token) const indexFrom = inputCurrency ? tokens.map(({ address }) => address).indexOf(inputCurrency.address) : 0 const indexTo = outputCurrency ? tokens.map(({ address }) => address).indexOf(outputCurrency.address) : 0 - const tradeData = calcInputOutput(inputCurrency, outputCurrency, isExactIn, parsedAmount, mathUtil, pool) + const tradeData = calcInputOutput(inputCurrency, outputCurrency, isExactIn, parsedAmount, pool) - const basisTrade = calcInputOutput( - inputCurrency, - outputCurrency, - isExactIn, - tryParseAmount('1', inputCurrency), - mathUtil, - pool - ) + const basisTrade = calcInputOutput(inputCurrency, outputCurrency, isExactIn, tryParseAmount('1', inputCurrency), pool) const input = tradeData[0] const output = tradeData[1] const fee = tradeData[2] From f6fe0ebc938b958987099286d5b24f2de1787625 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 22 Feb 2022 17:10:08 -0500 Subject: [PATCH 07/72] change swap hooks --- src/state/swap/hooks.ts | 36 +++++++++++++---------------------- src/utils/calculator/price.ts | 10 +++++----- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/state/swap/hooks.ts b/src/state/swap/hooks.ts index 417ed33593c..d66a038ba7c 100644 --- a/src/state/swap/hooks.ts +++ b/src/state/swap/hooks.ts @@ -1,11 +1,10 @@ import { parseUnits } from '@ethersproject/units' import { JSBI, Percent, Price, Token, TokenAmount, TradeType } from '@ubeswap/sdk' +import { IExchangeInfo } from 'constants/pools' import { useCallback } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useCurrentPool, usePools } from 'state/mobiusPools/hooks' -import { StableSwapPool } from 'state/stablePools/reducer' import invariant from 'tiny-invariant' -import { StableSwapMath } from 'utils/stableSwapMath' import { useWeb3Context } from '../../hooks' import { useCurrency } from '../../hooks/Tokens' @@ -84,7 +83,7 @@ export function tryParseAmount(value?: string, currency?: Token): TokenAmount | export type MobiusTrade = { input: TokenAmount output: TokenAmount - pool: StableSwapPool + pool: IExchangeInfo indexFrom: number indexTo: number executionPrice: Price @@ -96,15 +95,13 @@ export type MobiusTrade = { function calcInputOutput( input: Token | undefined, output: Token | undefined, - isExactIn: boolean, parsedAmount: TokenAmount | undefined, - math: StableSwapMath, - poolInfo: StableSwapPool + poolInfo: IExchangeInfo ): readonly [TokenAmount | undefined, TokenAmount | undefined, TokenAmount | undefined] { if (!input && !output) { return [undefined, undefined, undefined] } - const { tokens } = poolInfo + const tokens = poolInfo.reserves.map(({ token }) => token) if (!output) { return [parsedAmount, undefined, undefined] } @@ -122,17 +119,12 @@ function calcInputOutput( ] invariant(parsedAmount) - if (isExactIn) { - details[0] = parsedAmount - const [expectedOut, fee] = math.calculateSwap(indexFrom, indexTo, parsedAmount.raw, math.calc_xp()) - details[1] = new TokenAmount(output, expectedOut) - details[2] = new TokenAmount(input, fee) - } else { - details[1] = parsedAmount - const requiredIn = math.get_dx(indexFrom, indexTo, parsedAmount.raw, math.calc_xp()) - details[0] = new TokenAmount(input, requiredIn) - details[2] = new TokenAmount(input, JSBI.BigInt('0')) - } + + details[0] = parsedAmount + const [expectedOut, fee] = math.calculateSwap(indexFrom, indexTo, parsedAmount.raw, math.calc_xp()) + details[1] = new TokenAmount(output, expectedOut) + details[2] = new TokenAmount(input, fee) + return details } @@ -146,7 +138,6 @@ export function useMobiusTradeInfo(): { const { address, connected } = useWeb3Context() const { - independentField, typedValue, [Field.INPUT]: { currencyId: inputCurrencyId }, [Field.OUTPUT]: { currencyId: outputCurrencyId }, @@ -164,8 +155,7 @@ export function useMobiusTradeInfo(): { outputCurrency ?? undefined, ]) - const isExactIn: boolean = independentField === Field.INPUT - const parsedAmount = tryParseAmount(typedValue, (isExactIn ? inputCurrency : outputCurrency) ?? undefined) + const parsedAmount = tryParseAmount(typedValue, inputCurrency ?? undefined) const currencyBalances = { [Field.INPUT]: relevantTokenBalances[0], @@ -221,9 +211,9 @@ export function useMobiusTradeInfo(): { const indexFrom = inputCurrency ? tokens.map(({ address }) => address).indexOf(inputCurrency.address) : 0 const indexTo = outputCurrency ? tokens.map(({ address }) => address).indexOf(outputCurrency.address) : 0 - const tradeData = calcInputOutput(inputCurrency, outputCurrency, isExactIn, parsedAmount, pool) + const tradeData = calcInputOutput(inputCurrency, outputCurrency, parsedAmount, pool) - const basisTrade = calcInputOutput(inputCurrency, outputCurrency, isExactIn, tryParseAmount('1', inputCurrency), pool) + const basisTrade = calcInputOutput(inputCurrency, outputCurrency, tryParseAmount('1', inputCurrency), pool) const input = tradeData[0] const output = tradeData[1] const fee = tradeData[2] diff --git a/src/utils/calculator/price.ts b/src/utils/calculator/price.ts index d634789865f..ab3beca79d5 100644 --- a/src/utils/calculator/price.ts +++ b/src/utils/calculator/price.ts @@ -1,8 +1,8 @@ -import { Price, TokenAmount } from '@saberhq/token-utils' +import { Price, TokenAmount } from '@ubeswap/sdk' import BN from 'bn.js' -import type { IExchangeInfo } from '..' -import { calculateEstimatedSwapOutputAmount } from '..' +import type { IExchangeInfo } from '../../constants/pools' +import { calculateEstimatedSwapOutputAmount } from './' /** * Gets the price of the second token in the swap, i.e. "Token 1", with respect to "Token 0". @@ -11,8 +11,8 @@ import { calculateEstimatedSwapOutputAmount } from '..' * @returns */ export const calculateSwapPrice = (exchangeInfo: IExchangeInfo): Price => { - const reserve0 = exchangeInfo.reserves[0].amount - const reserve1 = exchangeInfo.reserves[1].amount + const reserve0 = exchangeInfo.reserves[0] + const reserve1 = exchangeInfo.reserves[1] // We try to get at least 4 decimal points of precision here // Otherwise, we attempt to swap 1% of total supply of the pool From 44ea8ea67ccfabcac71aba11dbbc6a7c4e23eb49 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 22 Feb 2022 17:13:23 -0500 Subject: [PATCH 08/72] remove deprecated hooks from --- src/pages/Charts/index.tsx | 25 +----------------------- src/state/stablePools/hooks.ts | 35 +--------------------------------- 2 files changed, 2 insertions(+), 58 deletions(-) diff --git a/src/pages/Charts/index.tsx b/src/pages/Charts/index.tsx index f349470db2c..b21594fe01b 100644 --- a/src/pages/Charts/index.tsx +++ b/src/pages/Charts/index.tsx @@ -10,34 +10,11 @@ import useTheme from 'hooks/useTheme' import { useWindowSize } from 'hooks/useWindowSize' import React, { useState } from 'react' import { isMobile } from 'react-device-detect' -import { usePools } from 'state/stablePools/hooks' +import { usePools } from 'state/mobiusPools/hooks' import { StableSwapPool } from 'state/stablePools/reducer' import styled from 'styled-components' import { Sel, TYPE } from 'theme' -const TextContainer = styled.div` - width: 100%; - display: flex; - flex-wrap: wrap; - margin-left: auto; - margin-right: auto; - justify-content: center; -` - -const PositionsContainer = styled.div` - width: 100%; - display: flex; - justify-content: space-between; - flex-wrap: wrap; - display: flex; - align-items: flex-start; - justify-content: center; - ${({ theme }) => theme.mediaWidth.upToSmall` - width: 100%; - `} - flex-wrap: wrap; -` - const OuterContainer = styled.div` width: min(1280px, 100%); margin-top: ${!isMobile ? '3rem' : '-1rem'}; diff --git a/src/state/stablePools/hooks.ts b/src/state/stablePools/hooks.ts index 365f0f6d228..777a2f83d87 100644 --- a/src/state/stablePools/hooks.ts +++ b/src/state/stablePools/hooks.ts @@ -14,7 +14,7 @@ import invariant from 'tiny-invariant' import WARNINGS from '../../constants/PoolWarnings.json' import { StableSwapMath } from '../../utils/stableSwapMath' import { AppState } from '..' -import { StableSwapConstants, StableSwapPool, WarningType } from './reducer' +import { StableSwapPool, WarningType } from './reducer' import { BigIntToJSBI } from './updater' export type WarningModifications = 'require-equal-deposit' | 'none' @@ -55,31 +55,6 @@ export interface StablePoolInfo { readonly isKilled?: boolean } -export function useCurrentPool(tok1: string, tok2: string): readonly [StableSwapPool | undefined] { - const withMetaPools = useSelector((state) => - Object.values(state.stablePools.pools).map(({ pool }) => { - if (!pool.metaPool || pool.disabled) return pool - const underlying = state.stablePools.pools[pool.metaPool]?.pool - return { - ...pool, - tokenAddresses: pool.tokenAddresses.concat(underlying.tokenAddresses), - } - }) - ) - const pools = withMetaPools.filter(({ tokenAddresses }) => { - return tokenAddresses.includes(tok1) && tokenAddresses.includes(tok2) - }) - - return [pools.length > 0 ? pools[0] : null] -} - -export function usePools(): readonly StableSwapPool[] { - const pools = useSelector((state) => - Object.values(state.stablePools.pools).map(({ pool }) => pool) - ) - return pools -} - const tokenAmountScaled = (token: Token, amount: JSBI): TokenAmount => new TokenAmount(token, JSBI.divide(amount, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt(token.decimals)))) @@ -213,14 +188,6 @@ export function useMathUtil(pool: StableSwapPool | string): StableSwapMath | und return math } -export function usePool(): readonly [StableSwapPool] { - const [tok1, tok2] = useSelector((state) => [ - state.swap.INPUT.currencyId, - state.swap.OUTPUT.currencyId, - ]) - return useCurrentPool(tok1, tok2) -} - export function usePriceOfLp(address: string, amountOfLp: TokenAmount): TokenAmount | undefined { const pool = useStablePoolInfoByName(address) const price = useEthBtcPrice(pool?.poolAddress ?? '') From 484c3b4f69d6e15d46270f33c75257d8aee55a24 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 24 Feb 2022 10:30:57 -0500 Subject: [PATCH 09/72] fix all calculator errors --- package.json | 2 + src/{utils => lib}/calculator/amounts.ts | 88 +++++++------------ .../calculator/amounts.unit.test.ts | 0 src/{utils => lib}/calculator/curve.ts | 4 +- .../calculator/curve.unit.test.ts | 0 src/{utils => lib}/calculator/index.ts | 0 src/{utils => lib}/calculator/price.ts | 11 +-- src/{utils => lib}/mentoCalculator/amounts.ts | 0 src/{utils => lib}/mentoCalculator/index.ts | 0 src/{utils => lib}/mentoCalculator/price.ts | 0 src/state/mento/hooks.ts | 8 +- yarn.lock | 12 +++ 12 files changed, 59 insertions(+), 66 deletions(-) rename src/{utils => lib}/calculator/amounts.ts (73%) rename src/{utils => lib}/calculator/amounts.unit.test.ts (100%) rename src/{utils => lib}/calculator/curve.ts (97%) rename src/{utils => lib}/calculator/curve.unit.test.ts (100%) rename src/{utils => lib}/calculator/index.ts (100%) rename src/{utils => lib}/calculator/price.ts (74%) rename src/{utils => lib}/mentoCalculator/amounts.ts (100%) rename src/{utils => lib}/mentoCalculator/index.ts (100%) rename src/{utils => lib}/mentoCalculator/price.ts (100%) diff --git a/package.json b/package.json index 02045eb63ca..750e842f016 100644 --- a/package.json +++ b/package.json @@ -132,6 +132,7 @@ "@ethersproject/units": "^5.3.0", "@sentry/react": "^6.9.0", "@sentry/tracing": "^6.9.0", + "@types/lodash.mapvalues": "^4.6.6", "@types/react-date-range": "^1.1.8", "@types/react-vis": "^1.11.7", "@ubeswap/default-token-list": "^4.0.29", @@ -143,6 +144,7 @@ "graphql": "^15.7.1", "jsbi": "^3.1.5", "lodash": "^4.17.21", + "lodash.mapvalues": "^4.6.0", "randombytes": "^2.1.0", "react-circular-progressbar": "^2.0.4", "react-date-range": "^1.4.0", diff --git a/src/utils/calculator/amounts.ts b/src/lib/calculator/amounts.ts similarity index 73% rename from src/utils/calculator/amounts.ts rename to src/lib/calculator/amounts.ts index 85e164ba2c7..a54f37a0af6 100644 --- a/src/utils/calculator/amounts.ts +++ b/src/lib/calculator/amounts.ts @@ -1,12 +1,13 @@ -import type { Token } from '@saberhq/token-utils' -import { Fraction, ONE, TokenAmount, ZERO } from '@saberhq/token-utils' +import { Fraction, Token, TokenAmount } from '@ubeswap/sdk' import JSBI from 'jsbi' import mapValues from 'lodash.mapvalues' -import type { IExchangeInfo } from '../entities/exchange' -import type { Fees } from '../state/fees' +import type { Fees, IExchangeInfo } from '../../constants/pools' import { computeD, computeY } from './curve' +const ZERO = JSBI.BigInt(0) +const ONE = JSBI.BigInt(1) + /** * Calculates the current virtual price of the exchange. * @param exchange @@ -14,12 +15,12 @@ import { computeD, computeY } from './curve' */ export const calculateVirtualPrice = (exchange: IExchangeInfo): Fraction | null => { const amount = exchange.lpTotalSupply - if (amount === undefined || amount.equalTo(0)) { + if (amount === undefined || amount.equalTo('0')) { // pool has no tokens return null } const price = new Fraction( - computeD(exchange.ampFactor, exchange.reserves[0].amount.raw, exchange.reserves[1].amount.raw), + computeD(exchange.ampFactor, exchange.reserves[0].raw, exchange.reserves[1].raw), amount.raw ) return price @@ -37,12 +38,12 @@ export const calculateEstimatedSwapOutputAmount = ( ): { [K in 'outputAmountBeforeFees' | 'outputAmount' | 'fee' | 'lpFee' | 'adminFee']: TokenAmount } => { - const [fromReserves, toReserves] = fromAmount.token.equals(exchange.reserves[0].amount.token) + const [fromReserves, toReserves] = fromAmount.token.equals(exchange.reserves[0].token) ? [exchange.reserves[0], exchange.reserves[1]] : [exchange.reserves[1], exchange.reserves[0]] - if (fromAmount.equalTo(0)) { - const zero = new TokenAmount(toReserves.amount.token, ZERO) + if (fromAmount.equalTo('0')) { + const zero = new TokenAmount(toReserves.token, ZERO) return { outputAmountBeforeFees: zero, outputAmount: zero, @@ -55,28 +56,18 @@ export const calculateEstimatedSwapOutputAmount = ( const amp = exchange.ampFactor const amountBeforeFees = JSBI.subtract( - toReserves.amount.raw, - computeY( - amp, - JSBI.add(fromReserves.amount.raw, fromAmount.raw), - computeD(amp, fromReserves.amount.raw, toReserves.amount.raw) - ) + toReserves.raw, + computeY(amp, JSBI.add(fromReserves.raw, fromAmount.raw), computeD(amp, fromReserves.raw, toReserves.raw)) ) - const outputAmountBeforeFees = new TokenAmount(toReserves.amount.token, amountBeforeFees) + const outputAmountBeforeFees = new TokenAmount(toReserves.token, amountBeforeFees) - const fee = new TokenAmount( - toReserves.amount.token, - exchange.fees.trade.asFraction.multiply(amountBeforeFees).toFixed(0) - ) + const fee = new TokenAmount(toReserves.token, exchange.fees.trade.multiply(amountBeforeFees).toFixed(0)) - const adminFee = new TokenAmount( - toReserves.amount.token, - exchange.fees.adminTrade.asFraction.multiply(fee.raw).toFixed(0) - ) + const adminFee = new TokenAmount(toReserves.token, exchange.fees.admin.multiply(fee.raw).toFixed(0)) const lpFee = fee.subtract(adminFee) - const outputAmount = new TokenAmount(toReserves.amount.token, JSBI.subtract(amountBeforeFees, fee.raw)) + const outputAmount = new TokenAmount(toReserves.token, JSBI.subtract(amountBeforeFees, fee.raw)) return { outputAmountBeforeFees, @@ -95,9 +86,7 @@ export interface IWithdrawOneResult { swapFee: TokenAmount withdrawFee: TokenAmount lpSwapFee: TokenAmount - lpWithdrawFee: TokenAmount adminSwapFee: TokenAmount - adminWithdrawFee: TokenAmount } /** @@ -113,7 +102,7 @@ export const calculateEstimatedWithdrawOneAmount = ({ poolTokenAmount: TokenAmount withdrawToken: Token }): IWithdrawOneResult => { - if (poolTokenAmount.equalTo(0)) { + if (poolTokenAmount.equalTo('0')) { // final quantities const quantities = { withdrawAmount: ZERO, @@ -121,9 +110,7 @@ export const calculateEstimatedWithdrawOneAmount = ({ swapFee: ZERO, withdrawFee: ZERO, lpSwapFee: ZERO, - lpWithdrawFee: ZERO, adminSwapFee: ZERO, - adminWithdrawFee: ZERO, } return mapValues(quantities, (q) => new TokenAmount(withdrawToken, q)) } @@ -131,8 +118,8 @@ export const calculateEstimatedWithdrawOneAmount = ({ const { ampFactor, fees } = exchange const [baseReserves, quoteReserves] = [ - exchange.reserves.find((r) => r.amount.token.equals(withdrawToken))?.amount.raw ?? ZERO, - exchange.reserves.find((r) => !r.amount.token.equals(withdrawToken))?.amount.raw ?? ZERO, + exchange.reserves.find((r) => r.token.equals(withdrawToken))?.raw ?? ZERO, + exchange.reserves.find((r) => !r.token.equals(withdrawToken))?.raw ?? ZERO, ] const d_0 = computeD(ampFactor, baseReserves, quoteReserves) @@ -145,27 +132,25 @@ export const calculateEstimatedWithdrawOneAmount = ({ // expected_quote_amount = swap_quote_amount - swap_quote_amount * d_1 / d_0; const expected_quote_amount = JSBI.subtract(quoteReserves, JSBI.divide(JSBI.multiply(quoteReserves, d_1), d_0)) // new_base_amount = swap_base_amount - expected_base_amount * fee / fee_denominator; - const new_base_amount = new Fraction(baseReserves.toString(), 1).subtract( + const new_base_amount = new Fraction(baseReserves.toString(), '1').subtract( normalizedTradeFee(fees, N_COINS, expected_base_amount) ) // new_quote_amount = swap_quote_amount - expected_quote_amount * fee / fee_denominator; - const new_quote_amount = new Fraction(quoteReserves.toString(), 1).subtract( + const new_quote_amount = new Fraction(quoteReserves.toString(), '1').subtract( normalizedTradeFee(fees, N_COINS, expected_quote_amount) ) const dy = new_base_amount.subtract(computeY(ampFactor, JSBI.BigInt(new_quote_amount.toFixed(0)), d_1).toString()) const dy_0 = JSBI.subtract(baseReserves, new_y) // lp fees - const swapFee = new Fraction(dy_0.toString(), 1).subtract(dy) - const withdrawFee = dy.multiply(fees.withdraw.asFraction) + const swapFee = new Fraction(dy_0.toString(), '1').subtract(dy) + const withdrawFee = dy.multiply(fees.withdraw) // admin fees - const adminSwapFee = swapFee.multiply(fees.adminTrade.asFraction) - const adminWithdrawFee = withdrawFee.multiply(fees.adminWithdraw.asFraction) + const adminSwapFee = swapFee.multiply(fees.admin) // final LP fees const lpSwapFee = swapFee.subtract(adminSwapFee) - const lpWithdrawFee = withdrawFee.subtract(adminWithdrawFee) // final withdraw amount const withdrawAmount = dy.subtract(withdrawFee).subtract(swapFee) @@ -177,9 +162,7 @@ export const calculateEstimatedWithdrawOneAmount = ({ swapFee, withdrawFee, lpSwapFee, - lpWithdrawFee, adminSwapFee, - adminWithdrawFee, } return mapValues(quantities, (q) => new TokenAmount(withdrawToken, q.toFixed(0))) @@ -190,7 +173,7 @@ export const calculateEstimatedWithdrawOneAmount = ({ */ export const normalizedTradeFee = ({ trade }: Fees, n_coins: JSBI, amount: JSBI): Fraction => { const adjustedTradeFee = new Fraction(n_coins, JSBI.multiply(JSBI.subtract(n_coins, ONE), JSBI.BigInt(4))) - return new Fraction(amount, 1).multiply(trade).multiply(adjustedTradeFee) + return new Fraction(amount, '1').multiply(trade).multiply(adjustedTradeFee) } export const calculateEstimatedWithdrawAmount = ({ @@ -208,8 +191,8 @@ export const calculateEstimatedWithdrawAmount = ({ withdrawAmountsBeforeFees: readonly [TokenAmount, TokenAmount] fees: readonly [TokenAmount, TokenAmount] } => { - if (lpTotalSupply.equalTo(0)) { - const zero = reserves.map((r) => new TokenAmount(r.amount.token, ZERO)) as [TokenAmount, TokenAmount] + if (lpTotalSupply.equalTo('0')) { + const zero = reserves.map((r) => new TokenAmount(r.token, ZERO)) as [TokenAmount, TokenAmount] return { withdrawAmounts: zero, withdrawAmountsBeforeFees: zero, @@ -219,9 +202,9 @@ export const calculateEstimatedWithdrawAmount = ({ const share = poolTokenAmount.divide(lpTotalSupply) - const withdrawAmounts = reserves.map(({ amount }) => { + const withdrawAmounts = reserves.map((amount) => { const baseAmount = share.multiply(amount.raw) - const fee = baseAmount.multiply(fees.withdraw.asFraction) + const fee = baseAmount.multiply(fees.withdraw) return [ new TokenAmount(amount.token, JSBI.BigInt(baseAmount.subtract(fee).toFixed(0))), { @@ -267,23 +250,20 @@ export const calculateEstimatedMintAmount = ( const amp = exchange.ampFactor const [reserveA, reserveB] = exchange.reserves - const d0 = computeD(amp, reserveA.amount.raw, reserveB.amount.raw) + const d0 = computeD(amp, reserveA.raw, reserveB.raw) - const d1 = computeD(amp, JSBI.add(reserveA.amount.raw, depositAmountA), JSBI.add(reserveB.amount.raw, depositAmountB)) + const d1 = computeD(amp, JSBI.add(reserveA.raw, depositAmountA), JSBI.add(reserveB.raw, depositAmountB)) if (JSBI.lessThan(d1, d0)) { throw new Error('New D cannot be less than previous D') } - const oldBalances = exchange.reserves.map((r) => r.amount.raw) as [JSBI, JSBI] - const newBalances = [ - JSBI.add(reserveA.amount.raw, depositAmountA), - JSBI.add(reserveB.amount.raw, depositAmountB), - ] as const + const oldBalances = exchange.reserves.map((r) => r.raw) as [JSBI, JSBI] + const newBalances = [JSBI.add(reserveA.raw, depositAmountA), JSBI.add(reserveB.raw, depositAmountB)] as const const adjustedBalances = newBalances.map((newBalance, i) => { const oldBalance = oldBalances[i] as JSBI const idealBalance = new Fraction(d1, d0).multiply(oldBalance) const difference = idealBalance.subtract(newBalance) - const diffAbs = difference.greaterThan(0) ? difference : difference.multiply(-1) + const diffAbs = difference.greaterThan('0') ? difference : difference.multiply('-1') const fee = normalizedTradeFee(exchange.fees, N_COINS, JSBI.BigInt(diffAbs.toFixed(0))) return JSBI.subtract(newBalance, JSBI.BigInt(fee.toFixed(0))) }) as [JSBI, JSBI] diff --git a/src/utils/calculator/amounts.unit.test.ts b/src/lib/calculator/amounts.unit.test.ts similarity index 100% rename from src/utils/calculator/amounts.unit.test.ts rename to src/lib/calculator/amounts.unit.test.ts diff --git a/src/utils/calculator/curve.ts b/src/lib/calculator/curve.ts similarity index 97% rename from src/utils/calculator/curve.ts rename to src/lib/calculator/curve.ts index 54eb9a8849e..24f953e6471 100644 --- a/src/utils/calculator/curve.ts +++ b/src/lib/calculator/curve.ts @@ -1,6 +1,8 @@ -import { ONE, ZERO } from '@saberhq/token-utils' import JSBI from 'jsbi' +const ZERO = JSBI.BigInt(0) +const ONE = JSBI.BigInt(1) + const N_COINS = JSBI.BigInt(2) // n const abs = (a: JSBI): JSBI => { diff --git a/src/utils/calculator/curve.unit.test.ts b/src/lib/calculator/curve.unit.test.ts similarity index 100% rename from src/utils/calculator/curve.unit.test.ts rename to src/lib/calculator/curve.unit.test.ts diff --git a/src/utils/calculator/index.ts b/src/lib/calculator/index.ts similarity index 100% rename from src/utils/calculator/index.ts rename to src/lib/calculator/index.ts diff --git a/src/utils/calculator/price.ts b/src/lib/calculator/price.ts similarity index 74% rename from src/utils/calculator/price.ts rename to src/lib/calculator/price.ts index ab3beca79d5..3193b9b0959 100644 --- a/src/utils/calculator/price.ts +++ b/src/lib/calculator/price.ts @@ -1,8 +1,7 @@ import { Price, TokenAmount } from '@ubeswap/sdk' -import BN from 'bn.js' import type { IExchangeInfo } from '../../constants/pools' -import { calculateEstimatedSwapOutputAmount } from './' +import { calculateEstimatedSwapOutputAmount } from '.' /** * Gets the price of the second token in the swap, i.e. "Token 1", with respect to "Token 0". @@ -19,13 +18,11 @@ export const calculateSwapPrice = (exchangeInfo: IExchangeInfo): Price => { // or at most, $1 const inputAmountNum = Math.max( 10_000, - Math.min(10 ** reserve0.token.decimals, Math.floor(parseInt(reserve0.toU64().div(new BN(100)).toString()))) + Math.min(10 ** reserve0.token.decimals, Math.floor(parseInt(reserve0.divide('100').toString()))) ) - const inputAmount = new TokenAmount(reserve0.token, inputAmountNum) + const inputAmount = new TokenAmount(reserve0.token, inputAmountNum.toString()) const outputAmount = calculateEstimatedSwapOutputAmount(exchangeInfo, inputAmount) - const frac = outputAmount.outputAmountBeforeFees.asFraction.divide(inputAmount.asFraction) - - return new Price(reserve0.token, reserve1.token, frac.denominator, frac.numerator) + return new Price(reserve0.token, reserve1.token, outputAmount.outputAmountBeforeFees.raw, inputAmount.raw) } diff --git a/src/utils/mentoCalculator/amounts.ts b/src/lib/mentoCalculator/amounts.ts similarity index 100% rename from src/utils/mentoCalculator/amounts.ts rename to src/lib/mentoCalculator/amounts.ts diff --git a/src/utils/mentoCalculator/index.ts b/src/lib/mentoCalculator/index.ts similarity index 100% rename from src/utils/mentoCalculator/index.ts rename to src/lib/mentoCalculator/index.ts diff --git a/src/utils/mentoCalculator/price.ts b/src/lib/mentoCalculator/price.ts similarity index 100% rename from src/utils/mentoCalculator/price.ts rename to src/lib/mentoCalculator/price.ts diff --git a/src/state/mento/hooks.ts b/src/state/mento/hooks.ts index 7031829e9f7..a1a7d99fb21 100644 --- a/src/state/mento/hooks.ts +++ b/src/state/mento/hooks.ts @@ -2,14 +2,14 @@ import { parseUnits } from '@ethersproject/units' import { JSBI, Percent, Price, Token, TokenAmount, TradeType } from '@ubeswap/sdk' import { IMentoExchangeInfo } from 'constants/mento' import { CELO } from 'constants/tokens' -import { useCallback } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import invariant from 'tiny-invariant' import { calculateEstimatedSwapInputAmount, calculateEstimatedSwapOutputAmount, calculateSwapPrice, -} from 'utils/mentoCalculator' +} from 'lib/mentoCalculator' +import { useCallback } from 'react' +import { useDispatch, useSelector } from 'react-redux' +import invariant from 'tiny-invariant' import { BIPS_BASE, CHAIN } from '../../constants' import { useWeb3Context } from '../../hooks' diff --git a/yarn.lock b/yarn.lock index d6b097cf6f6..f8cb591202c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2892,6 +2892,13 @@ dependencies: "@types/lodash" "*" +"@types/lodash.mapvalues@^4.6.6": + version "4.6.6" + resolved "https://registry.yarnpkg.com/@types/lodash.mapvalues/-/lodash.mapvalues-4.6.6.tgz#899b6e1d3b9b4e313bc332ec18182f9fce7aec7c" + integrity sha512-Mt9eg3AqwAt5HShuOu8taiIYg0sLl4w3vDi0++E0VtiOtj9DqQHaxVr3wicVop0eDEqr5ENbht7vsLJlkMHL+w== + dependencies: + "@types/lodash" "*" + "@types/lodash@*", "@types/lodash@^4.14.170", "@types/lodash@^4.14.53": version "4.14.178" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8" @@ -10452,6 +10459,11 @@ lodash.flatmap@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" integrity sha1-74y/QI9uSCaGYzRTBcaswLd4cC4= +lodash.mapvalues@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" + integrity sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw= + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" From 8affecbcd73ba6cd9507d48cf6061cd6c8b3c006 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 24 Feb 2022 11:14:49 -0500 Subject: [PATCH 10/72] still issues with pulling data --- src/lib/calculator/amounts.unit.test.ts | 275 ------------------------ src/lib/calculator/curve.unit.test.ts | 45 ---- src/state/swap/hooks.ts | 18 +- src/state/swap/reducer.ts | 3 - 4 files changed, 8 insertions(+), 333 deletions(-) delete mode 100644 src/lib/calculator/amounts.unit.test.ts delete mode 100644 src/lib/calculator/curve.unit.test.ts diff --git a/src/lib/calculator/amounts.unit.test.ts b/src/lib/calculator/amounts.unit.test.ts deleted file mode 100644 index b85ad71a799..00000000000 --- a/src/lib/calculator/amounts.unit.test.ts +++ /dev/null @@ -1,275 +0,0 @@ -import type { BigintIsh } from '@saberhq/token-utils' -import { Percent, Token as SToken, TokenAmount } from '@saberhq/token-utils' -import { PublicKey } from '@solana/web3.js' -import BN from 'bn.js' -import JSBI from 'jsbi' -import mapValues from 'lodash.mapvalues' - -import { SWAP_PROGRAM_ID } from '../constants' -import type { IExchangeInfo } from '../entities/exchange' -import { RECOMMENDED_FEES, ZERO_FEES } from '../state/fees' -import { - calculateEstimatedMintAmount, - calculateEstimatedSwapOutputAmount, - calculateEstimatedWithdrawAmount, - calculateEstimatedWithdrawOneAmount, - calculateVirtualPrice, -} from './amounts' - -const exchange = { - swapAccount: new PublicKey('YAkoNb6HKmSxQN9L8hiBE5tPJRsniSSMzND1boHmZxe'), - programID: SWAP_PROGRAM_ID, - lpToken: new SToken({ - symbol: 'LP', - name: 'StableSwap LP', - address: '2poo1w1DL6yd2WNTCnNTzDqkC6MBXq7axo77P16yrBuf', - decimals: 6, - chainId: 100, - }), - tokens: [ - new SToken({ - symbol: 'TOKA', - name: 'Token A', - address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', - decimals: 6, - chainId: 100, - }), - new SToken({ - symbol: 'TOKB', - name: 'Token B', - address: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', - decimals: 6, - chainId: 100, - }), - ], -} as const - -const makeExchangeInfo = ( - { - lpTotalSupply = JSBI.BigInt(200_000_000), - tokenAAmount = JSBI.BigInt(100_000_000), - tokenBAmount = JSBI.BigInt(100_000_000), - }: { - lpTotalSupply?: JSBI - tokenAAmount?: JSBI - tokenBAmount?: JSBI - } = { - lpTotalSupply: JSBI.BigInt(200_000_000), - tokenAAmount: JSBI.BigInt(100_000_000), - tokenBAmount: JSBI.BigInt(100_000_000), - } -): IExchangeInfo => ({ - ampFactor: JSBI.BigInt(100), - fees: ZERO_FEES, - lpTotalSupply: new TokenAmount(exchange.lpToken, lpTotalSupply), - reserves: [ - { - reserveAccount: new PublicKey('Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'), - adminFeeAccount: new PublicKey('Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'), - amount: new TokenAmount(exchange.tokens[0], tokenAAmount), - }, - { - reserveAccount: new PublicKey('Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'), - adminFeeAccount: new PublicKey('Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'), - amount: new TokenAmount(exchange.tokens[1], tokenBAmount), - }, - ], -}) - -const exchangeInfo = makeExchangeInfo() - -const exchangeInfoWithFees = { - ...exchangeInfo, - fees: RECOMMENDED_FEES, -} as const - -const assertTokenAmounts = (actual: TokenAmount, expected: TokenAmount) => { - expect(actual.equalTo(expected) && actual.token.equals(expected.token)).toBe(true) -} - -const assertTokenAmount = (actual: TokenAmount, expected: BigintIsh) => { - expect(actual.raw.toString()).toEqual(expected.toString()) -} - -describe('Calculated amounts', () => { - describe('#calculateVirtualPrice', () => { - it('works', () => { - const result = calculateVirtualPrice(exchangeInfo) - expect(result?.toFixed(4)).toBe('1.0000') - }) - - it('is symmetric', () => { - const result = calculateVirtualPrice( - makeExchangeInfo({ - lpTotalSupply: JSBI.BigInt(200_000_000), - tokenAAmount: JSBI.BigInt(10_000_000), - tokenBAmount: JSBI.BigInt(190_000_000), - }) - ) - expect(result?.toFixed(4)).toBe('0.9801') - - const result2 = calculateVirtualPrice( - makeExchangeInfo({ - lpTotalSupply: JSBI.BigInt(200_000_000), - tokenAAmount: JSBI.BigInt(190_000_000), - tokenBAmount: JSBI.BigInt(10_000_000), - }) - ) - expect(result2?.toFixed(4)).toBe('0.9801') - }) - - it('can quote both prices', () => { - const exchange = makeExchangeInfo({ - lpTotalSupply: JSBI.BigInt(200_000_000), - tokenAAmount: JSBI.BigInt(10_000_000), - tokenBAmount: JSBI.BigInt(190_000_000), - }) - - const result = calculateVirtualPrice(exchange) - expect(result?.toFixed(4)).toBe('0.9801') - }) - }) - - describe('#calculateEstimatedSwapOutputAmount', () => { - it('no fees', () => { - const result = calculateEstimatedSwapOutputAmount( - exchangeInfo, - new TokenAmount(exchange.tokens[0], JSBI.BigInt(10_000_000)) - ) - - assertTokenAmounts(result.outputAmount, result.outputAmountBeforeFees) - }) - - it('fees are different', () => { - const result = calculateEstimatedSwapOutputAmount( - { - ...exchangeInfoWithFees, - fees: { - ...exchangeInfoWithFees.fees, - trade: new Percent(50, 100), - }, - }, - new TokenAmount(exchange.tokens[0], JSBI.BigInt(100)) - ) - - // 50 percent fee - assertTokenAmount(result.outputAmountBeforeFees, JSBI.BigInt(100)) - assertTokenAmount(result.outputAmount, JSBI.BigInt(50)) - }) - }) - - describe('#calculateEstimatedMintAmount', () => { - it('no fees if equal liquidity provision', () => { - const result = calculateEstimatedMintAmount( - { - ...exchangeInfo, - fees: { - ...ZERO_FEES, - trade: new Percent(50, 100), - }, - }, - JSBI.BigInt(100), - JSBI.BigInt(100) - ) - - assertTokenAmounts(result.mintAmount, result.mintAmountBeforeFees) - }) - - it('fees if unequal liquidity provision', () => { - const result = calculateEstimatedMintAmount( - { - ...exchangeInfo, - fees: { - ...ZERO_FEES, - trade: new Percent(50, 100), - }, - }, - JSBI.BigInt(100_000), - JSBI.BigInt(0) - ) - - assertTokenAmount(result.mintAmountBeforeFees, new BN(99_999)) - // 3/4 because only half of the swapped amount (100 tokens) should have fees on it (so 1/4) - const expectedMintAmount = JSBI.divide( - JSBI.multiply(result.mintAmountBeforeFees.raw, JSBI.BigInt(3)), - JSBI.BigInt(4) - ) - assertTokenAmount(result.mintAmount, expectedMintAmount) - - assertTokenAmount(result.fees, JSBI.subtract(result.mintAmountBeforeFees.raw, expectedMintAmount)) - }) - }) - - describe('#calculateEstimatedWithdrawAmount', () => { - it('works', () => { - calculateEstimatedWithdrawAmount({ - ...exchangeInfo, - poolTokenAmount: new TokenAmount(exchange.lpToken, 100_000), - }) - }) - - it('works with fees', () => { - calculateEstimatedWithdrawAmount({ - ...exchangeInfoWithFees, - poolTokenAmount: new TokenAmount(exchange.lpToken, 100_000), - }) - }) - - it('works zero with fees', () => { - calculateEstimatedWithdrawAmount({ - ...exchangeInfoWithFees, - poolTokenAmount: new TokenAmount(exchange.lpToken, 0), - }) - }) - }) - - describe('#calculateEstimatedWithdrawOneAmount', () => { - it('works', () => { - calculateEstimatedWithdrawOneAmount({ - exchange: exchangeInfo, - poolTokenAmount: new TokenAmount(exchange.lpToken, 100_000), - withdrawToken: exchange.tokens[0], - }) - }) - - it('works with fees', () => { - const result = calculateEstimatedWithdrawOneAmount({ - exchange: exchangeInfoWithFees, - poolTokenAmount: new TokenAmount(exchange.lpToken, 100_000), - withdrawToken: exchange.tokens[0], - }) - - const resultMapped = mapValues(result, (q) => q.raw.toString()) - expect(resultMapped).toEqual({ - withdrawAmount: '99301', - withdrawAmountBeforeFees: '99900', - swapFee: '100', - withdrawFee: '500', - lpSwapFee: '50', - lpWithdrawFee: '250', - adminSwapFee: '50', - adminWithdrawFee: '250', - }) - }) - - it('works zero with fees', () => { - const result = calculateEstimatedWithdrawOneAmount({ - exchange: exchangeInfoWithFees, - poolTokenAmount: new TokenAmount(exchange.lpToken, 0), - withdrawToken: exchange.tokens[0], - }) - - const resultMapped = mapValues(result, (q) => q.raw.toString()) - expect(resultMapped).toEqual({ - withdrawAmount: '0', - withdrawAmountBeforeFees: '0', - swapFee: '0', - withdrawFee: '0', - lpSwapFee: '0', - lpWithdrawFee: '0', - adminSwapFee: '0', - adminWithdrawFee: '0', - }) - }) - }) -}) diff --git a/src/lib/calculator/curve.unit.test.ts b/src/lib/calculator/curve.unit.test.ts deleted file mode 100644 index 8eaf76c653a..00000000000 --- a/src/lib/calculator/curve.unit.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { BigintIsh } from '@saberhq/token-utils' -import JSBI from 'jsbi' - -import { computeD, computeY } from './curve' - -const assertBN = (actual: BigintIsh, expected: BigintIsh) => { - expect(actual.toString()).toEqual(expected.toString()) -} - -describe('Calculator tests', () => { - it('computeD', () => { - assertBN(computeD(JSBI.BigInt(100), JSBI.BigInt(0), JSBI.BigInt(0)), JSBI.BigInt(0)) - assertBN(computeD(JSBI.BigInt(100), JSBI.BigInt(1000000000), JSBI.BigInt(1000000000)), JSBI.BigInt(2000000000)) - assertBN(computeD(JSBI.BigInt(73), JSBI.BigInt(92), JSBI.BigInt(81)), JSBI.BigInt(173)) - assertBN(computeD(JSBI.BigInt(11503), JSBI.BigInt(28338), JSBI.BigInt(78889)), JSBI.BigInt(107225)) - assertBN(computeD(JSBI.BigInt(8552), JSBI.BigInt(26), JSBI.BigInt(69321)), JSBI.BigInt(66920)) - assertBN(computeD(JSBI.BigInt(496), JSBI.BigInt(62), JSBI.BigInt(68567)), JSBI.BigInt(57447)) - assertBN( - computeD( - JSBI.BigInt('17653203515214796177'), - JSBI.BigInt('13789683482691983066'), - JSBI.BigInt('3964443602730479576') - ), - JSBI.BigInt('17754127085422462641') - ) - }) - - it('computeY', () => { - assertBN(computeY(JSBI.BigInt(100), JSBI.BigInt(100), JSBI.BigInt(0)), JSBI.BigInt(0)) - assertBN(computeY(JSBI.BigInt(8), JSBI.BigInt(94), JSBI.BigInt(163)), JSBI.BigInt(69)) - assertBN(computeY(JSBI.BigInt(2137), JSBI.BigInt(905777403660), JSBI.BigInt(830914146046)), JSBI.BigInt(490376033)) - assertBN( - computeY(JSBI.BigInt('17095344176474858097'), JSBI.BigInt(383), JSBI.BigInt('2276818911077272163')), - JSBI.BigInt('2276917873767753112') - ) - assertBN( - computeY( - JSBI.BigInt('7644937799120520965'), - JSBI.BigInt('14818904982296505121'), - JSBI.BigInt('17480022366793075404') - ), - JSBI.BigInt('2661117384496570284') - ) - }) -}) diff --git a/src/state/swap/hooks.ts b/src/state/swap/hooks.ts index d66a038ba7c..3d52c726dab 100644 --- a/src/state/swap/hooks.ts +++ b/src/state/swap/hooks.ts @@ -1,6 +1,7 @@ import { parseUnits } from '@ethersproject/units' import { JSBI, Percent, Price, Token, TokenAmount, TradeType } from '@ubeswap/sdk' import { IExchangeInfo } from 'constants/pools' +import { calculateEstimatedSwapOutputAmount, calculateSwapPrice } from 'lib/calculator' import { useCallback } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useCurrentPool, usePools } from 'state/mobiusPools/hooks' @@ -101,7 +102,6 @@ function calcInputOutput( if (!input && !output) { return [undefined, undefined, undefined] } - const tokens = poolInfo.reserves.map(({ token }) => token) if (!output) { return [parsedAmount, undefined, undefined] } @@ -109,9 +109,6 @@ function calcInputOutput( return [undefined, parsedAmount, undefined] } - const indexFrom = tokens.map(({ address }) => address).indexOf(input.address) - const indexTo = tokens.map(({ address }) => address).indexOf(output.address) - const details: [TokenAmount | undefined, TokenAmount | undefined, TokenAmount | undefined] = [ undefined, undefined, @@ -121,9 +118,9 @@ function calcInputOutput( invariant(parsedAmount) details[0] = parsedAmount - const [expectedOut, fee] = math.calculateSwap(indexFrom, indexTo, parsedAmount.raw, math.calc_xp()) - details[1] = new TokenAmount(output, expectedOut) - details[2] = new TokenAmount(input, fee) + const { fee, outputAmount } = calculateEstimatedSwapOutputAmount(poolInfo, parsedAmount) + details[1] = outputAmount + details[2] = fee return details } @@ -179,6 +176,8 @@ export function useMobiusTradeInfo(): { inputError = inputError ?? 'Pool Info Loading' } + console.log(pool) + if (pool && JSBI.equal(pool.lpTotalSupply.raw, JSBI.BigInt('0'))) { inputError = inputError ?? 'Insufficient Liquidity' } @@ -213,12 +212,12 @@ export function useMobiusTradeInfo(): { const tradeData = calcInputOutput(inputCurrency, outputCurrency, parsedAmount, pool) - const basisTrade = calcInputOutput(inputCurrency, outputCurrency, tryParseAmount('1', inputCurrency), pool) + const basisPrice = calculateSwapPrice(pool) const input = tradeData[0] const output = tradeData[1] const fee = tradeData[2] - if (!input || !output || !fee || !basisTrade[0] || !basisTrade[1]) { + if (!input || !output || !fee || !basisPrice) { return { currencies, currencyBalances, @@ -233,7 +232,6 @@ export function useMobiusTradeInfo(): { } const executionPrice = new Price(inputCurrency, outputCurrency, input?.raw, output?.raw) - const basisPrice = new Price(inputCurrency, outputCurrency, basisTrade[0]?.raw, basisTrade[1]?.raw) const priceImpactFraction = basisPrice.subtract(executionPrice).divide(basisPrice) const priceImpact = new Percent(priceImpactFraction.numerator, priceImpactFraction.denominator) diff --git a/src/state/swap/reducer.ts b/src/state/swap/reducer.ts index 6e277361ee7..5ca841738bd 100644 --- a/src/state/swap/reducer.ts +++ b/src/state/swap/reducer.ts @@ -44,9 +44,6 @@ export default createReducer(initialState, (builder) => if (!!state[Field.INPUT].currencyId && !!state[Field.OUTPUT].currencyId) { return { ...state, - [otherField]: { - currencyId: undefined, - }, [field]: { currencyId: currencyId, }, From d32c08f8a4a60b0a3e85f7e9962f0d406d6ef365 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 24 Feb 2022 13:50:55 -0500 Subject: [PATCH 11/72] big int fix --- src/state/mobiusPools/updater.ts | 10 +- src/state/swap/hooks.ts | 2 - yarn.lock | 483 ++++++++++++++++--------------- 3 files changed, 254 insertions(+), 241 deletions(-) diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index d648ba4ab57..1d2b639b808 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -24,6 +24,7 @@ export function UpdatePools() { const lpTokenAddress = stablePools.map((p) => p.pool.lpToken.address) const poolAddress = stablePools.map((p) => p.pool.address) const lpTotalSupply = useMultipleContractSingleData(lpTokenAddress, lpInterface, 'totalSupply') + console.log('lp', lpTotalSupply) const balances = useMultipleContractSingleData(poolAddress, SwapInterface, 'getBalances') const query = gql` @@ -44,6 +45,8 @@ export function UpdatePools() { ` const { data, loading, error } = useQuery(query) + console.log('data', lpTotalSupply[0]?.result?.[0].toString()) + useEffect(() => { if (loading) return const inSubgraph: Set = @@ -57,7 +60,10 @@ export function UpdatePools() { fees: RECOMMENDED_FEES, volume: null, ampFactor: RECOMMENDED_AMP, - lpTotalSupply: new TokenAmount(displayPool.pool.lpToken, lpTotalSupply[i]?.result?.[0] ?? '0'), + lpTotalSupply: new TokenAmount( + displayPool.pool.lpToken, + BigIntToJSBI(lpTotalSupply[i]?.result?.[0] as BigInt) ?? '0' + ), reserves: balances?.[i]?.result?.[0] ? balances?.[i]?.result?.[0].map( (amt: BigInt, j: number): TokenAmount => @@ -68,7 +74,9 @@ export function UpdatePools() { }), }) ) + console.log('updated') } catch (error) { + console.log('error') console.error(error) } }, [loading, data?.swaps, dispatch, stablePools, lpTotalSupply, blockNumber, balances]) diff --git a/src/state/swap/hooks.ts b/src/state/swap/hooks.ts index 3d52c726dab..eccb14c851c 100644 --- a/src/state/swap/hooks.ts +++ b/src/state/swap/hooks.ts @@ -176,8 +176,6 @@ export function useMobiusTradeInfo(): { inputError = inputError ?? 'Pool Info Loading' } - console.log(pool) - if (pool && JSBI.equal(pool.lpTotalSupply.raw, JSBI.BigInt('0'))) { inputError = inputError ?? 'Insufficient Liquidity' } diff --git a/yarn.lock b/yarn.lock index f8cb591202c..31a3a58bdd1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,17 +2,17 @@ # yarn lockfile v1 -"@ampproject/remapping@^2.0.0": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.1.tgz#7922fb0817bf3166d8d9e258c57477e3fd1c3610" - integrity sha512-Aolwjd7HSC2PyY0fDj/wA/EimQT4HfEnFYNp5s9CQlrdhyvWTtvZ5YzrUPu6R6/1jKiUlxu8bUhkdSnKHNAHMA== +"@ampproject/remapping@^2.1.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" + integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== dependencies: "@jridgewell/trace-mapping" "^0.3.0" "@apollo/client@^3.4.16": - version "3.5.8" - resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.5.8.tgz#7215b974c5988b6157530eb69369209210349fe0" - integrity sha512-MAm05+I1ullr64VLpZwon/ISnkMuNLf6vDqgo9wiMhHYBGT4yOAbAIseRdjCHZwfSx/7AUuBgaTNOssZPIr6FQ== + version "3.5.9" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.5.9.tgz#306c1f8453d56dbb4ff1afaaaf16b3b719db696c" + integrity sha512-Qq3OE3GpyPG2fYXBzi1n4QXcKZ11c6jHdrXK2Kkn9SD+vUymSrllXsldqnKUK9tslxKqkKzNrkCXkLv7PxwfSQ== dependencies: "@graphql-typed-document-node/core" "^3.0.0" "@wry/context" "^0.6.0" @@ -48,7 +48,7 @@ dependencies: "@babel/highlight" "^7.16.7" -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8": +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0": version "7.17.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== @@ -76,19 +76,19 @@ source-map "^0.5.0" "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.7.5", "@babel/core@^7.8.4": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.2.tgz#2c77fc430e95139d816d39b113b31bf40fb22337" - integrity sha512-R3VH5G42VSDolRHyUO4V2cfag8WHcZyxdq5Z/m8Xyb92lW/Erm/6kM+XtRFGf3Mulre3mveni2NHfEUws8wSvw== + version "7.17.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.5.tgz#6cd2e836058c28f06a4ca8ee7ed955bbf37c8225" + integrity sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA== dependencies: - "@ampproject/remapping" "^2.0.0" + "@ampproject/remapping" "^2.1.0" "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.0" + "@babel/generator" "^7.17.3" "@babel/helper-compilation-targets" "^7.16.7" "@babel/helper-module-transforms" "^7.16.7" "@babel/helpers" "^7.17.2" - "@babel/parser" "^7.17.0" + "@babel/parser" "^7.17.3" "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.0" + "@babel/traverse" "^7.17.3" "@babel/types" "^7.17.0" convert-source-map "^1.7.0" debug "^4.1.0" @@ -96,10 +96,10 @@ json5 "^2.1.2" semver "^6.3.0" -"@babel/generator@^7.12.1", "@babel/generator@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.0.tgz#7bd890ba706cd86d3e2f727322346ffdbf98f65e" - integrity sha512-I3Omiv6FGOC29dtlZhkfXO6pgkmukJSlT26QjVvS1DGZe/NzSVCPG41X0tS21oZkJYlovfj9qDWgKP+Cn4bXxw== +"@babel/generator@^7.12.1", "@babel/generator@^7.17.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" + integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== dependencies: "@babel/types" "^7.17.0" jsesc "^2.5.1" @@ -130,10 +130,10 @@ browserslist "^4.17.5" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.17.1": - version "7.17.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz#9699f14a88833a7e055ce57dcd3ffdcd25186b21" - integrity sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ== +"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.17.1", "@babel/helper-create-class-features-plugin@^7.17.6": + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz#3778c1ed09a7f3e65e6d6e0f6fbfcc53809d92c9" + integrity sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" @@ -217,9 +217,9 @@ "@babel/types" "^7.16.7" "@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" - integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz#3c3b03cc6617e33d68ef5a27a67419ac5199ccd0" + integrity sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA== dependencies: "@babel/helper-environment-visitor" "^7.16.7" "@babel/helper-module-imports" "^7.16.7" @@ -227,8 +227,8 @@ "@babel/helper-split-export-declaration" "^7.16.7" "@babel/helper-validator-identifier" "^7.16.7" "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" "@babel/helper-optimise-call-expression@^7.16.7": version "7.16.7" @@ -321,10 +321,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.3", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.0", "@babel/parser@^7.7.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.0.tgz#f0ac33eddbe214e4105363bb17c3341c5ffcc43c" - integrity sha512-VKXSCQx5D8S04ej+Dqsr1CzYvvWgf20jIw2D+YhQCrIlr2UZGaDds23Y0xg75/skOxpLCRpUZvk/1EAVkGoDOw== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.3", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.7.0": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" + integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": version "7.16.7" @@ -360,11 +360,11 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-proposal-class-static-block@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz#712357570b612106ef5426d13dc433ce0f200c2a" - integrity sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw== + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz#164e8fd25f0d80fa48c5a4d1438a6629325ad83c" + integrity sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.17.6" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-class-static-block" "^7.14.5" @@ -428,11 +428,11 @@ "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-proposal-object-rest-spread@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz#94593ef1ddf37021a25bdcb5754c4a8d534b01d8" - integrity sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA== + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz#d9eb649a54628a51701aef7e0ea3d17e2b9dd390" + integrity sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw== dependencies: - "@babel/compat-data" "^7.16.4" + "@babel/compat-data" "^7.17.0" "@babel/helper-compilation-targets" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" @@ -673,9 +673,9 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-destructuring@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz#ca9588ae2d63978a4c29d3f33282d8603f618e23" - integrity sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A== + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz#c445f75819641788a27a0a3a759d9df911df6abc" + integrity sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg== dependencies: "@babel/helper-plugin-utils" "^7.16.7" @@ -815,9 +815,9 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-constant-elements@^7.12.1": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz#19e9e4c2df2f6c3e6b3aea11778297d81db8df62" - integrity sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ== + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.17.6.tgz#6cc273c2f612a6a50cb657e63ee1303e5e68d10a" + integrity sha512-OBv9VkyyKtsHZiHLoSfCn+h6yU7YKX8nrs32xUmOa1SRSk+t03FosB6fBZ0Yz4BpD1WV7l73Nsad+2Tz7APpqw== dependencies: "@babel/helper-plugin-utils" "^7.16.7" @@ -836,15 +836,15 @@ "@babel/plugin-transform-react-jsx" "^7.16.7" "@babel/plugin-transform-react-jsx@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.7.tgz#86a6a220552afd0e4e1f0388a68a372be7add0d4" - integrity sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag== + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz#eac1565da176ccb1a715dae0b4609858808008c1" + integrity sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-module-imports" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-jsx" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/types" "^7.17.0" "@babel/plugin-transform-react-pure-annotations@^7.16.7": version "7.16.7" @@ -1076,18 +1076,18 @@ "@babel/parser" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.1", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.0.tgz#3143e5066796408ccc880a33ecd3184f3e75cd30" - integrity sha512-fpFIXvqD6kC7c7PUNnZ0Z8cQXlarCLtCUpt2S1Dx7PjoRtCFffvOkHHSom+m5HIxMZn5bIBVb71lhabcmjEsqg== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.1", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" + integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== dependencies: "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.0" + "@babel/generator" "^7.17.3" "@babel/helper-environment-visitor" "^7.16.7" "@babel/helper-function-name" "^7.16.7" "@babel/helper-hoist-variables" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.0" + "@babel/parser" "^7.17.3" "@babel/types" "^7.17.0" debug "^4.1.0" globals "^11.1.0" @@ -1765,9 +1765,9 @@ "@ethersproject/strings" "^5.5.0" "@gar/promisify@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210" - integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw== + version "1.1.3" + resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" + integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== "@graphql-typed-document-node/core@^3.0.0": version "3.1.1" @@ -2300,20 +2300,20 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@sentry/browser@6.17.7": - version "6.17.7" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.17.7.tgz#04b72ae29a56c2001be525fa39c17aa7d9992e7f" - integrity sha512-0Ad6TmB5KH5o152Hgk5tlxNiooV0Rfoj7HEzxdOnHFkl57aR7VsiPkzIBl9vxn4iyy7IheUONhHSOU1osJkv2w== +"@sentry/browser@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.18.0.tgz#72d3e885199e0b41272ef37162dbbfa828e9c469" + integrity sha512-fQZdFs0jnBijVmhDWNIsHD0rGsIXup/1UYgMZqdBYYSBBQ7Ffpw+6nX1/vyKsCpLdgYhbi88eK/XO+QHtUJE2w== dependencies: - "@sentry/core" "6.17.7" - "@sentry/types" "6.17.7" - "@sentry/utils" "6.17.7" + "@sentry/core" "6.18.0" + "@sentry/types" "6.18.0" + "@sentry/utils" "6.18.0" tslib "^1.9.3" "@sentry/cli@^1.72.0": - version "1.72.2" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.72.2.tgz#ba57d8248fe4d2836883bbe3047fdd75cd6739b3" - integrity sha512-H/yrxyYscOzn0YBOzPsBnIW7QxsSQrG1kQfD1FisuMhPl67D948DPkagAms4sy1v+MntBBNnD4Z+WsdRzFWXJQ== + version "1.73.0" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.73.0.tgz#0d0bce913e0060ae192741c6693c57e50078c886" + integrity sha512-n4YINqmoncGUkLEpd4WuW+oD+aoUyQPhRbSBSYkbCFxPPmopn1VExCB2Vvzwj7vjXYRRGkix6keBMS0LLs3A3Q== dependencies: https-proxy-agent "^5.0.0" mkdirp "^0.5.5" @@ -2322,75 +2322,75 @@ progress "^2.0.3" proxy-from-env "^1.1.0" -"@sentry/core@6.17.7": - version "6.17.7" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.17.7.tgz#f591235c06b1a4e75d748b15c539e071bd3f5cf5" - integrity sha512-SRhLkD05lQb4eCt1ed9Dz72DKbRDlM8PJix8eC2oJLtwyFTS0IlJNkIYRrbsSKkJUm0VsKcDkzIHvUAgBBQICw== +"@sentry/core@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.18.0.tgz#9ebfff67265cbe1af29f1cce0f712d9bd36b331f" + integrity sha512-I3iQVfMWHXR/LtevJg83aD7UAiUBLz1xAW8y3gd5lJej96UNv/4TbCmKZumYnEJMXf8EcFlg8t48W0Bl1GxhEg== dependencies: - "@sentry/hub" "6.17.7" - "@sentry/minimal" "6.17.7" - "@sentry/types" "6.17.7" - "@sentry/utils" "6.17.7" + "@sentry/hub" "6.18.0" + "@sentry/minimal" "6.18.0" + "@sentry/types" "6.18.0" + "@sentry/utils" "6.18.0" tslib "^1.9.3" -"@sentry/hub@6.17.7": - version "6.17.7" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.17.7.tgz#5c90d661e263dad7da0e0106f1cb90cf797d93a7" - integrity sha512-siGzcg+quGOdjRaBGAz6T3ycwHUsGgvalptSJdf5Q783FVFhU+haPul++zGOYURXOgx0RjYGWqagwO8+jljl3Q== +"@sentry/hub@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.18.0.tgz#8c425bc340b2792c5ac9c6feed2f444d9b7f5bb7" + integrity sha512-E2GrrNcidyT67ONU3btHO5vyS1bPQNdWqC09sUc1F3q/nQyvc7L2W09TKY2veaMZQtC9EU760fTG1hMmgGwPmw== dependencies: - "@sentry/types" "6.17.7" - "@sentry/utils" "6.17.7" + "@sentry/types" "6.18.0" + "@sentry/utils" "6.18.0" tslib "^1.9.3" -"@sentry/minimal@6.17.7": - version "6.17.7" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.17.7.tgz#f19182047f19b563f40a30d45d2ce9ad7df1ec4e" - integrity sha512-+/FGem1uXsXikX9wHPw44nevO7YTVjkkiPjyLsvnWMjv64r4Au5s+NQSFHDaytRm9IlU//+OasCAS5VAwHcYRg== +"@sentry/minimal@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.18.0.tgz#03da29b45b62b3073fbd110e423608ada17ef52c" + integrity sha512-QkkWOhX3NMycUNLj96thMQ0BclmfxE2VdDf9ZqRkvdFzxI1FVY5NEArqD4wtlrCIoYN1ioAYrvdb48/BTuGung== dependencies: - "@sentry/hub" "6.17.7" - "@sentry/types" "6.17.7" + "@sentry/hub" "6.18.0" + "@sentry/types" "6.18.0" tslib "^1.9.3" "@sentry/react@^6.9.0": - version "6.17.7" - resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.17.7.tgz#550735bd9b56f20f15059f10a4573c80d5c882a5" - integrity sha512-rt6nAa9SJ+A4va88FASBoR5/26V2uZx/yucT9NzwoBIW41jA8lAwTmFu5MdtxGDBKDUSJlL3lt/Nkiq6LkiTaw== - dependencies: - "@sentry/browser" "6.17.7" - "@sentry/minimal" "6.17.7" - "@sentry/types" "6.17.7" - "@sentry/utils" "6.17.7" + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.18.0.tgz#df76dab64decd6789b0f9e3b3ae035c3aee85b9b" + integrity sha512-jJ3g41ucDyudT5Ye6ry3mGQaHkbp14yqjbgBWKhCljWwYie0rHLCfjZ6letz6K1ey2Asvl6MLH5eoNhGEV0idg== + dependencies: + "@sentry/browser" "6.18.0" + "@sentry/minimal" "6.18.0" + "@sentry/types" "6.18.0" + "@sentry/utils" "6.18.0" hoist-non-react-statics "^3.3.2" tslib "^1.9.3" "@sentry/tracing@^6.9.0": - version "6.17.7" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.17.7.tgz#f4536683b29bb3ac7ddda5ca49494731cec6b619" - integrity sha512-QzIDHOjjdi/0LTdrK2LTC27YEOODI473KD8KmMJ+r9PmjDeIjNzz4hJlPwQSnXR3Mu/8foxGJGXsAt3LNmKzlQ== - dependencies: - "@sentry/hub" "6.17.7" - "@sentry/minimal" "6.17.7" - "@sentry/types" "6.17.7" - "@sentry/utils" "6.17.7" + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.18.0.tgz#c9678f1c095eb58abec4de5ffd33f00420d2cbbe" + integrity sha512-thwVrYT+ba58h6F6Im4t+JH9o+7H+75ribkeTgM7NRhNuiGajlXNmb37Dh9gP5Iy76jNV8GATy4cOcuVc7P1jA== + dependencies: + "@sentry/hub" "6.18.0" + "@sentry/minimal" "6.18.0" + "@sentry/types" "6.18.0" + "@sentry/utils" "6.18.0" tslib "^1.9.3" -"@sentry/types@6.17.7": - version "6.17.7" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.17.7.tgz#61946a3f6532b8f21251b264f173b02f9ea2458e" - integrity sha512-iBlJDhrSowZKeqvutY0tCkUjrWqkLFsHrbaQ553r1Nx+/4mxHjzVYtEVGMjZAxQUEbkm0TbnQIkkT7ltglNJ9A== +"@sentry/types@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.18.0.tgz#89cee850d16c88621459d9f2a7f6cff9e9d3fb5f" + integrity sha512-SypDwXL1URE/XLkP4Ve+pFs41e+2OUYZ0lCimNreQQv46//pFXxP3LwU9Tc0Az4ZfxXnGiwofvt73XyBq9VpRQ== -"@sentry/utils@6.17.7": - version "6.17.7" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.17.7.tgz#0574bf914cc129b5e47041b75bb34dfbe0decbba" - integrity sha512-HEEEeKlZtwfQvH0waSKv5FKRFjHkVgkkEiAigXoYGQAlaUIuwRTvZGFnsmBoKMIrA4pARkA00FwwdtMU7ziC8A== +"@sentry/utils@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.18.0.tgz#99ad577020a269e43629feb6305c121065c992d1" + integrity sha512-mKegOabkAjoUHfokjI5oi3CMez5GD3xXOrBFcLVc9GFDXCgNMdYnHyEn/mmy8PikFdGHxZ3oI/16ZGU22wi5aw== dependencies: - "@sentry/types" "6.17.7" + "@sentry/types" "6.18.0" tslib "^1.9.3" "@sentry/webpack-plugin@^1.16.0": - version "1.18.5" - resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.18.5.tgz#aaff79d8e05b8d803654490324252406c976b1cd" - integrity sha512-HycNZEcVRj/LxaG6hLsxjHo47mpxop3j7u2aUkriE2pT7XNpeypsa0WiokYzStxzCfSu8rbAbX4PchTGLMlTjw== + version "1.18.7" + resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.18.7.tgz#f48dbebb4989f3a357280f2c92a8d4b5b963f6ec" + integrity sha512-pOJLzC2unQdtrQarcicZ3aPs6hnQUjMvVmRN7s+/m7PEITvvf24hgIPdbLnn6PVQARvFA8mbbst0+eHMi44veA== dependencies: "@sentry/cli" "^1.72.0" @@ -2927,9 +2927,9 @@ multicodec "*" "@types/node@*": - version "17.0.17" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.17.tgz#a8ddf6e0c2341718d74ee3dc413a13a042c45a0c" - integrity sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw== + version "17.0.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644" + integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ== "@types/node@10.12.18": version "10.12.18" @@ -2947,14 +2947,14 @@ integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== "@types/node@^12.11.7", "@types/node@^12.12.6": - version "12.20.45" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.45.tgz#f4980d177999299d99cd4b290f7f39366509a44f" - integrity sha512-1Jg2Qv5tuxBqgQV04+wO5u+wmSHbHgpORCJdeCLM+E+YdPElpdHhgywU+M1V1InL8rfOtpqtOjswk+uXTKwx7w== + version "12.20.46" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.46.tgz#7e49dee4c54fd19584e6a9e0da5f3dc2e9136bc7" + integrity sha512-cPjLXj8d6anFPzFvOPxS3fvly3Shm5nTfl6g8X5smexixbuGUf7hfr21J5tX9JW+UPStp/5P5R8qrKL5IyVJ+A== "@types/node@^14.14.37": - version "14.18.11" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.11.tgz#9bd810a959e1728d78df0f68b5c825b8ea7156f4" - integrity sha512-zCoCEMA+IPpsRkyCFBqew5vGb7r8RSiB3uwdu/map7uwLAfu1MTazW26/pUDWoNnF88vJz4W3U56i5gtXNqxGg== + version "14.18.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.12.tgz#0d4557fd3b94497d793efd4e7d92df2f83b4ef24" + integrity sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -3114,9 +3114,9 @@ integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== "@types/styled-components@*", "@types/styled-components@^5.1.9": - version "5.1.22" - resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.22.tgz#ee6206582d3da11fa2f9951e858aefebee37ff20" - integrity sha512-zQzf/0aGtgFDjB942f8IaKA6UilFziDza9wXkAX5mpiSWA/FBZBU6yUavvczulTvoR6759h6CH8HuuIcJDBgZA== + version "5.1.23" + resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.23.tgz#11e5740047f292b42a042c60c0ef16b58d5adef6" + integrity sha512-zt8oQGU6XB4LH1Xpq169YnAVmt22+swzHJvyKMyTZu/z8+afvgKjjg0s79aAodgNSf36ZOEG6DyVAW/JhLH2Nw== dependencies: "@types/hoist-non-react-statics" "*" "@types/react" "*" @@ -3299,9 +3299,9 @@ eslint-visitor-keys "^2.0.0" "@ubeswap/default-token-list@^4.0.29": - version "4.1.42" - resolved "https://registry.yarnpkg.com/@ubeswap/default-token-list/-/default-token-list-4.1.42.tgz#9917bf221a96d033032acc2fa0e66607f7efbc3c" - integrity sha512-GnbAZ5Qb33NG1/yPw8yHRKNfRre3UOKhTrlM4pop8hflxMeIWLyIbGJujeGZqUG77nvkBcQfrO8nlp3DV6qXoA== + version "4.1.44" + resolved "https://registry.yarnpkg.com/@ubeswap/default-token-list/-/default-token-list-4.1.44.tgz#f5b2b2c3bb64fc7282cb487810c48d304e2702bf" + integrity sha512-EIUsqOkHRUH4Dt9B8W5XTABUpxs0UjWXsnhucqR2qxJDkmUUMzb7X706RQy9JgsyPCOwdoFBZRqa9/gRsZ/a6g== "@ubeswap/sdk@^2.1.0": version "2.1.2" @@ -3708,7 +3708,7 @@ abstract-leveldown@~2.7.1: dependencies: xtend "~4.0.0" -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -3749,7 +3749,7 @@ acorn@^7.1.0, acorn@^7.1.1, acorn@^7.4.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.2.4, acorn@^8.4.1: +acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0: version "8.7.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== @@ -4339,14 +4339,15 @@ babel-plugin-polyfill-regenerator@^0.3.0: "@babel/helper-define-polyfill-provider" "^0.3.1" "babel-plugin-styled-components@>= 1.12.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.2.tgz#0fac11402dc9db73698b55847ab1dc73f5197c54" - integrity sha512-7eG5NE8rChnNTDxa6LQfynwgHTVOYYaHJbUYSlOhk8QBXIQiMBKq4gyfHBBKPrxUcVBXVJL61ihduCpCQbuNbw== + version "2.0.5" + resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.5.tgz#8c402e5868c2a419eefb5466fccf154af18c52d1" + integrity sha512-A7kfST5odbf8Ev42OQbj5teEiT8DskpRoQ/iPYePLLdcTCAsodpYKqtoy4SJthpsGzQKc2vvnrtlUgdmJq6WKQ== dependencies: "@babel/helper-annotate-as-pure" "^7.16.0" "@babel/helper-module-imports" "^7.16.0" babel-plugin-syntax-jsx "^6.18.0" lodash "^4.17.11" + picomatch "^2.3.0" babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" @@ -4612,20 +4613,20 @@ bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.2.0: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== -body-parser@1.19.1, body-parser@^1.16.0: - version "1.19.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" - integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== +body-parser@1.19.2, body-parser@^1.16.0: + version "1.19.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" + integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== dependencies: - bytes "3.1.1" + bytes "3.1.2" content-type "~1.0.4" debug "2.6.9" depd "~1.1.2" http-errors "1.8.1" iconv-lite "0.4.24" on-finished "~2.3.0" - qs "6.9.6" - raw-body "2.4.2" + qs "6.9.7" + raw-body "2.4.3" type-is "~1.6.18" bonjour@^3.5.0: @@ -4763,14 +4764,14 @@ browserslist@4.14.2: node-releases "^1.1.61" browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.17.5, browserslist@^4.19.1, browserslist@^4.6.2, browserslist@^4.6.4: - version "4.19.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" - integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== + version "4.19.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.3.tgz#29b7caad327ecf2859485f696f9604214bedd383" + integrity sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg== dependencies: - caniuse-lite "^1.0.30001286" - electron-to-chromium "^1.4.17" + caniuse-lite "^1.0.30001312" + electron-to-chromium "^1.4.71" escalade "^3.1.1" - node-releases "^2.0.1" + node-releases "^2.0.2" picocolors "^1.0.0" bs58@^4.0.0: @@ -4896,10 +4897,10 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= -bytes@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" - integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cacache@^12.0.2: version "12.0.4" @@ -5039,10 +5040,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001286: - version "1.0.30001311" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001311.tgz#682ef3f4e617f1a177ad943de59775ed3032e511" - integrity sha512-mleTFtFKfykEeW34EyfhGIFjGCqzhh38Y0LhdQ9aWF+HorZTtdgKV/1hEE0NlFkG2ubvisPV6l400tlbPys98A== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001312: + version "1.0.30001312" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" + integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== capture-exit@^2.0.0: version "2.0.0" @@ -5567,10 +5568,10 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" - integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== +cookie@0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== cookiejar@^2.1.1: version "2.1.3" @@ -5602,17 +5603,17 @@ copy-to-clipboard@^3.2.0, copy-to-clipboard@^3.3.1: toggle-selection "^1.0.6" core-js-compat@^3.20.2, core-js-compat@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.0.tgz#bcc86aa5a589cee358e7a7fa0a4979d5a76c3885" - integrity sha512-OSXseNPSK2OPJa6GdtkMz/XxeXx8/CJvfhQWTqd6neuUraujcL4jVsjkLQz1OWnax8xVQJnRPe0V2jqNWORA+A== + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.1.tgz#cac369f67c8d134ff8f9bd1623e3bc2c42068c82" + integrity sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g== dependencies: browserslist "^4.19.1" semver "7.0.0" core-js-pure@^3.20.2: - version "3.21.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.0.tgz#819adc8dfb808205ce25b51d50591becd615db7e" - integrity sha512-VaJUunCZLnxuDbo1rNOzwbet9E1K9joiXS5+DQMPtgxd24wfsZbJZMMfQLGYMlCUvSxLfsRUUhoOR2x28mFfeg== + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" + integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== core-js@^2.4.0: version "2.6.12" @@ -5620,9 +5621,9 @@ core-js@^2.4.0: integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== core-js@^3.6.5: - version "3.21.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.0.tgz#f479dbfc3dffb035a0827602dd056839a774aa71" - integrity sha512-YUdI3fFu4TF/2WykQ2xzSiTQdldLB4KVuL9WeAy5XONZYt5Cun/fpQvctoKbCgvPhmzADeesTk/j2Rdx77AcKQ== + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94" + integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig== core-util-is@1.0.2: version "1.0.2" @@ -6618,10 +6619,10 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.3.564, electron-to-chromium@^1.4.17: - version "1.4.68" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.68.tgz#d79447b6bd1bec9183f166bb33d4bef0d5e4e568" - integrity sha512-cId+QwWrV8R1UawO6b9BR1hnkJ4EJPCPAr4h315vliHUtVUJDk39Sg1PMNnaWKfj5x+93ssjeJ9LKL6r8LaMiA== +electron-to-chromium@^1.3.564, electron-to-chromium@^1.4.71: + version "1.4.72" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.72.tgz#19b871f1da8be8199b2330d694fc84fcdb72ecd9" + integrity sha512-9LkRQwjW6/wnSfevR21a3k8sOJ+XWSH7kkzs9/EUenKmuDkndP3W9y1yCZpOxufwGbX3JV8glZZSDb4o95zwXQ== elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" @@ -6824,9 +6825,9 @@ escodegen@^2.0.0: source-map "~0.6.1" eslint-config-prettier@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" - integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew== + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.4.0.tgz#8e6d17c7436649e98c4c2189868562921ef563de" + integrity sha512-CFotdUcMY18nGRo5KGsnNxpznzhkopOcOo0InID+sgQssPrzjvsyKZPvOgymTFeHrFuC3Tzdf2YndhXtULK9Iw== eslint-config-react-app@^6.0.0: version "6.0.0" @@ -7557,16 +7558,16 @@ expect@^26.6.0, expect@^26.6.2: jest-regex-util "^26.0.0" express@^4.14.0, express@^4.17.1: - version "4.17.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.2.tgz#c18369f265297319beed4e5558753cc8c1364cb3" - integrity sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg== + version "4.17.3" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" + integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.19.1" + body-parser "1.19.2" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.1" + cookie "0.4.2" cookie-signature "1.0.6" debug "2.6.9" depd "~1.1.2" @@ -7581,7 +7582,7 @@ express@^4.14.0, express@^4.17.1: parseurl "~1.3.3" path-to-regexp "0.1.7" proxy-addr "~2.0.7" - qs "6.9.6" + qs "6.9.7" range-parser "~1.2.1" safe-buffer "5.2.1" send "0.17.2" @@ -7858,17 +7859,17 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" -focus-lock@^0.10.1: - version "0.10.1" - resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.10.1.tgz#5f46fa74fefb87144479c2f8e276f0eedd8081b2" - integrity sha512-b9yUklCi4fTu2GXn7dnaVf4hiLVVBp7xTiZarAHMODV2To6Bitf6F/UI67RmKbdgJQeVwI1UO0d9HYNbXt3GkA== +focus-lock@^0.10.2: + version "0.10.2" + resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.10.2.tgz#561c62bae8387ecba1dd8e58a6df5ec29835c644" + integrity sha512-DSaI/UHZ/02sg1P616aIWgToQcrKKBmcCvomDZ1PZvcJFj350PnWhSJxJ76T3e5/GbtQEARIACtbrdlrF9C5kA== dependencies: tslib "^2.0.3" follow-redirects@^1.0.0, follow-redirects@^1.14.0: - version "1.14.8" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" - integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== + version "1.14.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" + integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== for-in@^1.0.2: version "1.0.2" @@ -10329,9 +10330,9 @@ lines-and-columns@^1.1.6: integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== lint-staged@>=11: - version "12.3.3" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.3.3.tgz#0a465962fe53baa2b4b9da50801ead49a910e03b" - integrity sha512-OqcLsqcPOqzvsfkxjeBpZylgJ3SRG1RYqc9LxC6tkt6tNsq1bNVkAixBwX09f6CobcHswzqVOCBpFR1Fck0+ag== + version "12.3.4" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.3.4.tgz#4b1ff8c394c3e6da436aaec5afd4db18b5dac360" + integrity sha512-yv/iK4WwZ7/v0GtVkNb3R82pdL9M+ScpIbJLJNyCXkJ1FGaXvRCOg/SeL59SZtPpqZhE7BD6kPKFLIDUhDx2/w== dependencies: cli-truncate "^3.1.0" colorette "^2.0.16" @@ -10577,9 +10578,9 @@ ltgt@~2.2.0: integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= luxon@^2.1.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-2.3.0.tgz#bf16a7e642513c2a20a6230a6a41b0ab446d0045" - integrity sha512-gv6jZCV+gGIrVKhO90yrsn8qXPKD8HYZJtrUDSfEbow8Tkw84T9OnCyJhWvnJIaIF/tBuiAjZuQHUt1LddX2mg== + version "2.3.1" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-2.3.1.tgz#f276b1b53fd9a740a60e666a541a7f6dbed4155a" + integrity sha512-I8vnjOmhXsMSlNMZlMkSOvgrxKJl0uOsEzdGgGNZuZPaS9KlefpE9KV95QFftlJSC+1UyCC9/I69R02cz/zcCA== magic-string@^0.25.0, magic-string@^0.25.7: version "0.25.7" @@ -10787,11 +10788,16 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.51.0, "mime-db@>= 1.43.0 < 2": +mime-db@1.51.0: version "1.51.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== +"mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + mime-types@^2.1.12, mime-types@^2.1.16, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.34" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" @@ -10862,9 +10868,9 @@ minimatch@3.0.4: brace-expansion "^1.1.7" minimatch@^3.0.4: - version "3.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.5.tgz#4da8f1290ee0f0f8e83d60ca69f8f134068604a3" - integrity sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" @@ -11100,9 +11106,9 @@ multicodec@^1.0.0: varint "^5.0.0" multiformats@^9.4.2: - version "9.6.3" - resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.6.3.tgz#9f2aef711ddd0e7b05a1b5f1ad70928544c8c190" - integrity sha512-yfXKI66fL0nFzt0nJl26i4wV1qAqbAEIBvfFbkbsne9GrLz6IHvHUoRyxUtlJcdP181ssOgjama6E/VSk4pbrA== + version "9.6.4" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.6.4.tgz#5dce1f11a407dbb69aa612cb7e5076069bb759ca" + integrity sha512-fCCB6XMrr6CqJiHNjfFNGT0v//dxOBMrOMqUIzpPc/mmITweLEyhvMpY9bF+jZ9z3vaMAau5E8B68DW77QMXkg== multihashes@^0.4.15, multihashes@~0.4.15: version "0.4.21" @@ -11133,9 +11139,9 @@ nano-json-stream-parser@^0.1.2: integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= nanoid@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" - integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== + version "3.3.1" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" + integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== nanomatch@^1.2.9: version "1.2.13" @@ -11280,7 +11286,7 @@ node-releases@^1.1.61: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e" integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ== -node-releases@^2.0.1: +node-releases@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== @@ -11958,7 +11964,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -12955,10 +12961,10 @@ qrcode@1.4.4: pngjs "^3.3.0" yargs "^13.2.4" -qs@6.9.6: - version "6.9.6" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" - integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== +qs@6.9.7: + version "6.9.7" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" + integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== qs@~6.5.2: version "6.5.3" @@ -13055,12 +13061,12 @@ raphael@^2.2.0: dependencies: eve-raphael "0.5.0" -raw-body@2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" - integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== +raw-body@2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" + integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== dependencies: - bytes "3.1.1" + bytes "3.1.2" http-errors "1.8.1" iconv-lite "0.4.24" unpipe "1.0.0" @@ -13173,12 +13179,12 @@ react-feather@^2.0.9: prop-types "^15.7.2" react-focus-lock@^2.5.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.7.1.tgz#a9fbb3fa4efaee32162406e5eb96ae658964193b" - integrity sha512-ImSeVmcrLKNMqzUsIdqOkXwTVltj79OPu43oT8tVun7eIckA4VdM7UmYUFo3H/UC2nRVgagMZGFnAOQEDiDYcA== + version "2.8.1" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.8.1.tgz#a28f06a4ef5eab7d4ef0d859512772ec1331d529" + integrity sha512-4kb9I7JIiBm0EJ+CsIBQ+T1t5qtmwPRbFGYFQ0t2q2qIpbFbYTHDjnjJVFB7oMBtXityEOQehblJPjqSIf3Amg== dependencies: "@babel/runtime" "^7.0.0" - focus-lock "^0.10.1" + focus-lock "^0.10.2" prop-types "^15.6.2" react-clientside-effect "^1.2.5" use-callback-ref "^1.2.5" @@ -13195,9 +13201,9 @@ react-hamburger-menu@^1.2.1: integrity sha512-It5Jque8bx9lYn8q/NFtu9Ci20fBMsyunFSp06ZGgWXbMZlTFrN0IxKguGZ0igYQr6RvJ3S9CN3rTjrObmq/Cw== react-i18next@^11.10.0: - version "11.15.4" - resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.15.4.tgz#fe0c792ea93f038548e838cecae3ed4173822937" - integrity sha512-jKJNAcVcbPGK+yrTcXhLblgPY16n6NbpZZL3Mk8nswj1v3ayIiUBVDU09SgqnT+DluyQBS97hwSvPU5yVFG0yg== + version "11.15.5" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.15.5.tgz#3de940a1c5a27956d8265663ca67494881f385e8" + integrity sha512-vBWuVEQgrhZrGKpyv8FmJ7Zs5jRQWl794Tte7yzJ0okZqqi3jd6j2pLYNg441WcREsbIOvWdiDXbY7W6E93p1A== dependencies: "@babel/runtime" "^7.14.5" html-escaper "^2.0.2" @@ -13277,9 +13283,9 @@ react-remove-scroll-bar@^2.1.0: tslib "^1.0.0" react-remove-scroll@^2.4.2: - version "2.4.3" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.4.3.tgz#83d19b02503b04bd8141ed6e0b9e6691a2e935a6" - integrity sha512-lGWYXfV6jykJwbFpsuPdexKKzp96f3RbvGapDSIdcyGvHb7/eqyn46C7/6h+rUzYar1j5mdU+XECITHXCKBk9Q== + version "2.4.4" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.4.4.tgz#2dfff377cf17efc00de39dad51c143fc7a1b9e3e" + integrity sha512-EyC5ohYhaeKbThMSQxuN2i+QC5HqV3AJvNZKEdiATITexu0gHm00+5ko0ltNS1ajYJVeDgVG2baRSCei0AUWlQ== dependencies: react-remove-scroll-bar "^2.1.0" react-style-singleton "^2.1.0" @@ -14646,9 +14652,9 @@ stack-utils@^2.0.2: escape-string-regexp "^2.0.0" stackframe@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303" - integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA== + version "1.2.1" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.1.tgz#1033a3473ee67f08e2f2fc8eba6aef4f845124e1" + integrity sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg== state-toggle@^1.0.0: version "1.0.3" @@ -15176,10 +15182,11 @@ terser@^4.1.2, terser@^4.6.2, terser@^4.6.3: source-map-support "~0.5.12" terser@^5.3.4: - version "5.10.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" - integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== + version "5.11.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.11.0.tgz#2da5506c02e12cd8799947f30ce9c5b760be000f" + integrity sha512-uCA9DLanzzWSsN1UirKwylhhRz3aKPInlfmpGfw8VN6jHsAtu8HJtIpeeHHK23rxnE/cDc+yvmq5wqkIC6Kn0A== dependencies: + acorn "^8.5.0" commander "^2.20.0" source-map "~0.7.2" source-map-support "~0.5.20" @@ -15820,9 +15827,9 @@ url-parse-lax@^3.0.0: prepend-http "^2.0.0" url-parse@^1.4.3, url-parse@^1.5.3: - version "1.5.4" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.4.tgz#e4f645a7e2a0852cc8a66b14b292a3e9a11a97fd" - integrity sha512-ITeAByWWoqutFClc/lRZnFplgXgEZr3WJ6XngMM/N9DMIm4K8zXPCZ1Jdu0rERwO84w1WC5wkle2ubwTA4NTBg== + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== dependencies: querystringify "^2.1.1" requires-port "^1.0.0" From ab128781173ea1aa3fe7d7309c8708fadfc53ed1 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 24 Feb 2022 14:29:00 -0500 Subject: [PATCH 12/72] swap math doesn't error but incorrect values --- src/lib/calculator/price.ts | 22 +++++++++++++++++----- src/pages/Staking/CalcBoost.tsx | 1 - src/state/mobiusPools/reducer.ts | 5 ++++- src/state/mobiusPools/updater.ts | 7 +++---- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/lib/calculator/price.ts b/src/lib/calculator/price.ts index 3193b9b0959..08f7f0dc16e 100644 --- a/src/lib/calculator/price.ts +++ b/src/lib/calculator/price.ts @@ -1,4 +1,4 @@ -import { Price, TokenAmount } from '@ubeswap/sdk' +import { JSBI, Price, TokenAmount } from '@ubeswap/sdk' import type { IExchangeInfo } from '../../constants/pools' import { calculateEstimatedSwapOutputAmount } from '.' @@ -9,6 +9,15 @@ import { calculateEstimatedSwapOutputAmount } from '.' * To get the price of "Token 0", use `.invert()` on the result of this function. * @returns */ + +function min(a: JSBI, b: JSBI): JSBI { + return JSBI.greaterThan(a, b) ? b : a +} + +function max(a: JSBI, b: JSBI): JSBI { + return JSBI.greaterThan(a, b) ? a : b +} + export const calculateSwapPrice = (exchangeInfo: IExchangeInfo): Price => { const reserve0 = exchangeInfo.reserves[0] const reserve1 = exchangeInfo.reserves[1] @@ -16,12 +25,15 @@ export const calculateSwapPrice = (exchangeInfo: IExchangeInfo): Price => { // We try to get at least 4 decimal points of precision here // Otherwise, we attempt to swap 1% of total supply of the pool // or at most, $1 - const inputAmountNum = Math.max( - 10_000, - Math.min(10 ** reserve0.token.decimals, Math.floor(parseInt(reserve0.divide('100').toString()))) + const inputAmountNum = max( + JSBI.BigInt('10000'), + min( + JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt(reserve0.token.decimals)), + JSBI.divide(reserve0.raw, JSBI.BigInt('100')) + ) ) - const inputAmount = new TokenAmount(reserve0.token, inputAmountNum.toString()) + const inputAmount = new TokenAmount(reserve0.token, inputAmountNum) const outputAmount = calculateEstimatedSwapOutputAmount(exchangeInfo, inputAmount) return new Price(reserve0.token, reserve1.token, outputAmount.outputAmountBeforeFees.raw, inputAmount.raw) diff --git a/src/pages/Staking/CalcBoost.tsx b/src/pages/Staking/CalcBoost.tsx index d4c9a539cb3..e7f61ad783e 100644 --- a/src/pages/Staking/CalcBoost.tsx +++ b/src/pages/Staking/CalcBoost.tsx @@ -136,7 +136,6 @@ export default function CalcBoost({ stakingInfo }: PositionsProps) { const stablePools = useStablePoolInfo() const { address, connected } = useWeb3Context() const { positions = [] } = stakingInfo - const loading = positions.length === 0 const greaterThanZero = positions.filter(({ baseBalance }) => baseBalance.greaterThan('0')) const [openModal, setOpenModal] = useState(false) const mobi = useMobi() diff --git a/src/state/mobiusPools/reducer.ts b/src/state/mobiusPools/reducer.ts index 249218c2a84..f21bd758b70 100644 --- a/src/state/mobiusPools/reducer.ts +++ b/src/state/mobiusPools/reducer.ts @@ -26,6 +26,9 @@ const initialState: Pools = { export default createReducer(initialState, (builder) => builder.addCase(updatePools, (state, { payload: { pools } }) => { - pools + return { + ...state, + pools: pools, + } }) ) diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index 1d2b639b808..552eac118af 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -1,6 +1,6 @@ import { gql, useQuery } from '@apollo/client' import { Interface } from '@ethersproject/abi' -import { TokenAmount } from '@ubeswap/sdk' +import { JSBI, TokenAmount } from '@ubeswap/sdk' import { RECOMMENDED_AMP, RECOMMENDED_FEES, StablePools } from 'constants/pools' import { useEffect } from 'react' import { useDispatch } from 'react-redux' @@ -45,8 +45,6 @@ export function UpdatePools() { ` const { data, loading, error } = useQuery(query) - console.log('data', lpTotalSupply[0]?.result?.[0].toString()) - useEffect(() => { if (loading) return const inSubgraph: Set = @@ -55,6 +53,7 @@ export function UpdatePools() { dispatch( updatePools({ pools: stablePools.map((displayPool, i) => { + console.log(i, new TokenAmount(displayPool.pool.lpToken, JSBI.BigInt(lpTotalSupply[i]?.result?.[0]) ?? '0')) return { ...displayPool.pool, fees: RECOMMENDED_FEES, @@ -62,7 +61,7 @@ export function UpdatePools() { ampFactor: RECOMMENDED_AMP, lpTotalSupply: new TokenAmount( displayPool.pool.lpToken, - BigIntToJSBI(lpTotalSupply[i]?.result?.[0] as BigInt) ?? '0' + JSBI.BigInt(lpTotalSupply[i]?.result?.[0]) ?? '0' ), reserves: balances?.[i]?.result?.[0] ? balances?.[i]?.result?.[0].map( From a74b6e17b2419a65660c44fc82152e3ef67268c3 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 24 Feb 2022 18:28:58 -0500 Subject: [PATCH 13/72] change hooks to use stablePools --- src/hooks/Tokens.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hooks/Tokens.ts b/src/hooks/Tokens.ts index 59bb6efcbc5..7563cb4e239 100644 --- a/src/hooks/Tokens.ts +++ b/src/hooks/Tokens.ts @@ -1,17 +1,15 @@ import { Token } from '@ubeswap/sdk' import { MENTO_POOL_INFO } from 'constants/mento' +import { StablePools } from 'constants/pools' import { stableToToken } from 'state/mentoPools/hooks' import { dedupeTokens } from 'utils/tokens' import { CHAIN } from '../constants' -import { STATIC_POOL_INFO } from '../constants/StablePools' import { CELO, ExternalRewards, MOBI, VEMOBI } from '../constants/tokens' import { isAddress } from '../utils' export function useSwappableTokens(mento: boolean): Token[] { - return dedupeTokens( - mento ? getMentoTokens() : STATIC_POOL_INFO[CHAIN].filter((pool) => !pool.disabled).flatMap(({ tokens }) => tokens) - ) + return dedupeTokens(mento ? getMentoTokens() : StablePools[CHAIN].flatMap((display) => display.pool.tokens)) } export function getMentoTokens(): Token[] { @@ -19,7 +17,7 @@ export function getMentoTokens(): Token[] { } export function getAllTokens(): Token[] | null { - const StableTokensWithDup = STATIC_POOL_INFO[CHAIN].flatMap((pools) => pools.tokens) + const StableTokensWithDup = StablePools[CHAIN].flatMap((display) => display.pool.tokens) const MentoTokensWithDup = getMentoTokens() return dedupeTokens(MentoTokensWithDup.concat(StableTokensWithDup).concat(ExternalRewards[CHAIN])) } From 9544c254ff1ca502afe5b20a38fa303d865568a2 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 24 Feb 2022 18:29:54 -0500 Subject: [PATCH 14/72] remove duplicate mobi from constants --- src/constants/StablePools.ts | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/constants/StablePools.ts b/src/constants/StablePools.ts index 826c024ee79..07f7e5071f9 100644 --- a/src/constants/StablePools.ts +++ b/src/constants/StablePools.ts @@ -8,19 +8,6 @@ import ethLogo from '../assets/images/ethereum-chain-logo.png' import polygonLogo from '../assets/images/polygon-chain-logo.png' import terraLogo from '../assets/images/terra-logo.png' -const mobiToken = (chainId: number, address: string) => - new WrappedTokenInfo( - { - chainId, - address, - decimals: 18, - symbol: 'MOBI', - name: 'Mobius DAO Token', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_MOBI.png', - }, - [] - ) - export enum Coins { Bitcoin, Ether, @@ -100,12 +87,6 @@ export const MOBIUS_MINTER_ADDRESS: { [K in ChainId]: string } = { [ChainId.BAKLAVA]: '', } -export const MOBI_TOKEN: { [K in ChainId]: Token | undefined } = { - [ChainId.MAINNET]: mobiToken(ChainId.MAINNET, '0x73a210637f6F6B7005512677Ba6B3C96bb4AA44B'), - [ChainId.ALFAJORES]: mobiToken(ChainId.ALFAJORES, '0x6dDcbC22c1ED5D0662635ffb020c82DF4e1Ba234'), - [ChainId.BAKLAVA]: undefined, -} - export const GAUGE_CONTROLLER: { [K in ChainId]: string } = { [ChainId.MAINNET]: '0x7530E03056D3a8eD0323e61091ea2f17a1aC5C25', [ChainId.ALFAJORES]: '0x00063Fbe0c90834EE90C6191d0D9F04eaB01A14f', From 1ad09e887e4a1bb100c31b4d3471d0e787a8766a Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 24 Feb 2022 18:32:48 -0500 Subject: [PATCH 15/72] move tokensTradeable to Token hooks --- src/components/SearchModal/CurrencySearch.tsx | 3 +-- src/hooks/Tokens.ts | 18 ++++++++++++++- src/state/stake/hooks.ts | 23 ------------------- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/components/SearchModal/CurrencySearch.tsx b/src/components/SearchModal/CurrencySearch.tsx index 0a4c36d6a11..26d1b6103c0 100644 --- a/src/components/SearchModal/CurrencySearch.tsx +++ b/src/components/SearchModal/CurrencySearch.tsx @@ -13,8 +13,7 @@ import { useOpticsV1Tokens, useOpticsV2Tokens } from 'state/openSum/hooks' import styled from 'styled-components' import { CHAIN } from '../../constants' -import { useSwappableTokens } from '../../hooks/Tokens' -import { useTokensTradeable } from '../../state/stake/hooks' +import { useSwappableTokens, useTokensTradeable } from '../../hooks/Tokens' import { CloseIcon, TYPE } from '../../theme' import { isAddress } from '../../utils' import Column from '../Column' diff --git a/src/hooks/Tokens.ts b/src/hooks/Tokens.ts index 7563cb4e239..7a07e9cca31 100644 --- a/src/hooks/Tokens.ts +++ b/src/hooks/Tokens.ts @@ -1,6 +1,6 @@ import { Token } from '@ubeswap/sdk' import { MENTO_POOL_INFO } from 'constants/mento' -import { StablePools } from 'constants/pools' +import { IExchange, StablePools } from 'constants/pools' import { stableToToken } from 'state/mentoPools/hooks' import { dedupeTokens } from 'utils/tokens' @@ -8,6 +8,22 @@ import { CHAIN } from '../constants' import { CELO, ExternalRewards, MOBI, VEMOBI } from '../constants/tokens' import { isAddress } from '../utils' +function inPool(token: Token, pool: IExchange): boolean { + return pool.tokens.map((t) => t.address === token.address && t.chainId === token.chainId).includes(true) +} + +export function useTokensTradeable(mento: boolean, tokenIn: Token | null | undefined): Token[] { + if (!tokenIn) return [] + const pools = mento + ? tokenIn === CELO[CHAIN] + ? MENTO_POOL_INFO[CHAIN].map((m) => stableToToken(m.stable)) + : [CELO[CHAIN]] + : StablePools[CHAIN].filter((display) => inPool(tokenIn, display.pool)) + .flatMap((display) => display.pool.tokens) + .filter((token) => token !== tokenIn) + return dedupeTokens(pools) +} + export function useSwappableTokens(mento: boolean): Token[] { return dedupeTokens(mento ? getMentoTokens() : StablePools[CHAIN].flatMap((display) => display.pool.tokens)) } diff --git a/src/state/stake/hooks.ts b/src/state/stake/hooks.ts index 637d67a2468..09c7d4ef162 100644 --- a/src/state/stake/hooks.ts +++ b/src/state/stake/hooks.ts @@ -1,32 +1,9 @@ import { JSBI, Token, TokenAmount } from '@ubeswap/sdk' -import { MENTO_POOL_INFO } from 'constants/mento' -import { CELO } from 'constants/tokens' -import { stableToToken } from 'state/mentoPools/hooks' -import { StableSwapConstants } from 'state/stablePools/reducer' -import { dedupeTokens } from 'utils/tokens' // Hooks -import { CHAIN } from '../../constants' -import { STATIC_POOL_INFO } from '../../constants/StablePools' import { useWeb3Context } from '../../hooks' import { tryParseAmount } from '../swap/hooks' -function inPool(token: Token, pool: StableSwapConstants): boolean { - return pool.tokens.map((t) => t.address === token.address && t.chainId === token.chainId).includes(true) -} - -export function useTokensTradeable(mento: boolean, tokenIn: Token | null | undefined): Token[] { - if (!tokenIn) return [] - const pools = mento - ? tokenIn === CELO[CHAIN] - ? MENTO_POOL_INFO[CHAIN].map((m) => stableToToken(m.stable)) - : [CELO[CHAIN]] - : STATIC_POOL_INFO[CHAIN].filter((pool) => !pool.disabled && inPool(tokenIn, pool)) - .flatMap(({ tokens }) => tokens) - .filter((token) => token !== tokenIn) - return dedupeTokens(pools) -} - // based on typed value export function useDerivedStakeInfo( typedValue: string, From 9db5449f8950f35e756f7412bdaba76cdcab3691 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 24 Feb 2022 18:42:33 -0500 Subject: [PATCH 16/72] added token --- src/constants/pools.ts | 6 ++---- src/constants/tokens.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/constants/pools.ts b/src/constants/pools.ts index b5fa3abc018..0fd6159ec35 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -1,7 +1,7 @@ import { ChainId, Percent, Token, TokenAmount } from '@ubeswap/sdk' import JSBI from 'jsbi' -import { CUSD } from './tokens' +import { CUSD, UST } from './tokens' export type Fees = { trade: Percent @@ -119,8 +119,6 @@ export interface DisplayPool { warningType?: WarningType } -const UST = new Token(ChainId.MAINNET, '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', 18, 'UST', 'UST') - const recommendedFeesRaw = { adminFeeNumerator: '50', adminFeeDenominator: '100', @@ -156,7 +154,7 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { 'MobLP', 'Mobius cUSD/aUST LP' ), - tokens: [CUSD[ChainId.MAINNET], UST], + tokens: [CUSD[ChainId.MAINNET], UST[ChainId.MAINNET]], }, gauge: { address: '0x107F94409746E8c8E6eFF139A100D17D9ca7FdfE', diff --git a/src/constants/tokens.ts b/src/constants/tokens.ts index 5b4418bdcfa..e38604e14f5 100644 --- a/src/constants/tokens.ts +++ b/src/constants/tokens.ts @@ -17,6 +17,18 @@ const makeTokens = ( }) } +export const UST = makeTokens( + { + [ChainId.MAINNET]: '0x73a210637f6F6B7005512677Ba6B3C96bb4AA44B', + [ChainId.ALFAJORES]: '0x17a139f275102bBaB5BcbF1c4b7143F08B635EA2', + [ChainId.BAKLAVA]: '0x00Be915B9dCf56a3CBE739D9B9c202ca692409EC', + }, + 18, + 'MOBI', + 'Mobius DAO Token', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_MOBI.png' +) + export const MOBI = makeTokens( { [ChainId.MAINNET]: '0x73a210637f6F6B7005512677Ba6B3C96bb4AA44B', From 680da8e78444ae14dfc96d3d81a36fddeafe7468 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 24 Feb 2022 18:44:39 -0500 Subject: [PATCH 17/72] move ust --- src/constants/tokens.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/constants/tokens.ts b/src/constants/tokens.ts index e38604e14f5..0e46534f0e0 100644 --- a/src/constants/tokens.ts +++ b/src/constants/tokens.ts @@ -19,14 +19,14 @@ const makeTokens = ( export const UST = makeTokens( { - [ChainId.MAINNET]: '0x73a210637f6F6B7005512677Ba6B3C96bb4AA44B', - [ChainId.ALFAJORES]: '0x17a139f275102bBaB5BcbF1c4b7143F08B635EA2', - [ChainId.BAKLAVA]: '0x00Be915B9dCf56a3CBE739D9B9c202ca692409EC', + [ChainId.MAINNET]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', + [ChainId.ALFAJORES]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', + [ChainId.BAKLAVA]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', }, 18, - 'MOBI', - 'Mobius DAO Token', - 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_MOBI.png' + 'UST', + 'TerraUSD', + 'https://raw.githubusercontent.com/kyscott18/default-token-list/master/assets/asset_UST.png' ) export const MOBI = makeTokens( From 113859ee43214519b2bfc38d64ca76f8a74500ca Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 24 Feb 2022 19:01:07 -0500 Subject: [PATCH 18/72] add mobi rate to staking --- src/state/mentoPools/actions.ts | 2 +- src/state/staking/reducer.ts | 2 ++ src/state/staking/updater.ts | 6 +++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/state/mentoPools/actions.ts b/src/state/mentoPools/actions.ts index 2e53938c10e..06be82b0d1f 100644 --- a/src/state/mentoPools/actions.ts +++ b/src/state/mentoPools/actions.ts @@ -1,4 +1,4 @@ import { createAction } from '@reduxjs/toolkit' import { IMentoExchange, IMentoExchangeInfo } from 'constants/mento' -export const updateMento = createAction<{ mento: IMentoExchangeInfo & IMentoExchange }>('mentoPools/initPools') +export const updateMento = createAction<{ mento: IMentoExchangeInfo & IMentoExchange }>('mentoPools/update') diff --git a/src/state/staking/reducer.ts b/src/state/staking/reducer.ts index c5a6e4b01a1..a3b7e3445dc 100644 --- a/src/state/staking/reducer.ts +++ b/src/state/staking/reducer.ts @@ -15,6 +15,7 @@ export type IStakingState = { externalRewardsRate: JSBI feesThisWeek: JSBI feesNextWeek: JSBI + mobiRate: JSBI } export type IUserStakingState = { @@ -32,6 +33,7 @@ const initialStakingState: IStakingState = { externalRewardsRate: JSBI.BigInt(0), feesThisWeek: JSBI.BigInt(0), feesNextWeek: JSBI.BigInt(0), + mobiRate: JSBI.BigInt(0), } const initialUserStakingState: IUserStakingState = { diff --git a/src/state/staking/updater.ts b/src/state/staking/updater.ts index 96cbf79d0e1..d8ab52a69cc 100644 --- a/src/state/staking/updater.ts +++ b/src/state/staking/updater.ts @@ -1,5 +1,6 @@ import { JSBI } from '@ubeswap/sdk' import { ExternalStakingRewards } from 'constants/staking' +import { VEMOBI } from 'constants/tokens' import { useWeb3Context } from 'hooks' import { roundDate } from 'pages/Staking/Lock' import { useEffect } from 'react' @@ -35,8 +36,9 @@ export default function StakingUpdater() { const totalVotingPower = useSingleCallResult(votingEscrow, 'totalSupply()') const totalWeight = useSingleCallResult(controller, 'get_total_weight') - const totalMobiLocked = useSingleCallResult(mobiContract, 'balanceOf(address)', [votingEscrow?.address ?? undefined]) + const totalMobiLocked = useSingleCallResult(mobiContract, 'balanceOf(address)', [VEMOBI[CHAIN].address]) const snxRewardRate = useSingleCallResult(snxContract, 'rewardRate()') + const mobiRate = useSingleCallResult(mobiContract, 'rate') const feesToClaim = useSingleCallResult(feeDistributorContract, 'claim()') const totalFeesNextWeek = useSingleCallResult(feeDistributorContract, 'tokens_per_week', [ @@ -70,6 +72,7 @@ export default function StakingUpdater() { externalRewardsRate: JSBI.BigInt(snxRewardRate?.result?.[0] ?? '0'), feesThisWeek: JSBI.BigInt(totalFeesThisWeek?.result?.[0] ?? '0'), feesNextWeek: JSBI.BigInt(totalFeesNextWeek?.result?.[0] ?? '0'), + mobiRate: JSBI.BigInt(mobiRate?.result?.[0] ?? '0'), }, }) ) @@ -80,6 +83,7 @@ export default function StakingUpdater() { feesToClaim?.result, locked?.result?.amount, locked?.result?.end, + mobiRate?.result, snxRewardRate?.result, snxToClaim?.result, totalFeesNextWeek?.result, From 73b2662873d04c28394dcbf83ff2291a08789547 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Fri, 25 Feb 2022 19:57:29 -0500 Subject: [PATCH 19/72] gauge reducer --- src/constants/pools.ts | 4 -- src/index.tsx | 2 + src/state/gauges/actions.ts | 6 ++ src/state/gauges/hooks.ts | 42 +++++++++++++ src/state/gauges/reducer.ts | 72 ++++++++++++++++++++++ src/state/gauges/updater.ts | 101 +++++++++++++++++++++++++++++++ src/state/index.ts | 2 + src/state/mobiusPools/updater.ts | 3 - src/state/stablePools/updater.ts | 4 +- src/state/staking/reducer.ts | 17 +++--- src/state/staking/updater.ts | 2 - 11 files changed, 236 insertions(+), 19 deletions(-) create mode 100644 src/state/gauges/actions.ts create mode 100644 src/state/gauges/hooks.ts create mode 100644 src/state/gauges/reducer.ts create mode 100644 src/state/gauges/updater.ts diff --git a/src/constants/pools.ts b/src/constants/pools.ts index 0fd6159ec35..601eb9af2c1 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -35,10 +35,6 @@ export interface IGauge { additionalRewardRate?: string[] } -export interface IGaugeInfo { - isKilled?: boolean -} - export interface Volume { volume: { total: number diff --git a/src/index.tsx b/src/index.tsx index 0939f15868d..9d859b5bcd4 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -7,6 +7,7 @@ import React, { StrictMode } from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import { HashRouter } from 'react-router-dom' +import { GaugeUpdater } from 'state/gauges/updater' import { UpdateMento } from 'state/mentoPools/updater' import { UpdatePools } from 'state/mobiusPools/updater' import { UpdateOpenSum } from 'state/openSum/updater' @@ -58,6 +59,7 @@ function Updaters() { + diff --git a/src/state/gauges/actions.ts b/src/state/gauges/actions.ts new file mode 100644 index 00000000000..0c7351685ed --- /dev/null +++ b/src/state/gauges/actions.ts @@ -0,0 +1,6 @@ +import { createAction } from '@reduxjs/toolkit' + +import { IGaugeInfo, IUserGaugeInfo } from './reducer' + +export const updateGauges = createAction<{ gaugeState: (IGaugeInfo | null)[] }>('gauges/update') +export const updateGaugesUser = createAction<{ userGaugeState: (IUserGaugeInfo | null)[] }>('gauges/updateUser') diff --git a/src/state/gauges/hooks.ts b/src/state/gauges/hooks.ts new file mode 100644 index 00000000000..3fa4b879e50 --- /dev/null +++ b/src/state/gauges/hooks.ts @@ -0,0 +1,42 @@ +import { IExchangeInfo, Volume } from 'constants/pools' +import { useSelector } from 'react-redux' +import invariant from 'tiny-invariant' + +import { AppState } from '..' + +export function useCurrentPool(token0: string, token1: string): IExchangeInfo | null { + const pools = useSelector((state) => + state.pools.pools.filter((pool) => { + const tokens = pool.tokens.map((t) => t.address) + return tokens.includes(token0) && tokens.includes(token1) + }) + ) + if (pools.length === 0) return null + invariant(pools.length === 1) + return pools[0] +} +export function useCurrentPoolAddress(exchangeAddress: string): IExchangeInfo | null { + const pools = useSelector((state) => + state.pools.pools.filter((pool) => pool.address === exchangeAddress) + ) + if (pools.length === 0) return null + invariant(pools.length === 1) + return pools[0] +} + +export function usePools(): readonly IExchangeInfo[] { + return useSelector((state) => state.pools.pools) +} + +export function useCurrentPoolVolume(exchangeAddress: string): Volume | null { + const pools = useSelector((state) => + state.pools.pools.filter((pool) => pool.address === exchangeAddress) + ) + if (pools.length === 0) return null + invariant(pools.length === 1) + return pools[0] +} + +export function usePoolsVolume(): readonly Volume[] { + return useSelector((state) => state.pools.pools) +} diff --git a/src/state/gauges/reducer.ts b/src/state/gauges/reducer.ts new file mode 100644 index 00000000000..73a5ab6964a --- /dev/null +++ b/src/state/gauges/reducer.ts @@ -0,0 +1,72 @@ +import { createReducer } from '@reduxjs/toolkit' +import { JSBI, Percent } from '@ubeswap/sdk' +import { IGauge, StablePools } from 'constants/pools' + +import { CHAIN } from '../../constants' +import { updateGauges, updateGaugesUser } from './actions' + +export interface Gauges { + readonly gauges: ((IUserGaugeInfo & IGaugeInfo & IGauge) | null)[] +} + +export interface IGaugeInfo { + isKilled: boolean + lastClaim: Date + weight: Percent + futureWeight: Percent + totalSupply: JSBI + workingSupply: JSBI +} + +export interface IUserGaugeInfo { + balance: JSBI + claimableMobi: JSBI + lastVote: number + powerAllocated: number +} + +const initialGaugeInfo: IGaugeInfo = { + isKilled: false, + lastClaim: new Date(), + weight: new Percent('0'), + futureWeight: new Percent('0'), + totalSupply: JSBI.BigInt(0), + workingSupply: JSBI.BigInt(0), +} + +const initialUserGaugeInfo: IUserGaugeInfo = { + balance: JSBI.BigInt(0), + claimableMobi: JSBI.BigInt(0), + lastVote: 0, + powerAllocated: 0, +} + +function emptyExchangeInfo(gauge: IGauge | null): (IGaugeInfo & IUserGaugeInfo & IGauge) | null { + return gauge === null + ? null + : { + ...gauge, + ...initialGaugeInfo, + ...initialUserGaugeInfo, + } +} + +const initialState: Gauges = { + gauges: StablePools[CHAIN].map((p) => emptyExchangeInfo(p.gauge)), +} + +export default createReducer(initialState, (builder) => + builder + .addCase(updateGauges, (state, { payload: { gaugeState } }) => { + const r = state.gauges.map((g, i) => (g ? { ...g, ...gaugeState[i] } : null)) + return { + gauges: r, + } + }) + .addCase(updateGaugesUser, (state, { payload: { userGaugeState } }) => { + const r = state.gauges.map((g, i) => (g ? { ...g, ...userGaugeState[i] } : null)) + return { + gauges: r, + } + }) +) diff --git a/src/state/gauges/updater.ts b/src/state/gauges/updater.ts new file mode 100644 index 00000000000..50b57f44005 --- /dev/null +++ b/src/state/gauges/updater.ts @@ -0,0 +1,101 @@ +import { Interface } from '@ethersproject/abi' +import { JSBI, Percent } from '@ubeswap/sdk' +import { IGauge, StablePools } from 'constants/pools' +import { useWeb3Context } from 'hooks' +import { useEffect } from 'react' +import { useDispatch } from 'react-redux' +import { AppDispatch } from 'state' +import { useBlockNumber } from 'state/application/hooks' +import { useMultipleContractSingleData, useSingleContractMultipleData } from 'state/multicall/hooks' + +import { CHAIN } from '../../constants' +import GAUGE_V3 from '../../constants/abis/LiquidityGaugeV3.json' +import { useGaugeControllerContract, useMobiContract } from '../../hooks/useContract' +import { updateGauges, updateGaugesUser } from './actions' + +const gaugeInterface = new Interface(GAUGE_V3.abi) + +export function GaugeUpdater() { + const { address, connected } = useWeb3Context() + const blockNumber = useBlockNumber() + const dispatch = useDispatch() + const gauges: (IGauge | null)[] = StablePools[CHAIN].map((display) => display.gauge) + const gaugeAddresses = gauges.map((g) => g?.address) + const gaugeController = useGaugeControllerContract() + const mobiContract = useMobiContract() + + const totalSupply = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'totalSupply') + const workingSupply = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_supply') + const totalEffectiveBalances = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_supply') + const weights = useSingleContractMultipleData( + gaugeController, + 'gauge_relative_weight(address)', + gaugeAddresses.map((a) => [a]) + ) + const futureWeights = useSingleContractMultipleData( + gaugeController, + 'get_gauge_weight', + gaugeAddresses.map((a) => [a]) + ) + const lastClaims = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'last_claim') + const isKilled = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'is_killed') + + const balance = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'balanceOf', [ + connected ? address : undefined, + ]) + const claimableMobi = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'claimable_tokens', [ + connected ? address : undefined, + ]) + const effectiveBalances = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_balances', [ + connected ? address : undefined, + ]) + const lastVote = useSingleContractMultipleData( + gaugeController, + 'last_user_vote', + gaugeAddresses.map((a) => [connected ? address : a, a]) + ) + // vote_user_slopes + const slopes = useSingleContractMultipleData( + gaugeController, + 'vote_user_slopes', + gaugeAddresses.map((a) => [connected ? address : a, a]) + ) + + console.log('returl', lastVote[0].result?.[0].toString()) + + useEffect(() => { + connected && + dispatch( + updateGaugesUser({ + userGaugeState: StablePools[CHAIN].map((displayPool, i) => { + return displayPool === null + ? null + : { + balance: JSBI.BigInt(balance[i].result?.[0]), + claimableMobi: JSBI.BigInt(claimableMobi[i].result?.[0]), + lastVote: parseInt((lastVote?.[i]?.result?.[0] ?? BigInt('0')).toString() ?? '0'), + powerAllocated: parseInt((slopes?.[i]?.result?.[1] ?? BigInt('0')).toString() ?? '0'), + } + }), + }) + ) + dispatch( + updateGauges({ + gaugeState: StablePools[CHAIN].map((display, i) => { + return display === null + ? null + : { + isKilled: isKilled[0].result?.[0] === false, + lastClaim: new Date(), + weight: new Percent('0'), + futureWeight: new Percent('0'), + totalSupply: JSBI.BigInt(0), + workingSupply: JSBI.BigInt(0), + } + }), + }) + ) + }, [connected, dispatch, blockNumber, balance, claimableMobi, lastVote, slopes]) + + return null +} diff --git a/src/state/index.ts b/src/state/index.ts index ff2ae283d97..2b8c3fc9bd0 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -4,6 +4,7 @@ import { load, save } from 'redux-localstorage-simple' import application from './application/reducer' import burn from './burn/reducer' import claim from './claim/reducer' +import gauges from './gauges/reducer' import { updateVersion } from './global/actions' import logs from './logs/slice' import mento from './mento/reducer' @@ -35,6 +36,7 @@ const store = configureStore({ mento, claim, staking, + gauges, logs, openSum, }, diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index 552eac118af..f456d66c290 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -53,7 +53,6 @@ export function UpdatePools() { dispatch( updatePools({ pools: stablePools.map((displayPool, i) => { - console.log(i, new TokenAmount(displayPool.pool.lpToken, JSBI.BigInt(lpTotalSupply[i]?.result?.[0]) ?? '0')) return { ...displayPool.pool, fees: RECOMMENDED_FEES, @@ -73,9 +72,7 @@ export function UpdatePools() { }), }) ) - console.log('updated') } catch (error) { - console.log('error') console.error(error) } }, [loading, data?.swaps, dispatch, stablePools, lpTotalSupply, blockNumber, balances]) diff --git a/src/state/stablePools/updater.ts b/src/state/stablePools/updater.ts index 0b70b0e9a3e..9682785a03b 100644 --- a/src/state/stablePools/updater.ts +++ b/src/state/stablePools/updater.ts @@ -168,13 +168,13 @@ export function BatchUpdateGauges(): null { connected ? address : undefined, ]) const totalEffectiveBalances = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_supply') - const lastUserVotes = useSingleContractMultipleData( + const lastVote = useSingleContractMultipleData( gaugeController, 'last_user_vote', gaugeAddresses.map((a) => [connected ? address : a, a]) ) // vote_user_slopes - const slopes = useSingleContractMultipleData( + const slope = useSingleContractMultipleData( gaugeController, 'vote_user_slopes', gaugeAddresses.map((a) => [connected ? address : a, a]) diff --git a/src/state/staking/reducer.ts b/src/state/staking/reducer.ts index a3b7e3445dc..a1b0db3411f 100644 --- a/src/state/staking/reducer.ts +++ b/src/state/staking/reducer.ts @@ -50,12 +50,13 @@ const initialState: IStakingState & IUserStakingState = { } export default createReducer(initialState, (builder) => { - builder.addCase(updateStaking, (state, { payload: { stakingState } }) => ({ - ...state, - ...stakingState, - })) - builder.addCase(updateStakingUser, (state, { payload: { userStakingState } }) => ({ - ...state, - ...userStakingState, - })) + builder + .addCase(updateStaking, (state, { payload: { stakingState } }) => ({ + ...state, + ...stakingState, + })) + .addCase(updateStakingUser, (state, { payload: { userStakingState } }) => ({ + ...state, + ...userStakingState, + })) }) diff --git a/src/state/staking/updater.ts b/src/state/staking/updater.ts index d8ab52a69cc..4c4916a3445 100644 --- a/src/state/staking/updater.ts +++ b/src/state/staking/updater.ts @@ -18,8 +18,6 @@ import { } from '../../hooks/useContract' import { updateStaking, updateStakingUser } from './actions' -// pools, general staking, general gauges, user staking, user gauges - export default function StakingUpdater() { const dispatch = useDispatch() const mobiContract = useMobiContract() From af9dca4eae6e8dfebccabb109355e2c6faa6f272 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sat, 26 Feb 2022 21:40:44 -0500 Subject: [PATCH 20/72] gauge reducer working --- src/index.tsx | 5 ++-- src/state/gauges/hooks.ts | 41 ++++---------------------------- src/state/gauges/reducer.ts | 18 ++++++++------ src/state/gauges/updater.ts | 41 ++++++++++++++++++++++---------- src/state/mobiusPools/updater.ts | 1 - 5 files changed, 45 insertions(+), 61 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 9d859b5bcd4..c453dda7980 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -11,7 +11,6 @@ import { GaugeUpdater } from 'state/gauges/updater' import { UpdateMento } from 'state/mentoPools/updater' import { UpdatePools } from 'state/mobiusPools/updater' import { UpdateOpenSum } from 'state/openSum/updater' -import { BatchUpdateGauges, UpdateVariablePoolInfo } from 'state/stablePools/updater' import StakingUpdater from 'state/staking/updater' import { Web3ContextProvider } from './hooks' @@ -58,9 +57,9 @@ function Updaters() { - + {/* */} - + {/* */} diff --git a/src/state/gauges/hooks.ts b/src/state/gauges/hooks.ts index 3fa4b879e50..d4b82bd6177 100644 --- a/src/state/gauges/hooks.ts +++ b/src/state/gauges/hooks.ts @@ -1,42 +1,9 @@ -import { IExchangeInfo, Volume } from 'constants/pools' +import { IGauge } from 'constants/pools' import { useSelector } from 'react-redux' -import invariant from 'tiny-invariant' import { AppState } from '..' +import { IGaugeInfo, IUserGaugeInfo } from './reducer' -export function useCurrentPool(token0: string, token1: string): IExchangeInfo | null { - const pools = useSelector((state) => - state.pools.pools.filter((pool) => { - const tokens = pool.tokens.map((t) => t.address) - return tokens.includes(token0) && tokens.includes(token1) - }) - ) - if (pools.length === 0) return null - invariant(pools.length === 1) - return pools[0] -} -export function useCurrentPoolAddress(exchangeAddress: string): IExchangeInfo | null { - const pools = useSelector((state) => - state.pools.pools.filter((pool) => pool.address === exchangeAddress) - ) - if (pools.length === 0) return null - invariant(pools.length === 1) - return pools[0] -} - -export function usePools(): readonly IExchangeInfo[] { - return useSelector((state) => state.pools.pools) -} - -export function useCurrentPoolVolume(exchangeAddress: string): Volume | null { - const pools = useSelector((state) => - state.pools.pools.filter((pool) => pool.address === exchangeAddress) - ) - if (pools.length === 0) return null - invariant(pools.length === 1) - return pools[0] -} - -export function usePoolsVolume(): readonly Volume[] { - return useSelector((state) => state.pools.pools) +export function useGauges(): readonly ((IUserGaugeInfo & IGaugeInfo & IGauge) | null)[] { + return useSelector((state) => state.gauges.gauges) } diff --git a/src/state/gauges/reducer.ts b/src/state/gauges/reducer.ts index 73a5ab6964a..ad67eccfcfc 100644 --- a/src/state/gauges/reducer.ts +++ b/src/state/gauges/reducer.ts @@ -1,5 +1,5 @@ import { createReducer } from '@reduxjs/toolkit' -import { JSBI, Percent } from '@ubeswap/sdk' +import { JSBI } from '@ubeswap/sdk' import { IGauge, StablePools } from 'constants/pools' import { CHAIN } from '../../constants' @@ -11,11 +11,12 @@ export interface Gauges { export interface IGaugeInfo { isKilled: boolean - lastClaim: Date - weight: Percent - futureWeight: Percent + lastClaim: number + weight: JSBI + futureWeight: JSBI totalSupply: JSBI workingSupply: JSBI + totalEffectiveBalance: JSBI } export interface IUserGaugeInfo { @@ -23,15 +24,17 @@ export interface IUserGaugeInfo { claimableMobi: JSBI lastVote: number powerAllocated: number + effectiveBalance: JSBI } const initialGaugeInfo: IGaugeInfo = { isKilled: false, - lastClaim: new Date(), - weight: new Percent('0'), - futureWeight: new Percent('0'), + lastClaim: 0, + weight: JSBI.BigInt('0'), + futureWeight: JSBI.BigInt('0'), totalSupply: JSBI.BigInt(0), workingSupply: JSBI.BigInt(0), + totalEffectiveBalance: JSBI.BigInt(0), } const initialUserGaugeInfo: IUserGaugeInfo = { @@ -39,6 +42,7 @@ const initialUserGaugeInfo: IUserGaugeInfo = { claimableMobi: JSBI.BigInt(0), lastVote: 0, powerAllocated: 0, + effectiveBalance: JSBI.BigInt(0), } function emptyExchangeInfo(gauge: IGauge | null): (IGaugeInfo & IUserGaugeInfo & IGauge) | null { diff --git a/src/state/gauges/updater.ts b/src/state/gauges/updater.ts index 50b57f44005..d620de95fa8 100644 --- a/src/state/gauges/updater.ts +++ b/src/state/gauges/updater.ts @@ -1,5 +1,5 @@ import { Interface } from '@ethersproject/abi' -import { JSBI, Percent } from '@ubeswap/sdk' +import { JSBI } from '@ubeswap/sdk' import { IGauge, StablePools } from 'constants/pools' import { useWeb3Context } from 'hooks' import { useEffect } from 'react' @@ -10,7 +10,7 @@ import { useMultipleContractSingleData, useSingleContractMultipleData } from 'st import { CHAIN } from '../../constants' import GAUGE_V3 from '../../constants/abis/LiquidityGaugeV3.json' -import { useGaugeControllerContract, useMobiContract } from '../../hooks/useContract' +import { useGaugeControllerContract } from '../../hooks/useContract' import { updateGauges, updateGaugesUser } from './actions' const gaugeInterface = new Interface(GAUGE_V3.abi) @@ -22,7 +22,6 @@ export function GaugeUpdater() { const gauges: (IGauge | null)[] = StablePools[CHAIN].map((display) => display.gauge) const gaugeAddresses = gauges.map((g) => g?.address) const gaugeController = useGaugeControllerContract() - const mobiContract = useMobiContract() const totalSupply = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'totalSupply') const workingSupply = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_supply') @@ -61,8 +60,6 @@ export function GaugeUpdater() { gaugeAddresses.map((a) => [connected ? address : a, a]) ) - console.log('returl', lastVote[0].result?.[0].toString()) - useEffect(() => { connected && dispatch( @@ -73,8 +70,9 @@ export function GaugeUpdater() { : { balance: JSBI.BigInt(balance[i].result?.[0]), claimableMobi: JSBI.BigInt(claimableMobi[i].result?.[0]), - lastVote: parseInt((lastVote?.[i]?.result?.[0] ?? BigInt('0')).toString() ?? '0'), - powerAllocated: parseInt((slopes?.[i]?.result?.[1] ?? BigInt('0')).toString() ?? '0'), + lastVote: parseInt(lastVote[i]?.result?.[0].toString() ?? '0'), + powerAllocated: parseInt(slopes[i]?.result?.[1] ?? '0'), + effectiveBalance: JSBI.BigInt(effectiveBalances[i].result?.[0]), } }), }) @@ -86,16 +84,33 @@ export function GaugeUpdater() { ? null : { isKilled: isKilled[0].result?.[0] === false, - lastClaim: new Date(), - weight: new Percent('0'), - futureWeight: new Percent('0'), - totalSupply: JSBI.BigInt(0), - workingSupply: JSBI.BigInt(0), + lastClaim: parseInt(lastClaims?.[i]?.result?.[0].toString() ?? '0'), + weight: JSBI.BigInt(weights[i].result?.[0] ?? 0), + futureWeight: JSBI.BigInt(futureWeights[i].result?.[0] ?? 0), + totalSupply: JSBI.BigInt(totalSupply[i].result?.[0] ?? 0), + workingSupply: JSBI.BigInt(workingSupply[i].result?.[0] ?? 0), + totalEffectiveBalance: JSBI.BigInt(totalEffectiveBalances[i].result?.[0] ?? 0), } }), }) ) - }, [connected, dispatch, blockNumber, balance, claimableMobi, lastVote, slopes]) + }, [ + connected, + dispatch, + blockNumber, + balance, + claimableMobi, + lastVote, + slopes, + isKilled, + lastClaims, + totalSupply, + workingSupply, + weights, + futureWeights, + effectiveBalances, + totalEffectiveBalances, + ]) return null } diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index f456d66c290..8f5af1d9d61 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -24,7 +24,6 @@ export function UpdatePools() { const lpTokenAddress = stablePools.map((p) => p.pool.lpToken.address) const poolAddress = stablePools.map((p) => p.pool.address) const lpTotalSupply = useMultipleContractSingleData(lpTokenAddress, lpInterface, 'totalSupply') - console.log('lp', lpTotalSupply) const balances = useMultipleContractSingleData(poolAddress, SwapInterface, 'getBalances') const query = gql` From e196748fda1dc9adcd08ba3a8ebb455d97b8cdc5 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sat, 26 Feb 2022 21:43:34 -0500 Subject: [PATCH 21/72] gauge update bug fix: --- src/state/gauges/updater.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/state/gauges/updater.ts b/src/state/gauges/updater.ts index d620de95fa8..04d21d22427 100644 --- a/src/state/gauges/updater.ts +++ b/src/state/gauges/updater.ts @@ -68,11 +68,11 @@ export function GaugeUpdater() { return displayPool === null ? null : { - balance: JSBI.BigInt(balance[i].result?.[0]), - claimableMobi: JSBI.BigInt(claimableMobi[i].result?.[0]), - lastVote: parseInt(lastVote[i]?.result?.[0].toString() ?? '0'), - powerAllocated: parseInt(slopes[i]?.result?.[1] ?? '0'), - effectiveBalance: JSBI.BigInt(effectiveBalances[i].result?.[0]), + balance: JSBI.BigInt(balance[i].result?.[0] ?? '0'), + claimableMobi: JSBI.BigInt(claimableMobi[i].result?.[0] ?? '0'), + lastVote: parseInt(lastVote[i].result?.[0].toString() ?? '0'), + powerAllocated: parseInt(slopes[i].result?.[1] ?? '0'), + effectiveBalance: JSBI.BigInt(effectiveBalances[i].result?.[0] ?? '0'), } }), }) From 3a890e33334b153ea5ccbe7f5e5eed99ef093eaf Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 09:06:57 -0500 Subject: [PATCH 22/72] remove mint and burn reducer --- src/state/burn/actions.ts | 10 ------- src/state/burn/reducer.ts | 23 ---------------- src/state/index.ts | 4 --- src/state/mint/actions.ts | 9 ------- src/state/mint/reducer.test.ts | 28 -------------------- src/state/mint/reducer.ts | 48 ---------------------------------- 6 files changed, 122 deletions(-) delete mode 100644 src/state/burn/actions.ts delete mode 100644 src/state/burn/reducer.ts delete mode 100644 src/state/mint/actions.ts delete mode 100644 src/state/mint/reducer.test.ts delete mode 100644 src/state/mint/reducer.ts diff --git a/src/state/burn/actions.ts b/src/state/burn/actions.ts deleted file mode 100644 index e746699fb72..00000000000 --- a/src/state/burn/actions.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createAction } from '@reduxjs/toolkit' - -export enum Field { - LIQUIDITY_PERCENT = 'LIQUIDITY_PERCENT', - LIQUIDITY = 'LIQUIDITY', - CURRENCY_A = 'CURRENCY_A', - CURRENCY_B = 'CURRENCY_B', -} - -export const typeInput = createAction<{ field: Field; typedValue: string }>('burn/typeInputBurn') diff --git a/src/state/burn/reducer.ts b/src/state/burn/reducer.ts deleted file mode 100644 index 188ff4e46bd..00000000000 --- a/src/state/burn/reducer.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { createReducer } from '@reduxjs/toolkit' - -import { Field, typeInput } from './actions' - -export interface BurnState { - readonly independentField: Field - readonly typedValue: string -} - -const initialState: BurnState = { - independentField: Field.LIQUIDITY_PERCENT, - typedValue: '0', -} - -export default createReducer(initialState, (builder) => - builder.addCase(typeInput, (state, { payload: { field, typedValue } }) => { - return { - ...state, - independentField: field, - typedValue, - } - }) -) diff --git a/src/state/index.ts b/src/state/index.ts index 2b8c3fc9bd0..c9f23a61949 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -2,14 +2,12 @@ import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit' import { load, save } from 'redux-localstorage-simple' import application from './application/reducer' -import burn from './burn/reducer' import claim from './claim/reducer' import gauges from './gauges/reducer' import { updateVersion } from './global/actions' import logs from './logs/slice' import mento from './mento/reducer' import mentoPools from './mentoPools/reducer' -import mint from './mint/reducer' import pools from './mobiusPools/reducer' import multicall from './multicall/reducer' import openSum from './openSum/reducer' @@ -27,8 +25,6 @@ const store = configureStore({ user, transactions, swap, - mint, - burn, multicall, stablePools, pools, diff --git a/src/state/mint/actions.ts b/src/state/mint/actions.ts deleted file mode 100644 index 4fcd912c514..00000000000 --- a/src/state/mint/actions.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createAction } from '@reduxjs/toolkit' - -export enum Field { - CURRENCY_A = 'CURRENCY_A', - CURRENCY_B = 'CURRENCY_B', -} - -export const typeInput = createAction<{ field: Field; typedValue: string; noLiquidity: boolean }>('mint/typeInputMint') -export const resetMintState = createAction('mint/resetMintState') diff --git a/src/state/mint/reducer.test.ts b/src/state/mint/reducer.test.ts deleted file mode 100644 index 92abd422779..00000000000 --- a/src/state/mint/reducer.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { createStore, Store } from 'redux' - -import { Field, typeInput } from './actions' -import reducer, { MintState } from './reducer' - -describe('mint reducer', () => { - let store: Store - - beforeEach(() => { - store = createStore(reducer, { - independentField: Field.CURRENCY_A, - typedValue: '', - otherTypedValue: '', - }) - }) - - describe('typeInput', () => { - it('sets typed value', () => { - store.dispatch(typeInput({ field: Field.CURRENCY_A, typedValue: '1.0', noLiquidity: false })) - expect(store.getState()).toEqual({ independentField: Field.CURRENCY_A, typedValue: '1.0', otherTypedValue: '' }) - }) - it('clears other value', () => { - store.dispatch(typeInput({ field: Field.CURRENCY_A, typedValue: '1.0', noLiquidity: false })) - store.dispatch(typeInput({ field: Field.CURRENCY_B, typedValue: '1.0', noLiquidity: false })) - expect(store.getState()).toEqual({ independentField: Field.CURRENCY_B, typedValue: '1.0', otherTypedValue: '' }) - }) - }) -}) diff --git a/src/state/mint/reducer.ts b/src/state/mint/reducer.ts deleted file mode 100644 index 6de567875f8..00000000000 --- a/src/state/mint/reducer.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { createReducer } from '@reduxjs/toolkit' - -import { Field, resetMintState, typeInput } from './actions' - -export interface MintState { - readonly independentField: Field - readonly typedValue: string - readonly otherTypedValue: string // for the case when there's no liquidity -} - -const initialState: MintState = { - independentField: Field.CURRENCY_A, - typedValue: '', - otherTypedValue: '', -} - -export default createReducer(initialState, (builder) => - builder - .addCase(resetMintState, () => initialState) - .addCase(typeInput, (state, { payload: { field, typedValue, noLiquidity } }) => { - if (noLiquidity) { - // they're typing into the field they've last typed in - if (field === state.independentField) { - return { - ...state, - independentField: field, - typedValue, - } - } - // they're typing into a new field, store the other value - else { - return { - ...state, - independentField: field, - typedValue, - otherTypedValue: state.typedValue, - } - } - } else { - return { - ...state, - independentField: field, - typedValue, - otherTypedValue: '', - } - } - }) -) From c8d595f4e8bc56da4b2139f91654ed93d356b75c Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 09:12:25 -0500 Subject: [PATCH 23/72] clear input amount on switch currencies --- src/state/swap/reducer.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/state/swap/reducer.ts b/src/state/swap/reducer.ts index 5ca841738bd..82250c23360 100644 --- a/src/state/swap/reducer.ts +++ b/src/state/swap/reducer.ts @@ -59,6 +59,7 @@ export default createReducer(initialState, (builder) => return { ...state, independentField: state.independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT, + typedValue: '', [Field.INPUT]: { currencyId: state[Field.OUTPUT].currencyId }, [Field.OUTPUT]: { currencyId: state[Field.INPUT].currencyId }, } From f2ec1cab7281c4b95fdc0ad3e54a4256b2a30d91 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 09:16:23 -0500 Subject: [PATCH 24/72] only look for proposals from genesis block --- src/constants/governance.ts | 2 ++ src/state/logs/updater.ts | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/constants/governance.ts b/src/constants/governance.ts index ae7d1e2a81e..6c3b2d0a976 100644 --- a/src/constants/governance.ts +++ b/src/constants/governance.ts @@ -3,6 +3,8 @@ export const GOVERNANCE_ADDRESS: { [chainId: number]: string } = { [44787]: '0xA878C6787490c9f0d2406bcd161b61f128Ab2708', } +export const GOVERNANCE_GENESIS = 10609767 + export const DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS = 5 // Block time here is slightly higher (~1s) than average in order to avoid ongoing proposals past the displayed time diff --git a/src/state/logs/updater.ts b/src/state/logs/updater.ts index de9baf94513..4b77ea09173 100644 --- a/src/state/logs/updater.ts +++ b/src/state/logs/updater.ts @@ -1,3 +1,4 @@ +import { GOVERNANCE_GENESIS } from 'constants/governance' import { useWeb3Context } from 'hooks' import { useEffect, useMemo } from 'react' @@ -39,7 +40,7 @@ export default function Updater(): null { provider .getLogs({ ...filter, - fromBlock: 0, + fromBlock: GOVERNANCE_GENESIS, toBlock: blockNumber, }) .then((logs) => { From 7bf34daf22f5eb807ace2082ff37275ba2f211aa Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 09:49:21 -0500 Subject: [PATCH 25/72] new staking hooks --- src/constants/staking.ts | 4 + src/hooks/useStaking.ts | 6 + src/pages/Staking/ExtendLock.tsx | 12 +- src/pages/Staking/GaugeVoteModal.tsx | 3 +- src/pages/Staking/Vote.tsx | 5 +- src/pages/Staking/index.tsx | 18 --- src/state/staking/hooks.ts | 185 ++++++++++++++------------- 7 files changed, 117 insertions(+), 116 deletions(-) create mode 100644 src/hooks/useStaking.ts diff --git a/src/constants/staking.ts b/src/constants/staking.ts index 3fd278a3bac..99f8b4f7de2 100644 --- a/src/constants/staking.ts +++ b/src/constants/staking.ts @@ -1,5 +1,9 @@ import { ChainId } from '@ubeswap/sdk' +import { CELO } from './tokens' + +export const ExternalRewardsToken = CELO + export const ExternalStakingRewards: { [K in ChainId]: string } = { [ChainId.MAINNET]: '0x0812f6de916667C5aa820E757704c4ac69159529', [ChainId.ALFAJORES]: '', diff --git a/src/hooks/useStaking.ts b/src/hooks/useStaking.ts new file mode 100644 index 00000000000..53259b6b7a9 --- /dev/null +++ b/src/hooks/useStaking.ts @@ -0,0 +1,6 @@ +import { useUserStakingInfo } from 'state/staking/hooks' + +export function useVotePowerLeft(): number { + const userStakingInfo = useUserStakingInfo() + return (10000 - userStakingInfo.voteUserPower) / 100 +} diff --git a/src/pages/Staking/ExtendLock.tsx b/src/pages/Staking/ExtendLock.tsx index 7c178202c87..af87f459229 100644 --- a/src/pages/Staking/ExtendLock.tsx +++ b/src/pages/Staking/ExtendLock.tsx @@ -5,8 +5,7 @@ import { useDoTransaction } from 'hooks/useDoTransaction' import React, { useState } from 'react' import { Calendar } from 'react-date-range' import { Text } from 'rebass' -import { useLockEnd } from 'state/staking/hooks' -import { useIsDarkMode } from 'state/user/hooks' +import { useUserStakingState } from 'state/staking/hooks' import { ButtonError } from '../../components/Button' import { useWeb3Context } from '../../hooks' @@ -25,9 +24,8 @@ export default function ExtendLock({ setHash, setAttempting }: WithdrawModalProp const { connected } = useWeb3Context() // monitor call to help UI loading state - const endOfLock = useLockEnd() - const [date, setDate] = useState(new Date(endOfLock)) - const isDarkMode = useIsDarkMode() + const { lock } = useUserStakingState() + const [date, setDate] = useState(new Date(lock?.end ?? 0)) const roundedDate = date ? new Date( Math.floor(date?.valueOf() / (MILLISECONDS_PER_SECOND * SECONDS_PER_WEEK)) * @@ -59,7 +57,7 @@ export default function ExtendLock({ setHash, setAttempting }: WithdrawModalProp error = 'Connect Wallet' } - if (!roundedDate || roundedDate.getTime() < endOfLock) { + if (!roundedDate || roundedDate.getTime() < (lock?.end ?? 0)) { error = error ?? 'Choose a date later than your current lock' } @@ -73,7 +71,7 @@ export default function ExtendLock({ setHash, setAttempting }: WithdrawModalProp - + {error ? error : `Lock until ${roundedDate?.toLocaleDateString()}`} diff --git a/src/pages/Staking/GaugeVoteModal.tsx b/src/pages/Staking/GaugeVoteModal.tsx index a65fbcae978..80b28c2170a 100644 --- a/src/pages/Staking/GaugeVoteModal.tsx +++ b/src/pages/Staking/GaugeVoteModal.tsx @@ -1,8 +1,9 @@ import { TransactionResponse } from '@ethersproject/providers' import { JSBI } from '@ubeswap/sdk' +import { useVotePowerLeft } from 'hooks/useStaking' import { MaxButton } from 'pages/Pool/styleds' import React, { useState } from 'react' -import { GaugeSummary, useVotePowerLeft } from 'state/staking/hooks' +import { GaugeSummary } from 'state/staking/hooks' import styled from 'styled-components' import { ButtonError } from '../../components/Button' diff --git a/src/pages/Staking/Vote.tsx b/src/pages/Staking/Vote.tsx index 88ce255a635..d0426e54420 100644 --- a/src/pages/Staking/Vote.tsx +++ b/src/pages/Staking/Vote.tsx @@ -3,9 +3,10 @@ import Loader from 'components/Loader' import { RowFixed } from 'components/Row' import { ChainLogo } from 'constants/StablePools' import { usePoolColor } from 'hooks/useColor' +import { useVotePowerLeft } from 'hooks/useStaking' import React, { useState } from 'react' import { isMobile } from 'react-device-detect' -import { GaugeSummary, useVotePowerLeft } from 'state/staking/hooks' +import { GaugeSummary } from 'state/staking/hooks' import styled from 'styled-components' import { TYPE } from 'theme' @@ -153,7 +154,7 @@ function WeightCard({ position, disabled }: { position: GaugeSummary; disabled: summary={position} isOpen={voteModalOpen} onDismiss={() => setVoteModalOpen(false)} - disabled={poolInfo.isDisabled} + disabled={poolInfo.isDisabled ?? false} /> !disabled && setVoteModalOpen(true)}> diff --git a/src/pages/Staking/index.tsx b/src/pages/Staking/index.tsx index 26d2465dfb5..3d439783d36 100644 --- a/src/pages/Staking/index.tsx +++ b/src/pages/Staking/index.tsx @@ -15,15 +15,6 @@ import StatsHeader from './StatsHeader' import VeMobiRewards from './VeMobiRewards' import Vote from './Vote' -const TextContainer = styled.div` - width: 100%; - display: flex; - flex-wrap: wrap; - margin-left: auto; - margin-right: auto; - justify-content: center; -` - const PositionsContainer = styled.div` width: 100%; display: flex; @@ -47,15 +38,6 @@ const OuterContainer = styled.div` flex-direction: column; ` -const Divider = styled.div` - height: 1px; - width: 100%; - background: ${({ theme }) => theme.text1}; - margin-top: 1rem; - margin-bottom: 2rem; - opacity: 0.2; -` - const HeaderLinks = styled(Row)` justify-self: center; background-color: ${({ theme }) => theme.bg1}; diff --git a/src/state/staking/hooks.ts b/src/state/staking/hooks.ts index 71ba6196803..47c02607518 100644 --- a/src/state/staking/hooks.ts +++ b/src/state/staking/hooks.ts @@ -1,4 +1,5 @@ import { JSBI, Percent, Token, TokenAmount } from '@ubeswap/sdk' +import { ExternalRewardsToken } from 'constants/staking' import { useMobi, useVeMobi } from 'hooks/Tokens' import { useSelector } from 'react-redux' import { AppState } from 'state' @@ -6,8 +7,103 @@ import { getPoolInfo } from 'state/stablePools/hooks' import { StableSwapPool } from 'state/stablePools/reducer' import { getDepositValues } from 'utils/stableSwaps' +import { CHAIN } from '../../constants' import { IStakingState, IUserStakingState } from './reducer' +export function useStakingState(): IStakingState { + return useSelector((state) => state.staking) +} + +export function useUserStakingState(): IUserStakingState { + return useSelector((state) => state.staking) +} + +export function useStakingStateCombined(): IStakingState & IUserStakingState { + return useSelector((state) => state.staking) +} + +export type FeeInfo = { + toClaim: TokenAmount + totalFeesThisWeek: TokenAmount + totalFeesNextWeek: TokenAmount +} + +export function useFeeInformation(): FeeInfo { + const { claimable, total, nextWeek } = useSelector((state: AppState) => ({ + claimable: state.staking.claimableFees, + total: state.staking.feesThisWeek, + nextWeek: state.staking.feesNextWeek, + })) + const mobi = useMobi() + + return { + toClaim: new TokenAmount(mobi, claimable ?? '0'), + totalFeesThisWeek: new TokenAmount(mobi, total ?? '0'), + totalFeesNextWeek: new TokenAmount(mobi, nextWeek ?? '0'), + } +} + +export type StakingInfo = { + totalWeight: JSBI + totalMobiLocked: TokenAmount + totalVotingPower: TokenAmount + externalRewardRate: TokenAmount + feesThisWeek: JSBI + feesNextWeek: JSBI + mobiRate: TokenAmount +} + +export function useStakingInfo(): StakingInfo { + const stakingState = useStakingState() + + const mobi = useMobi() + const veMobi = useVeMobi() + + return { + totalWeight: stakingState.totalWeight, + totalMobiLocked: new TokenAmount(mobi, stakingState.totalMobiLocked), + totalVotingPower: new TokenAmount(veMobi, stakingState.totalVotingPower), + externalRewardRate: new TokenAmount(ExternalRewardsToken[CHAIN], stakingState.externalRewardsRate), + feesThisWeek: stakingState.feesThisWeek, + feesNextWeek: stakingState.feesNextWeek, + mobiRate: new TokenAmount(mobi, stakingState.mobiRate), + } +} + +export type VoteLockInfo = { + locked: TokenAmount + end: number // UNIX time stamp +} + +export type UserStakingInfo = { + voteUserPower: number + votingPower: TokenAmount + claimableExternalRewards: TokenAmount + claimableFees: TokenAmount + lock: VoteLockInfo | null +} + +export function useUserStakingInfo(): UserStakingInfo { + const userStakingState = useUserStakingState() + + const mobi = useMobi() + const veMobi = useVeMobi() + + return { + voteUserPower: parseInt(userStakingState.voteUserPower.toString()), + votingPower: new TokenAmount(veMobi, userStakingState.votingPower), + claimableExternalRewards: new TokenAmount(ExternalRewardsToken[CHAIN], userStakingState.claimableExternalRewards), + claimableFees: new TokenAmount(mobi, userStakingState.claimableFees), + lock: + userStakingState.lock === null + ? null + : { + locked: new TokenAmount(mobi, userStakingState.lock?.amount), + end: userStakingState.lock.end, + }, + } +} + export type GaugeSummary = { pool: string poolAddress: string @@ -26,14 +122,6 @@ export type GaugeSummary = { powerAllocated: number } -export type MobiStakingInfo = { - votingPower: TokenAmount - totalVotingPower: TokenAmount - mobiLocked?: TokenAmount - lockEnd?: Date - positions?: GaugeSummary[] -} - // export function calculateBoostedBalance( // votingPower: JSBI, // totalVotingPower: JSBI, @@ -52,54 +140,7 @@ export type MobiStakingInfo = { // return JSBI.greaterThan(boosted, liquidity) ? boosted : liquidity // } -export type FeeInfo = { - toClaim: TokenAmount - totalFeesThisWeek: TokenAmount - totalFeesNextWeek: TokenAmount -} - -export function useMobiStakingInfo(): MobiStakingInfo { - const stakingInfo = useSelector((state) => state.staking) - const pools = useSelector((state) => { - const allPools = state.stablePools.pools - return Object.values(allPools).map(({ pool }) => pool) - }) - const veMobi = useVeMobi() - const mobi = useMobi() - const baseInfo: MobiStakingInfo = { - votingPower: new TokenAmount(veMobi, stakingInfo.votingPower), - totalVotingPower: new TokenAmount(veMobi, stakingInfo.totalVotingPower), - mobiLocked: new TokenAmount(mobi, stakingInfo.locked?.amount ?? '0'), - lockEnd: stakingInfo.locked ? new Date(stakingInfo.locked.end) : undefined, - } - if (pools && pools.length === 0) { - return baseInfo - } - const positions = pools.map((pool) => ({ - pool: pool.name, - poolAddress: pool.address, - address: pool.gaugeAddress ?? '', - baseBalance: new TokenAmount(pool.lpToken, pool.userStaked ?? '0'), - totalStaked: new TokenAmount(pool.lpToken, pool.totalStakedAmount ?? '0'), - unclaimedMobi: new TokenAmount(mobi, pool.pendingMobi ?? '0'), - firstToken: pool.tokens[0], - currentWeight: pool.poolWeight, - futureWeight: new Percent( - pool.futureWeight, - JSBI.divide(stakingInfo.totalWeight, JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(18))) - ), - workingBalance: new TokenAmount(pool.lpToken, pool.effectiveBalance), - totalWorkingBalance: new TokenAmount(pool.lpToken, pool.totalEffectiveBalance), - workingPercentage: new Percent(pool.effectiveBalance, pool.totalEffectiveBalance), - actualPercentage: new Percent(pool.userStaked ?? '0', pool.totalStakedAmount ?? '1'), - lastVote: new Date(pool.lastUserVote * 1000), - powerAllocated: pool.powerAllocated, - })) - return { - ...baseInfo, - positions, - } -} +// TODO: fix this hook export function usePriceOfDeposits() { const pools = useSelector((state) => { @@ -131,39 +172,7 @@ export function usePriceOfDeposits() { ) } -export function useLockEnd(): number { - const lockEnd = useSelector((state) => state.staking?.lock?.end ?? 0) - return lockEnd -} - export function useVotePowerLeft(): number { const votePower = useSelector((state) => state.staking.voteUserPower) return (10000 - parseInt(votePower.toString())) / 100 } - -export function useStakingState(): IStakingState { - return useSelector((state) => state.staking) -} - -export function useUserStakingState(): IUserStakingState { - return useSelector((state) => state.staking) -} - -export function useStakingStateCombined(): IStakingState & IUserStakingState { - return useSelector((state) => state.staking) -} - -export function useFeeInformation(): FeeInfo { - const { claimable, total, nextWeek } = useSelector((state: AppState) => ({ - claimable: state.staking.claimableFees, - total: state.staking.feesThisWeek, - nextWeek: state.staking.feesNextWeek, - })) - const mobi = useMobi() - - return { - toClaim: new TokenAmount(mobi, claimable ?? '0'), - totalFeesThisWeek: new TokenAmount(mobi, total ?? '0'), - totalFeesNextWeek: new TokenAmount(mobi, nextWeek ?? '0'), - } -} From 2bbe09665a9a3cf29dfafcc5c664c43822af8c11 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 09:56:01 -0500 Subject: [PATCH 26/72] stats header --- src/hooks/useExternalStakingRewards.ts | 10 +++++----- src/pages/Staking/StatsHeader.tsx | 15 +++++++++------ src/pages/Staking/index.tsx | 4 ---- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/hooks/useExternalStakingRewards.ts b/src/hooks/useExternalStakingRewards.ts index f81c31165dd..2e402771cc4 100644 --- a/src/hooks/useExternalStakingRewards.ts +++ b/src/hooks/useExternalStakingRewards.ts @@ -1,6 +1,6 @@ import { JSBI, Percent, TokenAmount } from '@ubeswap/sdk' import { calcApy } from 'components/earn/StablePoolCard' -import { CELO } from 'constants/tokens' +import { ExternalRewardsToken } from 'constants/staking' import { useTokenPrice } from 'state/application/hooks' import { useStakingState, useStakingStateCombined } from 'state/staking/hooks' @@ -23,7 +23,7 @@ export type ExternalUserRewardInfo = { export function useExternalStakingRewards(): ExternalRewardInfo { const stakingState = useStakingState() const mobi = useMobi() - const priceOfReward = useTokenPrice(CELO[CHAIN].address) + const priceOfReward = useTokenPrice(ExternalRewardsToken[CHAIN].address) const priceOfMobi = useTokenPrice(mobi?.address) const yearlyRate = JSBI.multiply(stakingState.externalRewardsRate, SECONDS_IN_YEAR) @@ -34,7 +34,7 @@ export function useExternalStakingRewards(): ExternalRewardInfo { : new Percent('0') return { - rewardRate: new TokenAmount(CELO[CHAIN], stakingState.externalRewardsRate), + rewardRate: new TokenAmount(ExternalRewardsToken[CHAIN], stakingState.externalRewardsRate), avgApr, } } @@ -47,7 +47,7 @@ export function useUserExternalStakingRewards(): ExternalUserRewardInfo { ) return { - userRewardRate: new TokenAmount(CELO[CHAIN], userRateJSBI), - claimableRewards: new TokenAmount(CELO[CHAIN], stakingState.claimableExternalRewards), + userRewardRate: new TokenAmount(ExternalRewardsToken[CHAIN], userRateJSBI), + claimableRewards: new TokenAmount(ExternalRewardsToken[CHAIN], stakingState.claimableExternalRewards), } } diff --git a/src/pages/Staking/StatsHeader.tsx b/src/pages/Staking/StatsHeader.tsx index 0edbbd0d8ee..87fde025733 100644 --- a/src/pages/Staking/StatsHeader.tsx +++ b/src/pages/Staking/StatsHeader.tsx @@ -3,7 +3,7 @@ import Loader from 'components/Loader' import { useExternalStakingRewards } from 'hooks/useExternalStakingRewards' import React from 'react' import { isMobile } from 'react-device-detect' -import { MobiStakingInfo, usePriceOfDeposits } from 'state/staking/hooks' +import { StakingInfo, UserStakingInfo } from 'state/staking/hooks' import { useIsDarkMode } from 'state/user/hooks' import styled from 'styled-components' import { TYPE } from 'theme' @@ -63,22 +63,25 @@ const StatSpan = styled.span` ` type PropType = { - stakingInfo: MobiStakingInfo + stakingInfo: StakingInfo + userStakingInfo: UserStakingInfo } -function StatsHeader({ stakingInfo }: PropType) { - const priceOfDeposits = usePriceOfDeposits() +function StatsHeader({ stakingInfo, userStakingInfo }: PropType) { + // TODO: fix price of deposits + // const priceOfDeposits = undefined const { avgApr } = useExternalStakingRewards() const isDarkMode = useIsDarkMode() const displayData = [ { label: 'Your Voting Power', - value: stakingInfo?.votingPower?.toSignificant(4, { groupSeparator: ',' }), + value: userStakingInfo?.votingPower?.toSignificant(4, { groupSeparator: ',' }), img: isDarkMode ? lockDark : lockLight, }, { label: 'Your total deposits', - value: priceOfDeposits ? '$' + priceOfDeposits?.toSignificant(4, { groupSeparator: ',' }) : undefined, + // value: priceOfDeposits ? '$' + priceOfDeposits?.toSignificant(4, { groupSeparator: ',' }) : undefined, + value: 'FIX', img: isDarkMode ? cashDark : cashLight, }, { diff --git a/src/pages/Staking/index.tsx b/src/pages/Staking/index.tsx index 3d439783d36..9ddcf4926dc 100644 --- a/src/pages/Staking/index.tsx +++ b/src/pages/Staking/index.tsx @@ -1,8 +1,6 @@ import { TokenAmount } from '@ubeswap/sdk' -import { useMobi } from 'hooks/Tokens' import React from 'react' import { isMobile } from 'react-device-detect' -import { useMobiStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { Row } from '../../components/Row' @@ -77,8 +75,6 @@ enum View { } export default function Staking() { - const stakingInfo = useMobiStakingInfo() - const mobi = useMobi() const unclaimedMobi = new TokenAmount(mobi, getAllUnclaimedMobi(stakingInfo.positions ?? [])) const [view, setView] = React.useState(View.Lock) From 544de77b77a20b13c9700d81e0dbb6a2a68d1fd3 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 10:10:23 -0500 Subject: [PATCH 27/72] stake page --- src/pages/Staking/Stake.tsx | 88 ++++++++++++++++++------------------ src/pages/Staking/index.tsx | 11 +++-- src/state/staking/hooks.ts | 18 ++------ src/state/staking/reducer.ts | 4 +- 4 files changed, 56 insertions(+), 65 deletions(-) diff --git a/src/pages/Staking/Stake.tsx b/src/pages/Staking/Stake.tsx index 3cd7aa011fb..81b0c28a76e 100644 --- a/src/pages/Staking/Stake.tsx +++ b/src/pages/Staking/Stake.tsx @@ -4,7 +4,7 @@ import { AutoColumn } from 'components/Column' import { RowBetween } from 'components/Row' import React, { useState } from 'react' import Countdown from 'react-countdown' -import { MobiStakingInfo } from 'state/staking/hooks' +import { UserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { theme, TYPE } from 'theme' @@ -29,7 +29,7 @@ const Container = styled.div` margin-bottom: 1rem; `} ` -const Wrapper = styled(AutoColumn)<{ showBackground: boolean; background: any }>` +const Wrapper = styled(AutoColumn)<{ showBackground: boolean }>` border-radius: 12px; width: 100%; overflow: hidden; @@ -48,14 +48,16 @@ const Wrapper = styled(AutoColumn)<{ showBackground: boolean; background: any }> ` type PropTypes = { - stakingInfo: MobiStakingInfo + userStakingInfo: UserStakingInfo } -export default function Stake({ stakingInfo }: PropTypes) { - const { mobiLocked, lockEnd } = stakingInfo +export default function Stake({ userStakingInfo }: PropTypes) { + const { lock } = userStakingInfo const [lockType, setLockType] = useState(-1) + const veMobiContract = useVotingEscrowContract() const [attempting, setAttempting] = useState(false) const addTransaction = useTransactionAdder() + async function onClaim() { if (veMobiContract) { setAttempting(true) @@ -79,64 +81,60 @@ export default function Stake({ stakingInfo }: PropTypes) { return ( -1} onDismiss={() => setLockType(-1)} lockType={lockType} /> - + Locked MOBI: - {mobiLocked ? mobiLocked.toFixed(2) : '0.00'} + {lock.locked.toSignificant(2)} - {mobiLocked && mobiLocked.greaterThan('0') && Date.now() + SECONDS_IN_DAY >= (lockEnd?.valueOf() ?? 0) ? ( + {lock.locked.greaterThan('0') && Date.now() + SECONDS_IN_DAY >= lock.end ? ( You can claim in: - + - ) : mobiLocked && mobiLocked.greaterThan('0') ? ( + ) : lock.locked.greaterThan('0') ? ( You can claim on: - {lockEnd?.toLocaleDateString() ?? '--'} + {new Date(lock.end).toLocaleDateString()} ) : null} - {true && ( -
- {Date.now() > (lockEnd?.valueOf() ?? 0) && mobiLocked && mobiLocked.greaterThan('0') ? ( +
+ {Date.now() > lock.end && lock.locked.greaterThan('0') ? ( + + {attempting ? 'CLAIMING...' : 'CLAIM'} + + ) : ( + <> + lock.locked.greaterThan('0') ? setLockType(LockType.increase) : setLockType(LockType.initial) + } + style={{ fontWeight: 700, fontSize: 18, backgroundColor: theme(false).celoGreen }} > - {attempting ? 'CLAIMING...' : 'CLAIM'} + DEPOSIT - ) : ( - <> + {lock.locked.greaterThan('0') && ( - mobiLocked && mobiLocked.greaterThan('0') - ? setLockType(LockType.increase) - : setLockType(LockType.initial) - } - style={{ fontWeight: 700, fontSize: 18, backgroundColor: theme(false).celoGreen }} + onClick={() => setLockType(LockType.extend)} + style={{ fontWeight: 700, fontSize: 18, backgroundColor: theme(false).celoGold }} > - DEPOSIT + EXTEND - {mobiLocked && mobiLocked.greaterThan('0') && ( - setLockType(LockType.extend)} - style={{ fontWeight: 700, fontSize: 18, backgroundColor: theme(false).celoGold }} - > - EXTEND - - )} - - )} -
- )} + )} + + )} +
) diff --git a/src/pages/Staking/index.tsx b/src/pages/Staking/index.tsx index 9ddcf4926dc..d227ff7ab57 100644 --- a/src/pages/Staking/index.tsx +++ b/src/pages/Staking/index.tsx @@ -1,11 +1,10 @@ -import { TokenAmount } from '@ubeswap/sdk' import React from 'react' import { isMobile } from 'react-device-detect' +import { useStakingInfo, useUserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { Row } from '../../components/Row' import CalcBoost from './CalcBoost' -import { getAllUnclaimedMobi } from './ClaimAllMobiModal' import GaugeWeights from './GaugeWeights' import Positions from './Positions' import Stake from './Stake' @@ -75,13 +74,15 @@ enum View { } export default function Staking() { - const unclaimedMobi = new TokenAmount(mobi, getAllUnclaimedMobi(stakingInfo.positions ?? [])) + // const unclaimedMobi = new TokenAmount(mobi, getAllUnclaimedMobi(stakingInfo.positions ?? [])) + const stakingInfo = useStakingInfo() + const userStakingInfo = useUserStakingInfo() const [view, setView] = React.useState(View.Lock) return ( - +
setView(View.Lock)} selected={view === View.Lock}> @@ -100,7 +101,7 @@ export default function Staking() {
{view === View.Lock ? ( - + diff --git a/src/state/staking/hooks.ts b/src/state/staking/hooks.ts index 47c02607518..fdb7d85d76a 100644 --- a/src/state/staking/hooks.ts +++ b/src/state/staking/hooks.ts @@ -80,7 +80,7 @@ export type UserStakingInfo = { votingPower: TokenAmount claimableExternalRewards: TokenAmount claimableFees: TokenAmount - lock: VoteLockInfo | null + lock: VoteLockInfo } export function useUserStakingInfo(): UserStakingInfo { @@ -94,13 +94,10 @@ export function useUserStakingInfo(): UserStakingInfo { votingPower: new TokenAmount(veMobi, userStakingState.votingPower), claimableExternalRewards: new TokenAmount(ExternalRewardsToken[CHAIN], userStakingState.claimableExternalRewards), claimableFees: new TokenAmount(mobi, userStakingState.claimableFees), - lock: - userStakingState.lock === null - ? null - : { - locked: new TokenAmount(mobi, userStakingState.lock?.amount), - end: userStakingState.lock.end, - }, + lock: { + locked: new TokenAmount(mobi, userStakingState.lock?.amount), + end: userStakingState.lock.end, + }, } } @@ -171,8 +168,3 @@ export function usePriceOfDeposits() { }, JSBI.BigInt('0')) ) } - -export function useVotePowerLeft(): number { - const votePower = useSelector((state) => state.staking.voteUserPower) - return (10000 - parseInt(votePower.toString())) / 100 -} diff --git a/src/state/staking/reducer.ts b/src/state/staking/reducer.ts index a1b0db3411f..b6bae887f1a 100644 --- a/src/state/staking/reducer.ts +++ b/src/state/staking/reducer.ts @@ -23,7 +23,7 @@ export type IUserStakingState = { votingPower: JSBI claimableExternalRewards: JSBI claimableFees: JSBI - lock: VoteLock | null + lock: VoteLock } const initialStakingState: IStakingState = { @@ -41,7 +41,7 @@ const initialUserStakingState: IUserStakingState = { votingPower: JSBI.BigInt(0), claimableExternalRewards: JSBI.BigInt(0), claimableFees: JSBI.BigInt(0), - lock: null, + lock: { amount: JSBI.BigInt(0), end: 0 }, } const initialState: IStakingState & IUserStakingState = { From 04f0966412cd7b7f46dba263b02c2dbbdb602b72 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 10:25:39 -0500 Subject: [PATCH 28/72] gauge hooks 1 --- src/pages/Staking/VeMobiRewards.tsx | 4 +- src/state/gauges/actions.ts | 6 +-- src/state/gauges/hooks.ts | 64 +++++++++++++++++++++++++++-- src/state/gauges/reducer.ts | 12 +++--- 4 files changed, 72 insertions(+), 14 deletions(-) diff --git a/src/pages/Staking/VeMobiRewards.tsx b/src/pages/Staking/VeMobiRewards.tsx index 7af6acfd416..f6127b4ab7d 100644 --- a/src/pages/Staking/VeMobiRewards.tsx +++ b/src/pages/Staking/VeMobiRewards.tsx @@ -8,7 +8,7 @@ import { useWeb3Context } from 'hooks' import { useFeeDistributor, useStakingContract } from 'hooks/useContract' import { useExternalStakingRewards, useUserExternalStakingRewards } from 'hooks/useExternalStakingRewards' import React, { useState } from 'react' -import { useFeeInformation } from 'state/staking/hooks' +import { useFeeInfo } from 'state/staking/hooks' import { useTransactionAdder } from 'state/transactions/hooks' import styled from 'styled-components' import { TYPE } from 'theme' @@ -116,7 +116,7 @@ const Divider = styled.div` export default function VeMobiRewards() { const { rewardRate, avgApr } = useExternalStakingRewards() const { userRewardRate, claimableRewards } = useUserExternalStakingRewards() - const { totalFeesThisWeek, totalFeesNextWeek } = useFeeInformation() + const { totalFeesThisWeek, totalFeesNextWeek } = useFeeInfo() const snxAddress = ExternalStakingRewards[CHAIN] const tokenColor = '#ab9325' const { connected, address } = useWeb3Context() diff --git a/src/state/gauges/actions.ts b/src/state/gauges/actions.ts index 0c7351685ed..0e309298188 100644 --- a/src/state/gauges/actions.ts +++ b/src/state/gauges/actions.ts @@ -1,6 +1,6 @@ import { createAction } from '@reduxjs/toolkit' -import { IGaugeInfo, IUserGaugeInfo } from './reducer' +import { IGaugeState, IUserGaugeState } from './reducer' -export const updateGauges = createAction<{ gaugeState: (IGaugeInfo | null)[] }>('gauges/update') -export const updateGaugesUser = createAction<{ userGaugeState: (IUserGaugeInfo | null)[] }>('gauges/updateUser') +export const updateGauges = createAction<{ gaugeState: (IGaugeState | null)[] }>('gauges/update') +export const updateGaugesUser = createAction<{ userGaugeState: (IUserGaugeState | null)[] }>('gauges/updateUser') diff --git a/src/state/gauges/hooks.ts b/src/state/gauges/hooks.ts index d4b82bd6177..7d01d110c5a 100644 --- a/src/state/gauges/hooks.ts +++ b/src/state/gauges/hooks.ts @@ -1,9 +1,67 @@ +import { JSBI, TokenAmount } from '@ubeswap/sdk' import { IGauge } from 'constants/pools' +import { useMobi } from 'hooks/Tokens' import { useSelector } from 'react-redux' import { AppState } from '..' -import { IGaugeInfo, IUserGaugeInfo } from './reducer' +import { IGaugeState, IUserGaugeState } from './reducer' -export function useGauges(): readonly ((IUserGaugeInfo & IGaugeInfo & IGauge) | null)[] { - return useSelector((state) => state.gauges.gauges) +export function useGauges(): readonly ((IGaugeState & IGauge) | null)[] { + return useSelector((state) => state.gauges.gauges) } + +export function useUserGauges(): readonly ((IUserGaugeState & IGauge) | null)[] { + return useSelector((state) => state.gauges.gauges) +} + +export type GaugeInfo = { + isKilled: boolean + lastClaim: Date + weight: number + futureWeight: number + totalSupply: JSBI + workingSupply: JSBI + totalEffectiveBalance: JSBI +} + +export type UserGaugeInfo = { + balance: JSBI + claimableMobi: TokenAmount + lastVote: number + powerAllocated: number + effectiveBalance: JSBI +} + +export function useAllGaugesInfo(): (GaugeInfo | null)[] { + const gauges = useGauges() + + return gauges.map((g) => + !g + ? null + : { + ...g, + lastClaim: new Date(g.lastClaim), + weight: g.lastClaim.valueOf(), + futureWeight: g.lastClaim.valueOf(), + } + ) +} + +export function useAllUserGaugesInfo(): (UserGaugeInfo | null)[] { + const userGauges = useUserGauges() + + const mobi = useMobi() + + return userGauges.map((ug) => + !ug + ? null + : { + ...ug, + claimableMobi: new TokenAmount(mobi, ug.claimableMobi), + } + ) +} + +// get all user gauges +// get one gauge by IGauge +// get one user gauge by IGauge diff --git a/src/state/gauges/reducer.ts b/src/state/gauges/reducer.ts index ad67eccfcfc..3e7ee2c1371 100644 --- a/src/state/gauges/reducer.ts +++ b/src/state/gauges/reducer.ts @@ -6,10 +6,10 @@ import { CHAIN } from '../../constants' import { updateGauges, updateGaugesUser } from './actions' export interface Gauges { - readonly gauges: ((IUserGaugeInfo & IGaugeInfo & IGauge) | null)[] + readonly gauges: ((IUserGaugeState & IGaugeState & IGauge) | null)[] } -export interface IGaugeInfo { +export interface IGaugeState { isKilled: boolean lastClaim: number weight: JSBI @@ -19,7 +19,7 @@ export interface IGaugeInfo { totalEffectiveBalance: JSBI } -export interface IUserGaugeInfo { +export interface IUserGaugeState { balance: JSBI claimableMobi: JSBI lastVote: number @@ -27,7 +27,7 @@ export interface IUserGaugeInfo { effectiveBalance: JSBI } -const initialGaugeInfo: IGaugeInfo = { +const initialGaugeInfo: IGaugeState = { isKilled: false, lastClaim: 0, weight: JSBI.BigInt('0'), @@ -37,7 +37,7 @@ const initialGaugeInfo: IGaugeInfo = { totalEffectiveBalance: JSBI.BigInt(0), } -const initialUserGaugeInfo: IUserGaugeInfo = { +const initialUserGaugeInfo: IUserGaugeState = { balance: JSBI.BigInt(0), claimableMobi: JSBI.BigInt(0), lastVote: 0, @@ -45,7 +45,7 @@ const initialUserGaugeInfo: IUserGaugeInfo = { effectiveBalance: JSBI.BigInt(0), } -function emptyExchangeInfo(gauge: IGauge | null): (IGaugeInfo & IUserGaugeInfo & IGauge) | null { +function emptyExchangeInfo(gauge: IGauge | null): (IGaugeState & IUserGaugeState & IGauge) | null { return gauge === null ? null : { From 18008e19815ceebd8be4ce476319e9e49288da92 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 10:31:11 -0500 Subject: [PATCH 29/72] add single gauge hooks --- src/state/gauges/hooks.ts | 43 +++++++++++++++++++++++++++++++++++--- src/state/staking/hooks.ts | 2 +- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/state/gauges/hooks.ts b/src/state/gauges/hooks.ts index 7d01d110c5a..bb8f5f4a0a0 100644 --- a/src/state/gauges/hooks.ts +++ b/src/state/gauges/hooks.ts @@ -1,3 +1,4 @@ +import { invariant } from '@apollo/client/utilities/globals' import { JSBI, TokenAmount } from '@ubeswap/sdk' import { IGauge } from 'constants/pools' import { useMobi } from 'hooks/Tokens' @@ -62,6 +63,42 @@ export function useAllUserGaugesInfo(): (UserGaugeInfo | null)[] { ) } -// get all user gauges -// get one gauge by IGauge -// get one user gauge by IGauge +export function useGaugeInfo(gauge: IGauge): GaugeInfo { + const gauges = useGauges() + + const gaugeInfo = gauges + .filter((g) => g?.address === gauge.address) + .map((g) => + !g + ? null + : { + ...g, + lastClaim: new Date(g.lastClaim), + weight: g.lastClaim.valueOf(), + futureWeight: g.lastClaim.valueOf(), + } + ) + invariant(gaugeInfo.length === 1, 'duplicate gauges') + invariant(!!gaugeInfo[0], 'gauge not found') + return gaugeInfo[0] +} + +export function useUserGaugeInfo(gauge: IGauge): UserGaugeInfo { + const gauges = useUserGauges() + + const mobi = useMobi() + + const gaugeInfo = gauges + .filter((g) => g?.address === gauge.address) + .map((ug) => + !ug + ? null + : { + ...ug, + claimableMobi: new TokenAmount(mobi, ug.claimableMobi), + } + ) + invariant(gaugeInfo.length === 1, 'duplicate gauges') + invariant(!!gaugeInfo[0], 'gauge not found') + return gaugeInfo[0] +} diff --git a/src/state/staking/hooks.ts b/src/state/staking/hooks.ts index fdb7d85d76a..7ff7d938b37 100644 --- a/src/state/staking/hooks.ts +++ b/src/state/staking/hooks.ts @@ -28,7 +28,7 @@ export type FeeInfo = { totalFeesNextWeek: TokenAmount } -export function useFeeInformation(): FeeInfo { +export function useFeeInfo(): FeeInfo { const { claimable, total, nextWeek } = useSelector((state: AppState) => ({ claimable: state.staking.claimableFees, total: state.staking.feesThisWeek, From 20026c2dd9675668a182682507f9b729165985e4 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 10:41:34 -0500 Subject: [PATCH 30/72] upgrade gauge reducer --- src/constants/pools.ts | 9 ++++----- src/state/gauges/hooks.ts | 17 ++++++++++------- src/state/gauges/reducer.ts | 5 ++--- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/constants/pools.ts b/src/constants/pools.ts index 601eb9af2c1..5b3946046d5 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -1,7 +1,8 @@ import { ChainId, Percent, Token, TokenAmount } from '@ubeswap/sdk' import JSBI from 'jsbi' -import { CUSD, UST } from './tokens' +import { CHAIN } from './' +import { CELO, CUSD, UST } from './tokens' export type Fees = { trade: Percent @@ -31,8 +32,7 @@ export interface IExchangeInfo { export interface IGauge { address: string - additionalRewards?: string[] - additionalRewardRate?: string[] + additionalRewards: TokenAmount[] } export interface Volume { @@ -154,8 +154,7 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { }, gauge: { address: '0x107F94409746E8c8E6eFF139A100D17D9ca7FdfE', - additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], - additionalRewardRate: ['12000000000000000'], + additionalRewards: [new TokenAmount(CELO[CHAIN], '12000000000000000')], }, }, ], diff --git a/src/state/gauges/hooks.ts b/src/state/gauges/hooks.ts index bb8f5f4a0a0..a128244c002 100644 --- a/src/state/gauges/hooks.ts +++ b/src/state/gauges/hooks.ts @@ -1,18 +1,19 @@ import { invariant } from '@apollo/client/utilities/globals' import { JSBI, TokenAmount } from '@ubeswap/sdk' -import { IGauge } from 'constants/pools' +import { IGauge, StablePools } from 'constants/pools' import { useMobi } from 'hooks/Tokens' import { useSelector } from 'react-redux' +import { CHAIN } from '../../constants' import { AppState } from '..' import { IGaugeState, IUserGaugeState } from './reducer' -export function useGauges(): readonly ((IGaugeState & IGauge) | null)[] { - return useSelector((state) => state.gauges.gauges) +export function useGauges(): readonly (IGaugeState | null)[] { + return useSelector((state) => state.gauges.gauges) } -export function useUserGauges(): readonly ((IUserGaugeState & IGauge) | null)[] { - return useSelector((state) => state.gauges.gauges) +export function useUserGauges(): readonly (IUserGaugeState | null)[] { + return useSelector((state) => state.gauges.gauges) } export type GaugeInfo = { @@ -67,7 +68,7 @@ export function useGaugeInfo(gauge: IGauge): GaugeInfo { const gauges = useGauges() const gaugeInfo = gauges - .filter((g) => g?.address === gauge.address) + .filter((g, i) => !StablePools[CHAIN][i].gauge && (StablePools[CHAIN][i].gauge?.address === gauge.address ?? false)) .map((g) => !g ? null @@ -89,7 +90,9 @@ export function useUserGaugeInfo(gauge: IGauge): UserGaugeInfo { const mobi = useMobi() const gaugeInfo = gauges - .filter((g) => g?.address === gauge.address) + .filter( + (ug, i) => !StablePools[CHAIN][i].gauge && (StablePools[CHAIN][i].gauge?.address === gauge.address ?? false) + ) .map((ug) => !ug ? null diff --git a/src/state/gauges/reducer.ts b/src/state/gauges/reducer.ts index 3e7ee2c1371..e854db5cfde 100644 --- a/src/state/gauges/reducer.ts +++ b/src/state/gauges/reducer.ts @@ -6,7 +6,7 @@ import { CHAIN } from '../../constants' import { updateGauges, updateGaugesUser } from './actions' export interface Gauges { - readonly gauges: ((IUserGaugeState & IGaugeState & IGauge) | null)[] + readonly gauges: ((IUserGaugeState & IGaugeState) | null)[] } export interface IGaugeState { @@ -45,11 +45,10 @@ const initialUserGaugeInfo: IUserGaugeState = { effectiveBalance: JSBI.BigInt(0), } -function emptyExchangeInfo(gauge: IGauge | null): (IGaugeState & IUserGaugeState & IGauge) | null { +function emptyExchangeInfo(gauge: IGauge | null): (IGaugeState & IUserGaugeState) | null { return gauge === null ? null : { - ...gauge, ...initialGaugeInfo, ...initialUserGaugeInfo, } From a234b7ea8018710878a8f513a2c1470fe488bbad Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 11:45:52 -0500 Subject: [PATCH 31/72] staking lock --- src/pages/Staking/CalcBoost.tsx | 1 - src/pages/Staking/{ => Lock}/ExtendLock.tsx | 8 +- .../Staking/{ => Lock}/IncreaseLockAmount.tsx | 67 ++++---------- src/pages/Staking/{ => Lock}/Lock.tsx | 92 ++++++++----------- src/pages/Staking/{ => Lock}/LockModal.tsx | 34 +++++-- src/pages/Staking/Stake.tsx | 19 +++- src/pages/Staking/index.tsx | 31 ++++--- src/state/gauges/updater.ts | 4 +- src/state/mobiusPools/updater.ts | 8 +- src/state/staking/updater.ts | 2 +- src/utils/calcExpectedVeMobi.ts | 12 +-- 11 files changed, 130 insertions(+), 148 deletions(-) rename src/pages/Staking/{ => Lock}/ExtendLock.tsx (92%) rename src/pages/Staking/{ => Lock}/IncreaseLockAmount.tsx (78%) rename src/pages/Staking/{ => Lock}/Lock.tsx (77%) rename src/pages/Staking/{ => Lock}/LockModal.tsx (79%) diff --git a/src/pages/Staking/CalcBoost.tsx b/src/pages/Staking/CalcBoost.tsx index e7f61ad783e..4c08c5bb5a2 100644 --- a/src/pages/Staking/CalcBoost.tsx +++ b/src/pages/Staking/CalcBoost.tsx @@ -130,7 +130,6 @@ const StyledDropDown = styled(DropDown)<{ selected: boolean }>` type PositionsProps = { stakingInfo: MobiStakingInfo - unclaimedMobi: TokenAmount } export default function CalcBoost({ stakingInfo }: PositionsProps) { const stablePools = useStablePoolInfo() diff --git a/src/pages/Staking/ExtendLock.tsx b/src/pages/Staking/Lock/ExtendLock.tsx similarity index 92% rename from src/pages/Staking/ExtendLock.tsx rename to src/pages/Staking/Lock/ExtendLock.tsx index af87f459229..872b78867ed 100644 --- a/src/pages/Staking/ExtendLock.tsx +++ b/src/pages/Staking/Lock/ExtendLock.tsx @@ -7,10 +7,10 @@ import { Calendar } from 'react-date-range' import { Text } from 'rebass' import { useUserStakingState } from 'state/staking/hooks' -import { ButtonError } from '../../components/Button' -import { useWeb3Context } from '../../hooks' -import { useVotingEscrowContract } from '../../hooks/useContract' -import { TYPE } from '../../theme' +import { ButtonError } from '../../../components/Button' +import { useWeb3Context } from '../../../hooks' +import { useVotingEscrowContract } from '../../../hooks/useContract' +import { TYPE } from '../../../theme' const MILLISECONDS_PER_SECOND = 1000 const SECONDS_PER_WEEK = 604800 diff --git a/src/pages/Staking/IncreaseLockAmount.tsx b/src/pages/Staking/Lock/IncreaseLockAmount.tsx similarity index 78% rename from src/pages/Staking/IncreaseLockAmount.tsx rename to src/pages/Staking/Lock/IncreaseLockAmount.tsx index 6c55ef4a01a..8307c5abeec 100644 --- a/src/pages/Staking/IncreaseLockAmount.tsx +++ b/src/pages/Staking/Lock/IncreaseLockAmount.tsx @@ -10,23 +10,21 @@ import { useDoTransaction } from 'hooks/useDoTransaction' import React, { useState } from 'react' import { Text } from 'rebass' import { StablePoolInfo } from 'state/stablePools/hooks' -import { useIsDarkMode } from 'state/user/hooks' import { useTokenBalance } from 'state/wallet/hooks' import styled from 'styled-components' +import invariant from 'tiny-invariant' + +import { ButtonConfirmed, ButtonError } from '../../../components/Button' +import Column from '../../../components/Column' +import DoubleCurrencyLogo from '../../../components/DoubleLogo' +import { Input as NumericalInput } from '../../../components/NumericalInput' +import ProgressSteps from '../../../components/ProgressSteps' +import { useWeb3Context } from '../../../hooks' +import { ApprovalState, useApproveCallback } from '../../../hooks/useApproveCallback' +import { useVotingEscrowContract } from '../../../hooks/useContract' +import { tryParseAmount } from '../../../state/swap/hooks' +import { TYPE } from '../../../theme' -import { ButtonConfirmed, ButtonError } from '../../components/Button' -import Column from '../../components/Column' -import DoubleCurrencyLogo from '../../components/DoubleLogo' -import { Input as NumericalInput } from '../../components/NumericalInput' -import ProgressSteps from '../../components/ProgressSteps' -import { useWeb3Context } from '../../hooks' -import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback' -import { useVotingEscrowContract } from '../../hooks/useContract' -import { tryParseAmount } from '../../state/swap/hooks' -import { TYPE } from '../../theme' - -const MILLISECONDS_PER_SECOND = 1000 -const SECONDS_PER_WEEK = 604800 interface IncreaseLockAmountProps { setAttempting: (attempting: boolean) => void setHash: (hash: string | undefined) => void @@ -41,10 +39,10 @@ export default function IncreaseLockAmount({ setHash, setAttempting }: IncreaseL const [approving, setApproving] = useState(false) const [input, setInput] = useState('') const selectedAmount = tryParseAmount(input, mobi) || new TokenAmount(mobi, '0') - const isDarkMode = useIsDarkMode() const doTransaction = useDoTransaction() const veMobiContract = useVotingEscrowContract() + invariant(veMobiContract, 'veMobi contract') const [approval, approveCallback] = useApproveCallback(selectedAmount, veMobiContract.address) const showApproveFlow = @@ -123,7 +121,7 @@ export default function IncreaseLockAmount({ setHash, setAttempting }: IncreaseL ) : ( - + {error ? error : `Increase Lock`} @@ -141,15 +139,10 @@ type CurrencyRowProps = { val: string token: Token setTokenAmount: (tokenAmount: string) => void - readOnly: boolean | undefined balance?: TokenAmount pool?: StablePoolInfo } -const InputRowLeft = styled.div`` - -const TokenInfo = styled.div`` - const InputRow = styled.div<{ selected: boolean }>` ${({ theme }) => theme.flexRowNoWrap}; align-items: center; @@ -168,22 +161,6 @@ const Aligner = styled.span` justify-content: space-between; ` -const InputPanel = styled.div<{ hideInput?: boolean }>` - ${({ theme }) => theme.flexColumnNoWrap} - position: relative; - border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')}; - background-color: ${({ theme }) => theme.bg2}; - z-index: 1; - width: 100%; -` - -const Container = styled.div<{ hideInput: boolean }>` - border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')}; - border: 1px solid ${({ theme }) => theme.bg2}; - background-color: ${({ theme }) => theme.bg1}; - padding: 0.5rem; -` - const StyledTokenName = styled.span<{ active?: boolean }>` ${({ active }) => (active ? ' margin: 0 0.25rem 0 0.75rem;' : ' margin: 0 0.25rem 0 0.25rem;')} font-size: ${({ active }) => (active ? '20px' : '16px')}; @@ -193,13 +170,12 @@ const BalanceText = styled(TYPE.subHeader)` cursor: pointer; ` -export const CurrencyRow = ({ val, token, setTokenAmount, balance, readOnly, pool }: CurrencyRowProps) => { +export const CurrencyRow = ({ val, token, setTokenAmount, balance, pool }: CurrencyRowProps) => { const currency = token const tokenBalance = balance - const TEN = JSBI.BigInt('10') const mainRow = ( - +
{pool ? ( @@ -219,7 +195,6 @@ export const CurrencyRow = ({ val, token, setTokenAmount, balance, readOnly, poo { setTokenAmount(val) @@ -230,7 +205,7 @@ export const CurrencyRow = ({ val, token, setTokenAmount, balance, readOnly, poo ) const decimalPlacesForBalance = tokenBalance?.greaterThan('1') ? 2 : tokenBalance?.greaterThan('0') ? 10 : 2 - const balanceRow = !readOnly && ( + const balanceRow = (
setTokenAmount(tokenBalance?.toExact() || '0')}> Balance: {tokenBalance?.toFixed(decimalPlacesForBalance)} @@ -245,11 +220,3 @@ export const CurrencyRow = ({ val, token, setTokenAmount, balance, readOnly, poo
) } - -const insertDecimal = (tokenAmount: TokenAmount) => { - const { token } = tokenAmount - const amount = tokenAmount.divide( - new TokenAmount(token, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt(token.decimals))) - ) - return amount.toFixed(2) -} diff --git a/src/pages/Staking/Lock.tsx b/src/pages/Staking/Lock/Lock.tsx similarity index 77% rename from src/pages/Staking/Lock.tsx rename to src/pages/Staking/Lock/Lock.tsx index 61e5355212d..fa75914c0e4 100644 --- a/src/pages/Staking/Lock.tsx +++ b/src/pages/Staking/Lock/Lock.tsx @@ -5,26 +5,29 @@ import { JSBI, Token, TokenAmount } from '@ubeswap/sdk' import CurrencyLogo from 'components/CurrencyLogo' import Loader from 'components/Loader' import { AutoRow, RowBetween } from 'components/Row' +import { StablePools } from 'constants/pools' import { useMobi } from 'hooks/Tokens' import { useDoTransaction } from 'hooks/useDoTransaction' import React, { useState } from 'react' import { Calendar } from 'react-date-range' import { Text } from 'rebass' -import { useMobiStakingInfo } from 'state/staking/hooks' -import { useIsDarkMode } from 'state/user/hooks' +import { GaugeInfo, UserGaugeInfo } from 'state/gauges/hooks' +import { StakingInfo } from 'state/staking/hooks' import { useTokenBalance } from 'state/wallet/hooks' import styled from 'styled-components' +import invariant from 'tiny-invariant' import { calcBoost, calcExpectedVeMobi } from 'utils/calcExpectedVeMobi' -import { ButtonConfirmed, ButtonError } from '../../components/Button' -import Column from '../../components/Column' -import { Input as NumericalInput } from '../../components/NumericalInput' -import ProgressSteps from '../../components/ProgressSteps' -import { useWeb3Context } from '../../hooks' -import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback' -import { useVotingEscrowContract } from '../../hooks/useContract' -import { tryParseAmount } from '../../state/swap/hooks' -import { TYPE } from '../../theme' +import { ButtonConfirmed, ButtonError } from '../../../components/Button' +import Column from '../../../components/Column' +import { Input as NumericalInput } from '../../../components/NumericalInput' +import ProgressSteps from '../../../components/ProgressSteps' +import { CHAIN } from '../../../constants' +import { useWeb3Context } from '../../../hooks' +import { ApprovalState, useApproveCallback } from '../../../hooks/useApproveCallback' +import { useVotingEscrowContract } from '../../../hooks/useContract' +import { tryParseAmount } from '../../../state/swap/hooks' +import { TYPE } from '../../../theme' const MILLISECONDS_PER_SECOND = 1000 const SECONDS_PER_WEEK = 604800 @@ -36,30 +39,35 @@ export const roundDate = (date: number) => interface LockProps { setAttempting: (attempting: boolean) => void setHash: (hash: string | undefined) => void + userGauges: (UserGaugeInfo | null)[] + gauges: (GaugeInfo | null)[] + stakingInfo: StakingInfo } -export default function Lock({ setHash, setAttempting }: LockProps) { +export default function Lock({ setHash, setAttempting, userGauges, gauges, stakingInfo }: LockProps) { const { connected, address } = useWeb3Context() // monitor call to help UI loading state - const stakingInfo = useMobiStakingInfo() - const positions = stakingInfo.positions?.filter((pos) => pos.baseBalance.greaterThan('0')) ?? [] const mobi = useMobi() const balance = useTokenBalance(connected ? address : undefined, mobi) + const [approving, setApproving] = useState(false) const [input, setInput] = useState('') const [showBoosts, setShowBoosts] = useState(false) + const selectedAmount = tryParseAmount(input, mobi) || new TokenAmount(mobi, '0') const [date, setDate] = useState() - const isDarkMode = useIsDarkMode() - const roundedDate = date ? roundDate(date) : undefined + const roundedDate = date ? roundDate(date.getSeconds()) : undefined const doTransaction = useDoTransaction() const veMobiContract = useVotingEscrowContract() const expectedVeMobi = calcExpectedVeMobi( selectedAmount, - roundedDate ? roundedDate.getTime() - roundDate(new Date(Date.now())).getTime() : 0 + roundedDate ? roundedDate.getTime() - roundDate(Date.now()).getTime() : 0 ) + + invariant(veMobiContract, 'veMobi contract') + const [approval, approveCallback] = useApproveCallback(selectedAmount, veMobiContract.address) const showApproveFlow = approval === ApprovalState.NOT_APPROVED || @@ -116,15 +124,18 @@ export default function Lock({ setHash, setAttempting }: LockProps) { Show Boosts ) : ( - positions.map((pos) => { + userGauges.map((ug, i) => { + if (ug === null || JSBI.equal(ug.balance, JSBI.BigInt(0))) return null const boost = calcBoost( - pos, + ug?.balance, + gauges[i]?.totalSupply ?? JSBI.BigInt(0), expectedVeMobi.raw, JSBI.add(expectedVeMobi.raw, stakingInfo.totalVotingPower.raw) ) + const poolName = StablePools[CHAIN][i].name return ( - - {pos.pool} + + {poolName} {boost.toFixed(2)}x ) @@ -166,7 +177,7 @@ export default function Lock({ setHash, setAttempting }: LockProps) { ) : ( - + {error ? error : `Lock until ${roundedDate?.toLocaleDateString()}`} @@ -184,14 +195,9 @@ type CurrencyRowProps = { val: string token: Token setTokenAmount: (tokenAmount: string) => void - readOnly: boolean | undefined balance?: TokenAmount } -const InputRowLeft = styled.div`` - -const TokenInfo = styled.div`` - const InputRow = styled.div<{ selected: boolean }>` ${({ theme }) => theme.flexRowNoWrap}; align-items: center; @@ -210,22 +216,6 @@ const Aligner = styled.span` justify-content: space-between; ` -const InputPanel = styled.div<{ hideInput?: boolean }>` - ${({ theme }) => theme.flexColumnNoWrap} - position: relative; - border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')}; - background-color: ${({ theme }) => theme.bg2}; - z-index: 1; - width: 100%; -` - -const Container = styled.div<{ hideInput: boolean }>` - border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')}; - border: 1px solid ${({ theme }) => theme.bg2}; - background-color: ${({ theme }) => theme.bg1}; - padding: 0.5rem; -` - const StyledTokenName = styled.span<{ active?: boolean }>` ${({ active }) => (active ? ' margin: 0 0.25rem 0 0.75rem;' : ' margin: 0 0.25rem 0 0.25rem;')} font-size: ${({ active }) => (active ? '20px' : '16px')}; @@ -235,13 +225,12 @@ const BalanceText = styled(TYPE.subHeader)` cursor: pointer; ` -const CurrencyRow = ({ val, token, setTokenAmount, balance, readOnly }: CurrencyRowProps) => { +const CurrencyRow = ({ val, token, setTokenAmount, balance }: CurrencyRowProps) => { const currency = token const tokenBalance = balance - const TEN = JSBI.BigInt('10') const mainRow = ( - +
@@ -257,7 +246,6 @@ const CurrencyRow = ({ val, token, setTokenAmount, balance, readOnly }: Currency { setTokenAmount(val) @@ -268,7 +256,7 @@ const CurrencyRow = ({ val, token, setTokenAmount, balance, readOnly }: Currency ) const decimalPlacesForBalance = tokenBalance?.greaterThan('1') ? 2 : tokenBalance?.greaterThan('0') ? 10 : 2 - const balanceRow = !readOnly && ( + const balanceRow = (
setTokenAmount(tokenBalance?.toExact() || '0')}> Balance: {tokenBalance?.toFixed(decimalPlacesForBalance)} @@ -283,11 +271,3 @@ const CurrencyRow = ({ val, token, setTokenAmount, balance, readOnly }: Currency
) } - -const insertDecimal = (tokenAmount: TokenAmount) => { - const { token } = tokenAmount - const amount = tokenAmount.divide( - new TokenAmount(token, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt(token.decimals))) - ) - return amount.toFixed(2) -} diff --git a/src/pages/Staking/LockModal.tsx b/src/pages/Staking/Lock/LockModal.tsx similarity index 79% rename from src/pages/Staking/LockModal.tsx rename to src/pages/Staking/Lock/LockModal.tsx index 00a7ec0d92d..3dab73fc752 100644 --- a/src/pages/Staking/LockModal.tsx +++ b/src/pages/Staking/Lock/LockModal.tsx @@ -4,15 +4,17 @@ import Loader from 'components/Loader' import { ExternalStakingRewards } from 'constants/staking' import { useStakingContract } from 'hooks/useContract' import React, { useState } from 'react' +import { GaugeInfo, UserGaugeInfo } from 'state/gauges/hooks' +import { StakingInfo } from 'state/staking/hooks' import { useTransactionAdder } from 'state/transactions/hooks' import styled from 'styled-components' -import { AutoColumn } from '../../components/Column' -import Modal from '../../components/Modal' -import { LoadingView, SubmittedView } from '../../components/ModalViews' -import { RowBetween } from '../../components/Row' -import { CHAIN } from '../../constants' -import { CloseIcon, TYPE } from '../../theme' +import { AutoColumn } from '../../../components/Column' +import Modal from '../../../components/Modal' +import { LoadingView, SubmittedView } from '../../../components/ModalViews' +import { RowBetween } from '../../../components/Row' +import { CHAIN } from '../../../constants' +import { CloseIcon, TYPE } from '../../../theme' import ExtendLock from './ExtendLock' import IncreaseLockAmount from './IncreaseLockAmount' import Lock from './Lock' @@ -31,6 +33,9 @@ interface LockModalProps { isOpen: boolean onDismiss: () => void lockType?: LockType + stakingInfo: StakingInfo + gauges: (GaugeInfo | null)[] + userGauges: (UserGaugeInfo | null)[] } const ModifiedWrapper = styled(ContentWrapper)` @@ -41,7 +46,14 @@ const ModifiedWrapper = styled(ContentWrapper)` } ` -export default function LockModal({ isOpen, onDismiss, lockType = LockType.initial }: LockModalProps) { +export default function LockModal({ + isOpen, + onDismiss, + lockType = LockType.initial, + stakingInfo, + gauges, + userGauges, +}: LockModalProps) { // monitor call to help UI loading state const stakingContract = useStakingContract(ExternalStakingRewards[CHAIN]) const addTransaction = useTransactionAdder() @@ -92,7 +104,13 @@ export default function LockModal({ isOpen, onDismiss, lockType = LockType.initi {hasSnapshot === 0 ? Snapshot veMOBI Celo Rewards : } ) : lockType === LockType.initial ? ( - + ) : lockType === LockType.extend ? ( ) : ( diff --git a/src/pages/Staking/Stake.tsx b/src/pages/Staking/Stake.tsx index 81b0c28a76e..2309a545f28 100644 --- a/src/pages/Staking/Stake.tsx +++ b/src/pages/Staking/Stake.tsx @@ -4,13 +4,14 @@ import { AutoColumn } from 'components/Column' import { RowBetween } from 'components/Row' import React, { useState } from 'react' import Countdown from 'react-countdown' -import { UserStakingInfo } from 'state/staking/hooks' +import { GaugeInfo, UserGaugeInfo } from 'state/gauges/hooks' +import { StakingInfo, UserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { theme, TYPE } from 'theme' import { useVotingEscrowContract } from '../../hooks/useContract' import { useTransactionAdder } from '../../state/transactions/hooks' -import LockModal, { LockType } from './LockModal' +import LockModal, { LockType } from './Lock/LockModal' const SECONDS_IN_DAY = 24 * 60 * 60 @@ -49,8 +50,11 @@ const Wrapper = styled(AutoColumn)<{ showBackground: boolean }>` type PropTypes = { userStakingInfo: UserStakingInfo + stakingInfo: StakingInfo + userGauges: (UserGaugeInfo | null)[] + gauges: (GaugeInfo | null)[] } -export default function Stake({ userStakingInfo }: PropTypes) { +export default function Stake({ userStakingInfo, stakingInfo, userGauges, gauges }: PropTypes) { const { lock } = userStakingInfo const [lockType, setLockType] = useState(-1) @@ -80,7 +84,14 @@ export default function Stake({ userStakingInfo }: PropTypes) { return ( - -1} onDismiss={() => setLockType(-1)} lockType={lockType} /> + -1} + onDismiss={() => setLockType(-1)} + lockType={lockType} + stakingInfo={stakingInfo} + userGauges={userGauges} + gauges={gauges} + /> Locked MOBI: diff --git a/src/pages/Staking/index.tsx b/src/pages/Staking/index.tsx index d227ff7ab57..106ebba14f6 100644 --- a/src/pages/Staking/index.tsx +++ b/src/pages/Staking/index.tsx @@ -1,16 +1,15 @@ +import { TokenAmount } from '@ubeswap/sdk' +import { useMobi } from 'hooks/Tokens' import React from 'react' import { isMobile } from 'react-device-detect' +import { useAllGaugesInfo, useAllUserGaugesInfo, UserGaugeInfo } from 'state/gauges/hooks' import { useStakingInfo, useUserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { Row } from '../../components/Row' -import CalcBoost from './CalcBoost' -import GaugeWeights from './GaugeWeights' -import Positions from './Positions' import Stake from './Stake' import StatsHeader from './StatsHeader' import VeMobiRewards from './VeMobiRewards' -import Vote from './Vote' const PositionsContainer = styled.div` width: 100%; @@ -73,8 +72,18 @@ enum View { Rewards = 4, } +export const useAllClaimableMobi = (userGauges: (UserGaugeInfo | null)[]): TokenAmount => { + const mobi = useMobi() + return userGauges.reduce( + (accum, userGauge) => (userGauge ? accum.add(userGauge.claimableMobi) : accum), + new TokenAmount(mobi, '0') + ) +} + export default function Staking() { - // const unclaimedMobi = new TokenAmount(mobi, getAllUnclaimedMobi(stakingInfo.positions ?? [])) + const userGauges = useAllUserGaugesInfo() + const gauges = useAllGaugesInfo() + const claimableMobi = useAllClaimableMobi(userGauges) const stakingInfo = useStakingInfo() const userStakingInfo = useUserStakingInfo() @@ -101,18 +110,16 @@ export default function Staking() {
{view === View.Lock ? ( - - - + + {/* */} + {/* */} ) : view === View.Vote ? ( - + {/* */} ) : view === View.Analyze ? ( - - - + {/* */} ) : ( diff --git a/src/state/gauges/updater.ts b/src/state/gauges/updater.ts index 04d21d22427..e4c8a2e336c 100644 --- a/src/state/gauges/updater.ts +++ b/src/state/gauges/updater.ts @@ -65,7 +65,7 @@ export function GaugeUpdater() { dispatch( updateGaugesUser({ userGaugeState: StablePools[CHAIN].map((displayPool, i) => { - return displayPool === null + return displayPool.gauge === null ? null : { balance: JSBI.BigInt(balance[i].result?.[0] ?? '0'), @@ -80,7 +80,7 @@ export function GaugeUpdater() { dispatch( updateGauges({ gaugeState: StablePools[CHAIN].map((display, i) => { - return display === null + return display.gauge === null ? null : { isKilled: isKilled[0].result?.[0] === false, diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index 8f5af1d9d61..5d6b4e2b6e7 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -42,12 +42,12 @@ export function UpdatePools() { } } ` - const { data, loading, error } = useQuery(query) + const { data, loading } = useQuery(query) useEffect(() => { if (loading) return - const inSubgraph: Set = - data?.swaps.reduce((accum: Set, cur: any) => new Set([...accum, cur.id]), new Set()) ?? new Set() + // const inSubgraph: Set = + // data?.swaps.reduce((accum: Set, cur: any) => new Set([...accum, cur.id]), new Set()) ?? new Set() try { dispatch( updatePools({ @@ -59,7 +59,7 @@ export function UpdatePools() { ampFactor: RECOMMENDED_AMP, lpTotalSupply: new TokenAmount( displayPool.pool.lpToken, - JSBI.BigInt(lpTotalSupply[i]?.result?.[0]) ?? '0' + JSBI.BigInt(lpTotalSupply[i]?.result?.[0] ?? '0') ), reserves: balances?.[i]?.result?.[0] ? balances?.[i]?.result?.[0].map( diff --git a/src/state/staking/updater.ts b/src/state/staking/updater.ts index 4c4916a3445..c637cd74ce2 100644 --- a/src/state/staking/updater.ts +++ b/src/state/staking/updater.ts @@ -2,7 +2,7 @@ import { JSBI } from '@ubeswap/sdk' import { ExternalStakingRewards } from 'constants/staking' import { VEMOBI } from 'constants/tokens' import { useWeb3Context } from 'hooks' -import { roundDate } from 'pages/Staking/Lock' +import { roundDate } from 'pages/Staking/Lock/Lock' import { useEffect } from 'react' import { useDispatch } from 'react-redux' import { AppDispatch } from 'state' diff --git a/src/utils/calcExpectedVeMobi.ts b/src/utils/calcExpectedVeMobi.ts index 85a7e3a6a34..1424d9cdb0b 100644 --- a/src/utils/calcExpectedVeMobi.ts +++ b/src/utils/calcExpectedVeMobi.ts @@ -1,20 +1,20 @@ import { Fraction, JSBI, Token, TokenAmount } from '@ubeswap/sdk' import { GaugeSummary } from 'state/staking/hooks' -export function calcBoost(summary: GaugeSummary, votingPower: JSBI, totalVotingPower: JSBI): Fraction { - const { baseBalance, totalStaked } = summary - const baseWeighted = JSBI.divide(JSBI.multiply(JSBI.BigInt(4), baseBalance.raw), JSBI.BigInt(10)) +// TODO double check that this math is correct +export function calcBoost(userBalance: JSBI, totalSupply: JSBI, votingPower: JSBI, totalVotingPower: JSBI): Fraction { + const baseWeighted = JSBI.divide(JSBI.multiply(JSBI.BigInt(4), userBalance), JSBI.BigInt(10)) let weighted = baseWeighted if (JSBI.greaterThan(totalVotingPower, JSBI.BigInt('0'))) { weighted = JSBI.add( - JSBI.divide(JSBI.multiply(JSBI.BigInt(4), baseBalance.raw), JSBI.BigInt(10)), + JSBI.divide(JSBI.multiply(JSBI.BigInt(4), userBalance), JSBI.BigInt(10)), JSBI.divide( - JSBI.multiply(JSBI.BigInt(6), JSBI.multiply(totalStaked.raw, votingPower)), + JSBI.multiply(JSBI.BigInt(6), JSBI.multiply(totalSupply, votingPower)), JSBI.multiply(totalVotingPower, JSBI.BigInt(10)) ) ) } - const min = JSBI.lessThan(weighted, baseBalance.raw) ? weighted : baseBalance.raw + const min = JSBI.lessThan(weighted, userBalance) ? weighted : userBalance return new Fraction(min, baseWeighted) } From 69d88299580f88478b14d7885745a8353a4b1f1c Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 12:48:35 -0500 Subject: [PATCH 32/72] stake vote page --- src/hooks/useColor.ts | 6 +- src/pages/Staking/GaugeVoteModal.tsx | 33 +++---- src/pages/Staking/GaugeWeights.tsx | 125 ++++--------------------- src/pages/Staking/{ => Lock}/Stake.tsx | 6 +- src/pages/Staking/VeMobiRewards.tsx | 3 - src/pages/Staking/Vote.tsx | 88 +++++++++-------- src/pages/Staking/index.tsx | 10 +- src/state/gauges/hooks.ts | 14 +-- 8 files changed, 101 insertions(+), 184 deletions(-) rename src/pages/Staking/{ => Lock}/Stake.tsx (96%) diff --git a/src/hooks/useColor.ts b/src/hooks/useColor.ts index 0f2c517f122..45a7a0e6552 100644 --- a/src/hooks/useColor.ts +++ b/src/hooks/useColor.ts @@ -1,9 +1,9 @@ import { ChainId, Token } from '@ubeswap/sdk' +import { DisplayPool } from 'constants/pools' import { Coins, STATIC_POOL_INFO } from 'constants/StablePools' import Vibrant from 'node-vibrant' import { shade } from 'polished' import { useLayoutEffect, useState } from 'react' -import { StablePoolInfo } from 'state/stablePools/hooks' import { useTheme } from 'styled-components' import uriToHttp from 'utils/uriToHttp' import { hex } from 'wcag-contrast' @@ -82,9 +82,9 @@ export function generateColorPallete(tokens: Token[]) { return colors.join('\n') } -export function usePoolColor(pool: StablePoolInfo) { +export function usePoolColor(pool: DisplayPool) { const theme = useTheme() - const coin = pool.coin + const coin = pool.peg.coin if (coin === Coins.USD) return theme.cusd if (coin === Coins.Eur) return theme.ceur if (coin === Coins.Ether) return theme.ether diff --git a/src/pages/Staking/GaugeVoteModal.tsx b/src/pages/Staking/GaugeVoteModal.tsx index 80b28c2170a..4db90b98e2c 100644 --- a/src/pages/Staking/GaugeVoteModal.tsx +++ b/src/pages/Staking/GaugeVoteModal.tsx @@ -1,9 +1,9 @@ import { TransactionResponse } from '@ethersproject/providers' -import { JSBI } from '@ubeswap/sdk' +import { IGauge } from 'constants/pools' import { useVotePowerLeft } from 'hooks/useStaking' import { MaxButton } from 'pages/Pool/styleds' import React, { useState } from 'react' -import { GaugeSummary } from 'state/staking/hooks' +import { UserGaugeInfo } from 'state/gauges/hooks' import styled from 'styled-components' import { ButtonError } from '../../components/Button' @@ -25,18 +25,16 @@ const ContentWrapper = styled(AutoColumn)` interface GaugeVoteModalProps { isOpen: boolean onDismiss: () => void - summary: GaugeSummary - disabled: boolean + userGauge: UserGaugeInfo + gauge: IGauge + poolName: string } -export const getAllUnclaimedMobi = (summaries: GaugeSummary[]): JSBI => - summaries.reduce((accum, { unclaimedMobi }) => JSBI.add(accum, unclaimedMobi.raw), JSBI.BigInt(0)) - function daysBetween(d1: Date, d2: Date): number { return Math.floor((d1.getTime() - d2.getTime()) / (1000 * 3600 * 24)) } -export default function GaugeVoteModal({ isOpen, onDismiss, summary, disabled }: GaugeVoteModalProps) { +export default function GaugeVoteModal({ isOpen, onDismiss, userGauge, poolName, gauge }: GaugeVoteModalProps) { const { connected } = useWeb3Context() // monitor call to help UI loading state @@ -44,9 +42,8 @@ export default function GaugeVoteModal({ isOpen, onDismiss, summary, disabled }: const [hash, setHash] = useState() const [attempting, setAttempting] = useState(false) const [input, setInput] = useState(0) - const votesLeft = useVotePowerLeft() + summary.powerAllocated + const votesLeft = useVotePowerLeft() + userGauge.powerAllocated const today = new Date(Date.now()) - const lastVote = summary.lastVote function wrappedOnDismiss() { setHash(undefined) @@ -60,10 +57,10 @@ export default function GaugeVoteModal({ isOpen, onDismiss, summary, disabled }: if (controller) { setAttempting(true) await controller - .vote_for_gauge_weights(summary.address, input * 100, { gasLimit: 350000 }) + .vote_for_gauge_weights(gauge.address, input * 100, { gasLimit: 350000 }) .then((response: TransactionResponse) => { addTransaction(response, { - summary: `Voted ${disabled ? 'to burn' : `for ${summary.pool} to receive`} ${input}% of MOBI inflation`, + summary: `Voted for ${poolName} to receive ${input}% of MOBI inflation`, }) setHash(response.hash) }) @@ -79,8 +76,8 @@ export default function GaugeVoteModal({ isOpen, onDismiss, summary, disabled }: error = 'Connect Wallet' } - if (daysBetween(today, lastVote) < 10) { - error = error ?? `Wait ${10 - daysBetween(today, lastVote)} days to vote for this pool again` + if (daysBetween(today, new Date(userGauge.lastVote)) < 10) { + error = error ?? `Wait ${10 - daysBetween(today, new Date(userGauge.lastVote))} days to vote for this pool again` } return ( @@ -88,7 +85,7 @@ export default function GaugeVoteModal({ isOpen, onDismiss, summary, disabled }: {!attempting && !hash && ( - Vote for {disabled ? 'BURN' : summary.pool} + Vote for {poolName} {votesLeft === 0 ? ( @@ -124,9 +121,7 @@ export default function GaugeVoteModal({ isOpen, onDismiss, summary, disabled }: - {`Vote ${ - disabled ? 'to burn' : `for ${summary.pool} to receive` - } ${input}% of MOBI inflation`} + {`Vote for ${poolName} to receive ${input}% of MOBI inflation`} {error ?? `Vote!`} @@ -146,7 +141,7 @@ export default function GaugeVoteModal({ isOpen, onDismiss, summary, disabled }: Transaction Submitted - veMOBI allocated to {summary.pool} + veMOBI allocated to {poolName} )} diff --git a/src/pages/Staking/GaugeWeights.tsx b/src/pages/Staking/GaugeWeights.tsx index c4279b3fb91..a021384556f 100644 --- a/src/pages/Staking/GaugeWeights.tsx +++ b/src/pages/Staking/GaugeWeights.tsx @@ -1,21 +1,20 @@ -import { CardNoise } from 'components/claim/styled' +import { JSBI } from '@ubeswap/sdk' import { AutoColumn } from 'components/Column' import Loader from 'components/Loader' import { AutoRow, RowBetween, RowFixed } from 'components/Row' -import { useColor } from 'hooks/useColor' +import { StablePools } from 'constants/pools' import { useWindowSize } from 'hooks/useWindowSize' import { darken } from 'polished' -import React, { useState } from 'react' +import React from 'react' import { isMobile } from 'react-device-detect' import { RadialChart } from 'react-vis' -import { GaugeSummary } from 'state/staking/hooks' -import { useIsDarkMode } from 'state/user/hooks' +import { GaugeInfo } from 'state/gauges/hooks' import styled from 'styled-components' import { TYPE } from 'theme' -import GaugeVoteModal from './GaugeVoteModal' +import { CHAIN } from '../../constants' -const Wrapper = styled(AutoColumn)<{ showBackground: boolean; background: any }>` +const Wrapper = styled(AutoColumn)` border-radius: 12px; width: 100%; overflow: hidden; @@ -23,13 +22,9 @@ const Wrapper = styled(AutoColumn)<{ showBackground: boolean; background: any }> padding: 1rem; background: ${({ theme }) => theme.bg1}; color: ${({ theme }) => theme.text1} !important; - ${({ showBackground }) => - showBackground && - ` box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), - 0px 24px 32px rgba(0, 0, 0, 0.01);`} ${({ theme }) => theme.mediaWidth.upToSmall` `} -margin-top: 1rem; + margin-top: 1rem; ` const WrappedRow = styled.div` display: flex; @@ -38,13 +33,6 @@ const WrappedRow = styled.div` justify-content: center; ` -const CardContainer = styled.div` - display: flex; - flex-wrap: wrap; - margin-top: 1rem; - justify-content: space-between; -` - const ColorBox = styled.div<{ color: string }>` background: ${({ color }) => color}; width: 20px; @@ -57,21 +45,21 @@ const ColorBox = styled.div<{ color: string }>` const colorsForChart = ['#35D07F', '#73DDFF', '#BF97FF', '#3488EC', '#FB7C6D', '#FBCC5C', '#FEF2D6'] interface GaugeWeightsProps { - summaries: GaugeSummary[] + gauges: (GaugeInfo | null)[] } // TO DO: Account for Vote Power Allocations -export default function GaugeWeights({ summaries }: GaugeWeightsProps) { +export default function GaugeWeights({ gauges }: GaugeWeightsProps) { const numColors = colorsForChart.length - const data = summaries.map((summary, i) => ({ - label: summary.pool, - angle: parseInt(summary.currentWeight.multiply('360').toFixed(0)), - radius: summary.workingBalance.greaterThan('0') ? 10 : 9.5, - subLabel: `${summary.currentWeight.toFixed(2)}%`, + const data = gauges.map((g, i) => ({ + label: StablePools[CHAIN][i].name, + angle: parseInt(g?.weight.multiply('360').toFixed(0) ?? '0'), + radius: JSBI.greaterThan(g?.workingSupply ?? JSBI.BigInt(0), JSBI.BigInt(0)) ? 10 : 9.5, + subLabel: `${g?.weight.toFixed(2) ?? '0'}%`, color: darken(Math.floor(i / numColors) * 0.2, colorsForChart[i % numColors]), })) - const isDarkMode = useIsDarkMode() - const { width, height } = useWindowSize() + + const { width } = useWindowSize() return ( @@ -100,7 +88,7 @@ export default function GaugeWeights({ summaries }: GaugeWeightsProps) { /> {!isMobile && ( - {data.map(({ label, subLabel, color }) => ( + {data.map(({ label, color }) => ( {label} @@ -110,7 +98,7 @@ export default function GaugeWeights({ summaries }: GaugeWeightsProps) { {isMobile && ( - {data.map(({ label, subLabel, color }) => ( + {data.map(({ label, color }) => ( {label} @@ -122,80 +110,3 @@ export default function GaugeWeights({ summaries }: GaugeWeightsProps) { ) } - -const PositionWrapper = styled(AutoColumn)<{ - showBackground: boolean - bgColor: any - activated: boolean - disabled: boolean -}>` - border-radius: 12px; - width: 100%; - height: fit-content; - overflow: hidden; - position: relative; - margin-bottom: 1rem; - padding: 1rem; - cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')}; - opacity: ${({ activated }) => (activated ? 1 : 0.9)}; - overflow: hidden; - position: relative; - background: ${({ bgColor, theme }) => - `radial-gradient(91.85% 100% at 1.84% 0%, ${bgColor} 0%, ${theme.black} 100%) `}; - color: ${({ theme, showBackground }) => (showBackground ? theme.white : theme.text1)} !important; - ${({ showBackground }) => - showBackground && - ` box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), - 0px 24px 32px rgba(0, 0, 0, 0.01);`} - ${({ theme }) => theme.mediaWidth.upToSmall` -`} - &:hover { - opacity: 1; - } -` -const RowWithGap = styled(RowFixed)` - gap: 8px; -` - -function WeightCard({ - position, - showUserVote, - disabled, -}: { - position: GaugeSummary - showUserVote: boolean - disabled: boolean -}) { - const backgroundColor = useColor(position.firstToken) - const [voteModalOpen, setVoteModalOpen] = useState(false) - - return ( - <> - setVoteModalOpen(false)} /> - - !disabled && setVoteModalOpen(true)} - > - - - {position.pool} - {showUserVote ? ( - - Your Vote: - {`${position.powerAllocated.toFixed(2)}%`} - - ) : ( - - {`Current: ${position.currentWeight.toFixed(2)}%`} - {`Future: ${position.futureWeight.toFixed(2)}%`} - - )} - - - - ) -} diff --git a/src/pages/Staking/Stake.tsx b/src/pages/Staking/Lock/Stake.tsx similarity index 96% rename from src/pages/Staking/Stake.tsx rename to src/pages/Staking/Lock/Stake.tsx index 2309a545f28..34ca69fac08 100644 --- a/src/pages/Staking/Stake.tsx +++ b/src/pages/Staking/Lock/Stake.tsx @@ -9,9 +9,9 @@ import { StakingInfo, UserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { theme, TYPE } from 'theme' -import { useVotingEscrowContract } from '../../hooks/useContract' -import { useTransactionAdder } from '../../state/transactions/hooks' -import LockModal, { LockType } from './Lock/LockModal' +import { useVotingEscrowContract } from '../../../hooks/useContract' +import { useTransactionAdder } from '../../../state/transactions/hooks' +import LockModal, { LockType } from './LockModal' const SECONDS_IN_DAY = 24 * 60 * 60 diff --git a/src/pages/Staking/VeMobiRewards.tsx b/src/pages/Staking/VeMobiRewards.tsx index f6127b4ab7d..49e9c10776f 100644 --- a/src/pages/Staking/VeMobiRewards.tsx +++ b/src/pages/Staking/VeMobiRewards.tsx @@ -236,9 +236,6 @@ export default function VeMobiRewards() { <> - {/* - Claim - */} Available to Claim: {claimableRewards ? ( diff --git a/src/pages/Staking/Vote.tsx b/src/pages/Staking/Vote.tsx index d0426e54420..370d4c33ced 100644 --- a/src/pages/Staking/Vote.tsx +++ b/src/pages/Staking/Vote.tsx @@ -1,18 +1,20 @@ import { AutoColumn } from 'components/Column' -import Loader from 'components/Loader' import { RowFixed } from 'components/Row' +import { DisplayPool, StablePools } from 'constants/pools' import { ChainLogo } from 'constants/StablePools' import { usePoolColor } from 'hooks/useColor' import { useVotePowerLeft } from 'hooks/useStaking' import React, { useState } from 'react' import { isMobile } from 'react-device-detect' -import { GaugeSummary } from 'state/staking/hooks' +import { GaugeInfo, UserGaugeInfo } from 'state/gauges/hooks' +import { UserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { TYPE } from 'theme' +import invariant from 'tiny-invariant' import CurrencyPoolLogo from '../../components/CurrencyPoolLogo' import Logo from '../../components/Logo' -import { useStablePoolInfo } from '../../state/stablePools/hooks' +import { CHAIN } from '../../constants' import GaugeVoteModal from './GaugeVoteModal' const Wrapper = styled(AutoColumn)` @@ -57,20 +59,17 @@ const TopSection = styled.div` `}; ` -interface GaugeWeightsProps { - summaries: GaugeSummary[] - lockDate: Date +interface VoteProps { + gauges: (GaugeInfo | null)[] + userGauges: (UserGaugeInfo | null)[] + userStaking: UserStakingInfo } -export default function Vote({ summaries, lockDate }: GaugeWeightsProps) { +export default function Vote({ gauges, userGauges, userStaking }: VoteProps) { const votePowerLeft = useVotePowerLeft() - const tooLateToVote = lockDate.valueOf() - Date.now() <= 7 * 24 * 60 * 60 * 1000 + const tooLateToVote = userStaking.lock.end.valueOf() - Date.now() <= 7 * 24 * 60 * 60 * 1000 - return summaries.length === 0 ? ( - - - - ) : ( + return ( Allocate your voting power to affect the MOBI distribution of each pool. {votePowerLeft}% Left to Allocate @@ -80,9 +79,20 @@ export default function Vote({ summaries, lockDate }: GaugeWeightsProps) { )} - {summaries.map((summary) => ( - - ))} + {gauges.map((g, i) => { + if (g === null) return null + const userGauge = userGauges[i] + invariant(userGauge, 'user gauge') + return ( + + ) + })} ) @@ -141,43 +151,50 @@ const SecondSection = styled.div<{ mobile: boolean }>` `}; ` -function WeightCard({ position, disabled }: { position: GaugeSummary; disabled: boolean }) { +function WeightCard({ + userGauge, + gauge, + displayPool, + disabled, +}: { + userGauge: UserGaugeInfo + gauge: GaugeInfo + displayPool: DisplayPool + disabled: boolean +}) { const [voteModalOpen, setVoteModalOpen] = useState(false) - const stablePools = useStablePoolInfo() - const poolInfo = stablePools.filter((x) => x.name === position.pool)[0] - const poolColor = usePoolColor(poolInfo) + const poolColor = usePoolColor(displayPool) - return ( + return displayPool.gauge === null ? null : ( <> setVoteModalOpen(false)} - disabled={poolInfo.isDisabled ?? false} /> !disabled && setVoteModalOpen(true)}> - {poolInfo.isDisabled ? 'BURN' : position.pool} + {displayPool.name} - {!poolInfo.isDisabled && ( - - )} + - {`Future: ${position.futureWeight.toFixed(2)}%`} + {`Future: ${gauge.futureWeight.toFixed(2)}%`} - + - {poolInfo.tokens.map((t) => t.symbol).join(' / ')} + {displayPool.pool.tokens.map((t) => t.symbol).join(' / ')}
@@ -186,22 +203,15 @@ function WeightCard({ position, disabled }: { position: GaugeSummary; disabled: fontSize={[13, 16]} fontWeight={800} color={poolColor} - >{`Current: ${position.currentWeight.toFixed(2)}%`} + >{`Current: ${gauge.weight.toFixed(2)}%`} {`My Vote: ${position.powerAllocated.toFixed(2)}%`} + >{`My Vote: ${userGauge.powerAllocated.toFixed(2)}%`}
- {poolInfo.isDisabled && ( - - - Any inflation allocated toward this gauge will be burnt. - - - )}
) diff --git a/src/pages/Staking/index.tsx b/src/pages/Staking/index.tsx index 106ebba14f6..ee452dbf598 100644 --- a/src/pages/Staking/index.tsx +++ b/src/pages/Staking/index.tsx @@ -7,9 +7,11 @@ import { useStakingInfo, useUserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { Row } from '../../components/Row' -import Stake from './Stake' +import GaugeWeights from './GaugeWeights' +import Stake from './Lock/Stake' import StatsHeader from './StatsHeader' import VeMobiRewards from './VeMobiRewards' +import Vote from './Vote' const PositionsContainer = styled.div` width: 100%; @@ -116,10 +118,12 @@ export default function Staking() {
) : view === View.Vote ? ( - {/* */} + ) : view === View.Analyze ? ( - {/* */} + + + ) : ( diff --git a/src/state/gauges/hooks.ts b/src/state/gauges/hooks.ts index a128244c002..e1dee8284ad 100644 --- a/src/state/gauges/hooks.ts +++ b/src/state/gauges/hooks.ts @@ -1,5 +1,5 @@ import { invariant } from '@apollo/client/utilities/globals' -import { JSBI, TokenAmount } from '@ubeswap/sdk' +import { JSBI, Percent, TokenAmount } from '@ubeswap/sdk' import { IGauge, StablePools } from 'constants/pools' import { useMobi } from 'hooks/Tokens' import { useSelector } from 'react-redux' @@ -19,8 +19,8 @@ export function useUserGauges(): readonly (IUserGaugeState | null)[] { export type GaugeInfo = { isKilled: boolean lastClaim: Date - weight: number - futureWeight: number + weight: Percent + futureWeight: Percent totalSupply: JSBI workingSupply: JSBI totalEffectiveBalance: JSBI @@ -43,8 +43,8 @@ export function useAllGaugesInfo(): (GaugeInfo | null)[] { : { ...g, lastClaim: new Date(g.lastClaim), - weight: g.lastClaim.valueOf(), - futureWeight: g.lastClaim.valueOf(), + weight: new Percent(g.weight), + futureWeight: new Percent(g.futureWeight), } ) } @@ -75,8 +75,8 @@ export function useGaugeInfo(gauge: IGauge): GaugeInfo { : { ...g, lastClaim: new Date(g.lastClaim), - weight: g.lastClaim.valueOf(), - futureWeight: g.lastClaim.valueOf(), + weight: new Percent(g.weight), + futureWeight: new Percent(g.futureWeight), } ) invariant(gaugeInfo.length === 1, 'duplicate gauges') From 8734d1b1761c420ffc8da07acdba29418e178887 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 13:56:40 -0500 Subject: [PATCH 33/72] stake positions --- src/pages/Staking/ClaimAllMobiModal.tsx | 35 +++--- src/pages/Staking/Positions.tsx | 136 +++++++++++------------- src/pages/Staking/index.tsx | 9 +- 3 files changed, 85 insertions(+), 95 deletions(-) diff --git a/src/pages/Staking/ClaimAllMobiModal.tsx b/src/pages/Staking/ClaimAllMobiModal.tsx index eac01de4fbe..ae5ba58df54 100644 --- a/src/pages/Staking/ClaimAllMobiModal.tsx +++ b/src/pages/Staking/ClaimAllMobiModal.tsx @@ -1,8 +1,7 @@ import { TransactionResponse } from '@ethersproject/providers' -import { JSBI, TokenAmount } from '@ubeswap/sdk' -import { useMobi } from 'hooks/Tokens' +import { IGauge } from 'constants/pools' import React, { useState } from 'react' -import { GaugeSummary } from 'state/staking/hooks' +import { UserGaugeInfo } from 'state/gauges/hooks' import styled from 'styled-components' import { ButtonError } from '../../components/Button' @@ -14,6 +13,7 @@ import { useWeb3Context } from '../../hooks' import { useMobiMinterContract } from '../../hooks/useContract' import { useTransactionAdder } from '../../state/transactions/hooks' import { CloseIcon, TYPE } from '../../theme' +import { useAllClaimableMobi } from './' const ContentWrapper = styled(AutoColumn)` width: 100%; @@ -23,15 +23,13 @@ const ContentWrapper = styled(AutoColumn)` interface StakingModalProps { isOpen: boolean onDismiss: () => void - summaries: GaugeSummary[] + userGauges: UserGaugeInfo[] + gauges: IGauge[] } -export const getAllUnclaimedMobi = (summaries: GaugeSummary[]): JSBI => - summaries.reduce((accum, { unclaimedMobi }) => JSBI.add(accum, unclaimedMobi.raw), JSBI.BigInt(0)) - -export default function ClaimAllMobiModal({ isOpen, onDismiss, summaries }: StakingModalProps) { +export default function ClaimAllMobiModal({ isOpen, onDismiss, userGauges, gauges }: StakingModalProps) { const { connected } = useWeb3Context() - const mobi = useMobi() + const claimableMobi = useAllClaimableMobi(userGauges) // monitor call to help UI loading state const addTransaction = useTransactionAdder() @@ -46,9 +44,8 @@ export default function ClaimAllMobiModal({ isOpen, onDismiss, summaries }: Stak const minter = useMobiMinterContract() - const pendingMobi = new TokenAmount(mobi, getAllUnclaimedMobi(summaries)) const gaugeAddresses = [...Array(8).keys()].map((i) => - i < summaries.length ? summaries[i].address : '0x0000000000000000000000000000000000000000' + i < gauges.length ? gauges[i].address : '0x0000000000000000000000000000000000000000' ) async function onClaimReward() { @@ -82,14 +79,12 @@ export default function ClaimAllMobiModal({ isOpen, onDismiss, summaries }: Stak Claim - {pendingMobi && ( - - - {pendingMobi.toSignificant(6)} MOBI - - {`Across ${summaries.length} farms`} - - )} + + + {claimableMobi.toSignificant(6)} MOBI + + {`Across ${gauges.length} farms`} + {error ?? 'Claim'} @@ -98,7 +93,7 @@ export default function ClaimAllMobiModal({ isOpen, onDismiss, summaries }: Stak {attempting && !hash && ( - Claiming {pendingMobi.toSignificant(6)} MOBI + Claiming {claimableMobi.toSignificant(6)} MOBI )} diff --git a/src/pages/Staking/Positions.tsx b/src/pages/Staking/Positions.tsx index 0b34597f0bb..bd3e5ca2ae8 100644 --- a/src/pages/Staking/Positions.tsx +++ b/src/pages/Staking/Positions.tsx @@ -1,24 +1,26 @@ import { JSBI, TokenAmount } from '@ubeswap/sdk' -import { ButtonOutlined, ButtonPrimary } from 'components/Button' +import { ButtonPrimary } from 'components/Button' import { AutoColumn } from 'components/Column' import { CardNoise } from 'components/earn/styled' -import Loader from 'components/Loader' -import { AutoRow, RowBetween, RowFixed } from 'components/Row' +import { RowBetween, RowFixed } from 'components/Row' +import { DisplayPool, IGauge, StablePools } from 'constants/pools' import { ChainLogo } from 'constants/StablePools' +import { CUSD } from 'constants/tokens' import { usePoolColor } from 'hooks/useColor' import React, { useState } from 'react' import { isMobile } from 'react-device-detect' import { ChevronDown, ChevronUp } from 'react-feather' -import { usePriceOfLp } from 'state/stablePools/hooks' -import { GaugeSummary, MobiStakingInfo } from 'state/staking/hooks' +import { GaugeInfo, UserGaugeInfo } from 'state/gauges/hooks' +import { StakingInfo, UserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { TYPE } from 'theme' +import invariant from 'tiny-invariant' import { calcBoost } from 'utils/calcExpectedVeMobi' import Logo from '../../components/Logo' -import { useStablePoolInfo } from '../../state/stablePools/hooks' +import { CHAIN } from '../../constants' +import { useAllClaimableMobi } from '.' import ClaimAllMobiModal from './ClaimAllMobiModal' -import GaugeVoteModal from './GaugeVoteModal' const Container = styled.div` width: 100%; @@ -32,11 +34,7 @@ const Container = styled.div` width: 100% `} ` -const SmallButton = styled(ButtonOutlined)` - padding: 0.5rem; - width: 8rem; - border-color: ${({ theme }) => theme.primary1}; -` + const Wrapper = styled(AutoColumn)<{ showBackground: boolean; bgColor: any }>` width: 100%; overflow: hidden; @@ -63,30 +61,36 @@ const StyledLogo = styled(Logo)<{ size: string }>` box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.075); background-color: ${({ theme }) => theme.white}; ` -const Divider = styled.div` - width: 100%; - height: 1px; - margin: 0; - background: ${({ theme }) => theme.bg4}; -` +function parse(include: boolean[], toParse: T[]): T[] { + invariant(include.length === toParse.length, 'length mismatch') + return toParse.filter((_, i) => include[i]) +} type PositionsProps = { - stakingInfo: MobiStakingInfo - unclaimedMobi: TokenAmount + stakingInfo: StakingInfo + userStakingInfo: UserStakingInfo + gauges: (GaugeInfo | null)[] + userGauges: (UserGaugeInfo | null)[] } -export default function Positions({ stakingInfo, unclaimedMobi }: PositionsProps) { - const { positions = [] } = stakingInfo - const loading = positions.length === 0 - const greaterThanZero = positions.filter( - ({ baseBalance, unclaimedMobi }) => baseBalance.greaterThan('0') || unclaimedMobi.greaterThan('0') + +export default function Positions({ stakingInfo, userStakingInfo, gauges, userGauges }: PositionsProps) { + const claimableMobi = useAllClaimableMobi(userGauges) + const openPosition = userGauges.map( + (ug) => ug !== null && (JSBI.greaterThan(ug.balance, JSBI.BigInt('0')) || ug.claimableMobi.greaterThan('0')) ) + const [openModal, setOpenModal] = useState(false) return ( setOpenModal(false)} - summaries={greaterThanZero.filter(({ unclaimedMobi }) => unclaimedMobi.greaterThan('0'))} + userGauges={ + parse(openPosition, userGauges).filter( + (ug) => ug !== null && ug.claimableMobi.greaterThan('0') + ) as UserGaugeInfo[] + } + gauges={parse(openPosition, StablePools[CHAIN]).map((d) => d.gauge as IGauge)} /> Your Positions @@ -96,24 +100,22 @@ export default function Positions({ stakingInfo, unclaimedMobi }: PositionsProps fontWeight={800} fontSize={[18, 24]} > - {unclaimedMobi.toSignificant(4)} Unclaimed MOBI + {claimableMobi.toSignificant(4)} Unclaimed MOBI - {loading ? ( - - - - ) : ( - greaterThanZero.map((position) => ( + {openPosition.map((p, i) => + p ? ( - )) + ) : null )} - {JSBI.greaterThan(unclaimedMobi.raw, JSBI.BigInt(0)) && ( + {claimableMobi.greaterThan('0') && ( setOpenModal(true)} style={{ fontWeight: 700, fontSize: 18, marginBottom: '1rem' }} @@ -126,29 +128,35 @@ export default function Positions({ stakingInfo, unclaimedMobi }: PositionsProps } function PositionCard({ - position, - votingPower, - totalVotingPower, + stakingInfo, + userStakingInfo, + gaugeInfo, + userGaugeInfo, + displayPool, }: { - position: GaugeSummary - votingPower: JSBI - totalVotingPower: JSBI + stakingInfo: StakingInfo + userStakingInfo: UserStakingInfo + gaugeInfo: GaugeInfo + userGaugeInfo: UserGaugeInfo + displayPool: DisplayPool }) { - const lpAsUsd = usePriceOfLp(position.poolAddress, position.baseBalance) - const [voteModalOpen, setVoteModalOpen] = useState(false) - const boost = calcBoost(position, votingPower, totalVotingPower) + const lpAsUsd = new TokenAmount(CUSD[CHAIN], '1') + const boost = calcBoost( + userGaugeInfo.balance, + gaugeInfo.totalSupply, + userStakingInfo.votingPower.raw, + stakingInfo.totalVotingPower.raw + ) - const stablePools = useStablePoolInfo() - const poolInfo = stablePools.filter((x) => x.name === position.pool)[0] - const poolColor = usePoolColor(poolInfo) + const poolColor = usePoolColor(displayPool) const [expand, setExpand] = useState(false) const mobileView = (
- - {position.pool} + + {displayPool.name} {expand ? : } @@ -169,28 +177,10 @@ function PositionCard({
)}
- // - // - // - // {position.pool} - // {`$${lpAsUsd?.toSignificant(4)}`} - // - // - // {`${boost.greaterThan(JSBI.BigInt(0)) ? boost.toFixed(2) : '1'}x`} - // - // ) return ( <> - setVoteModalOpen(false)} /> - setExpand(!expand)}> {isMobile ? ( @@ -198,8 +188,8 @@ function PositionCard({ ) : ( - - {position.pool} + + {displayPool.name} {` - $${lpAsUsd?.toSignificant(4)}`} {/* */} - {/* */} + ) : view === View.Vote ? ( From 30aa65f8d26dd082862d0684d9661fbd8b9c4803 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 14:49:53 -0500 Subject: [PATCH 34/72] calc boosts --- .../PoolSearchModal/CurrencySearch.tsx | 12 +- src/pages/Staking/CalcBoost.tsx | 122 +++++++++--------- src/pages/Staking/Lock/IncreaseLockAmount.tsx | 32 +++-- src/pages/Staking/index.tsx | 8 +- src/state/gauges/hooks.ts | 9 +- src/state/staking/hooks.ts | 61 +++++---- src/theme/index.tsx | 1 - 7 files changed, 126 insertions(+), 119 deletions(-) diff --git a/src/components/PoolSearchModal/CurrencySearch.tsx b/src/components/PoolSearchModal/CurrencySearch.tsx index 9024df25d59..4cbd63c0974 100644 --- a/src/components/PoolSearchModal/CurrencySearch.tsx +++ b/src/components/PoolSearchModal/CurrencySearch.tsx @@ -1,5 +1,5 @@ import { Token } from '@ubeswap/sdk' -import { STATIC_POOL_INFO } from 'constants/StablePools' +import { StablePools } from 'constants/pools' import { useOnClickOutside } from 'hooks/useOnClickOutside' import useTheme from 'hooks/useTheme' import useToggle from 'hooks/useToggle' @@ -36,13 +36,13 @@ export function CurrencySearch({ selectedCurrency, onCurrencySelect, onDismiss } // refs for fixed size lists const fixedList = useRef() - const tokensToSelect = STATIC_POOL_INFO[CHAIN].map( - ({ lpToken, name }) => + const tokensToSelect = StablePools[CHAIN].map( + (s) => new WrappedTokenInfo( { - ...lpToken, - symbol: name, - name, + ...s.pool.lpToken, + symbol: s.name, + name: s.name, }, [] ) diff --git a/src/pages/Staking/CalcBoost.tsx b/src/pages/Staking/CalcBoost.tsx index 4c08c5bb5a2..ccba435cde1 100644 --- a/src/pages/Staking/CalcBoost.tsx +++ b/src/pages/Staking/CalcBoost.tsx @@ -1,26 +1,26 @@ -import { Fraction, JSBI, TokenAmount } from '@ubeswap/sdk' +import { JSBI, TokenAmount } from '@ubeswap/sdk' import { AutoColumn } from 'components/Column' import QuestionHelper from 'components/QuestionHelper' import { RowBetween } from 'components/Row' -import { useMobi, useVeMobi } from 'hooks/Tokens' +import { DisplayPool, StablePools } from 'constants/pools' +import { useVeMobi } from 'hooks/Tokens' import { useColor } from 'hooks/useColor' +import useTheme from 'hooks/useTheme' import { darken } from 'polished' import React, { useCallback, useState } from 'react' +import { GaugeInfo, UserGaugeInfo } from 'state/gauges/hooks' import { tryParseAmount } from 'state/mento/hooks' -import { MobiStakingInfo, useMobiStakingInfo } from 'state/staking/hooks' -import { useTokenBalance } from 'state/wallet/hooks' +import { StakingInfo, UserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' -import { theme, TYPE } from 'theme' -import { calcEstimatedBoost, calcVotesForMaxBoost } from 'utils/calcExpectedVeMobi' +import { TYPE } from 'theme' import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg' import DoubleCurrencyLogo from '../../components/DoubleLogo' import CurrencySearchModal from '../../components/PoolSearchModal/CurrencySearchModal' +import { CHAIN } from '../../constants' import { useWeb3Context } from '../../hooks' -import { StablePoolInfo, useStablePoolInfo } from '../../state/stablePools/hooks' import { useIsDarkMode } from '../../state/user/hooks' -import ClaimAllMobiModal from './ClaimAllMobiModal' -import { CurrencyRow } from './IncreaseLockAmount' +import { CurrencyRow } from './Lock/IncreaseLockAmount' const Container = styled.div` width: 49%; @@ -37,7 +37,7 @@ const Container = styled.div` `} ` -const Wrapper = styled(AutoColumn)<{ showBackground: boolean; bgColor: any; activated: boolean }>` +const Wrapper = styled(AutoColumn)` border-radius: 12px; width: 100%; overflow: hidden; @@ -46,16 +46,10 @@ const Wrapper = styled(AutoColumn)<{ showBackground: boolean; bgColor: any; acti padding: 0.5rem; gap: 0.5rem; cursor: pointer; - opacity: ${({ activated }) => (activated ? 1 : 0.9)}; + opacity: 0.9; overflow: hidden; position: relative; - background: ${({ bgColor, theme }) => - `radial-gradient(91.85% 100% at 1.84% 0%, ${bgColor} 0%, ${theme.black} 100%) `}; - color: ${({ theme, showBackground }) => (showBackground ? theme.white : theme.text1)} !important; - ${({ showBackground }) => - showBackground && - ` box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), - 0px 24px 32px rgba(0, 0, 0, 0.01);`} + color: theme.white !important; ${({ theme }) => theme.mediaWidth.upToSmall` `} &:hover { @@ -129,24 +123,31 @@ const StyledDropDown = styled(DropDown)<{ selected: boolean }>` ` type PositionsProps = { - stakingInfo: MobiStakingInfo + stakingInfo: StakingInfo + userStakingInfo: UserStakingInfo + gauges: (GaugeInfo | null)[] + userGauges: (UserGaugeInfo | null)[] } -export default function CalcBoost({ stakingInfo }: PositionsProps) { - const stablePools = useStablePoolInfo() - const { address, connected } = useWeb3Context() - const { positions = [] } = stakingInfo - const greaterThanZero = positions.filter(({ baseBalance }) => baseBalance.greaterThan('0')) - const [openModal, setOpenModal] = useState(false) - const mobi = useMobi() + +export default function CalcBoost({ stakingInfo, userStakingInfo, gauges, userGauges }: PositionsProps) { + const { connected } = useWeb3Context() + + const displays = StablePools[CHAIN] + const openPositions = userGauges.filter((ug) => ug !== null && JSBI.greaterThan(ug.balance, JSBI.BigInt('0'))) + const vemobi = useVeMobi() + const theme = useTheme() + const color = useColor() + const isDarkMode = useIsDarkMode() + const [lpInput, setLPInput] = useState('') const [veInput, setVEInput] = useState('') - const [pool, setPool] = useState(stablePools[0] ?? undefined) - const lpBalance = pool ? pool.amountDeposited : new TokenAmount(mobi, JSBI.BigInt(0)) - const veBalance = useTokenBalance(connected ? address : undefined, vemobi) - const isDarkMode = useIsDarkMode() - const color = useColor() - const staking = useMobiStakingInfo() + const [pool, setPool] = useState(undefined) + const index = pool ? displays.indexOf(pool) : null + const gauge = index ? userGauges[index] : null + + const lpBalance = pool && gauge ? new TokenAmount(pool.pool.lpToken, gauge.balance) : null + const [modalOpen, setModalOpen] = useState(false) const handleDismissSearch = useCallback(() => { setModalOpen(false) @@ -154,31 +155,25 @@ export default function CalcBoost({ stakingInfo }: PositionsProps) { const onCurrencySelect = useCallback( (currency) => { - setPool(stablePools.filter((x) => x.lpToken?.address === currency.address)[0]) + setPool(displays.filter((x) => x.pool.lpToken?.address === currency.address)[0]) }, - [stablePools] + [displays] ) - const stake = - staking.positions && pool - ? staking.positions.filter((s) => s.address.toLowerCase() === pool.gaugeAddress?.toLowerCase())[0] - : undefined + const veParse = tryParseAmount(veInput, vemobi) + const lpParse = pool ? tryParseAmount(lpInput, pool.pool.lpToken) : undefined - if (!vemobi) return null + // TODO: fix this math + // const boost = + // !veParse || !lpParse + // ? new Fraction(JSBI.BigInt(0)) + // : calcEstimatedBoost(stake, veParse.raw, staking.totalVotingPower.raw, lpParse.raw) - const veParse = tryParseAmount(veInput, vemobi) - const lpParse = pool ? tryParseAmount(lpInput, pool.lpToken) : undefined - const boost = - !veParse || !lpParse - ? new Fraction(JSBI.BigInt(0)) - : calcEstimatedBoost(stake, veParse.raw, staking.totalVotingPower.raw, lpParse.raw) - - const votes = !lpParse - ? new TokenAmount(vemobi, JSBI.BigInt(0)) - : calcVotesForMaxBoost(stake, staking.totalVotingPower.raw, lpParse.raw, vemobi) + // const votes = !lpParse + // ? new TokenAmount(vemobi, JSBI.BigInt(0)) + // : calcVotesForMaxBoost(stake, staking.totalVotingPower.raw, lpParse.raw, vemobi) return ( - setOpenModal(false)} summaries={greaterThanZero} /> Calculate Boosts Calculate how much MOBI you need to stake} /> @@ -198,7 +193,12 @@ export default function CalcBoost({ stakingInfo }: PositionsProps) { > {pool ? ( - + ) : null} {pool ? ( @@ -214,26 +214,30 @@ export default function CalcBoost({ stakingInfo }: PositionsProps) { isOpen={modalOpen} onDismiss={handleDismissSearch} onCurrencySelect={onCurrencySelect} - selectedCurrency={pool ? pool.lpToken : undefined} + selectedCurrency={pool?.pool.lpToken} /> - {!pool ? ( - Select a Pool - ) : ( + {pool && (
{/* Enter amount */} - + {/* Enter amount */} - + Boost - {boost.toFixed(2)}x + 4.9x veMOBI to get max boost - {votes.toFixed(2)} + 67,780.98
diff --git a/src/pages/Staking/Lock/IncreaseLockAmount.tsx b/src/pages/Staking/Lock/IncreaseLockAmount.tsx index 8307c5abeec..4a37b061a58 100644 --- a/src/pages/Staking/Lock/IncreaseLockAmount.tsx +++ b/src/pages/Staking/Lock/IncreaseLockAmount.tsx @@ -5,11 +5,11 @@ import { JSBI, Token, TokenAmount } from '@ubeswap/sdk' import CurrencyLogo from 'components/CurrencyLogo' import Loader from 'components/Loader' import { AutoRow, RowBetween } from 'components/Row' +import { DisplayPool } from 'constants/pools' import { useMobi } from 'hooks/Tokens' import { useDoTransaction } from 'hooks/useDoTransaction' import React, { useState } from 'react' import { Text } from 'rebass' -import { StablePoolInfo } from 'state/stablePools/hooks' import { useTokenBalance } from 'state/wallet/hooks' import styled from 'styled-components' import invariant from 'tiny-invariant' @@ -137,10 +137,10 @@ export default function IncreaseLockAmount({ setHash, setAttempting }: IncreaseL type CurrencyRowProps = { val: string + balance: TokenAmount | undefined token: Token setTokenAmount: (tokenAmount: string) => void - balance?: TokenAmount - pool?: StablePoolInfo + pool?: DisplayPool } const InputRow = styled.div<{ selected: boolean }>` @@ -171,24 +171,22 @@ const BalanceText = styled(TYPE.subHeader)` ` export const CurrencyRow = ({ val, token, setTokenAmount, balance, pool }: CurrencyRowProps) => { - const currency = token - const tokenBalance = balance - const mainRow = (
{pool ? ( - + ) : ( - + )} - - {(currency && currency.symbol && currency.symbol.length > 20 - ? currency.symbol.slice(0, 4) + - '...' + - currency.symbol.slice(currency.symbol.length - 5, currency.symbol.length) - : currency?.symbol) || ''} + + {token.symbol ?? ''}
@@ -203,12 +201,12 @@ export const CurrencyRow = ({ val, token, setTokenAmount, balance, pool }: Curre
) - const decimalPlacesForBalance = tokenBalance?.greaterThan('1') ? 2 : tokenBalance?.greaterThan('0') ? 10 : 2 + const decimalPlacesForBalance = balance?.greaterThan('1') ? 2 : balance?.greaterThan('0') ? 10 : 2 const balanceRow = (
- setTokenAmount(tokenBalance?.toExact() || '0')}> - Balance: {tokenBalance?.toFixed(decimalPlacesForBalance)} + setTokenAmount(balance?.toExact() || '0')}> + Balance: {balance?.toFixed(decimalPlacesForBalance)}
) diff --git a/src/pages/Staking/index.tsx b/src/pages/Staking/index.tsx index 2c9ef967efa..fe0f20eef8d 100644 --- a/src/pages/Staking/index.tsx +++ b/src/pages/Staking/index.tsx @@ -7,6 +7,7 @@ import { useStakingInfo, useUserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { Row } from '../../components/Row' +import CalcBoost from './CalcBoost' import GaugeWeights from './GaugeWeights' import Stake from './Lock/Stake' import Positions from './Positions' @@ -113,7 +114,12 @@ export default function Staking() { {view === View.Lock ? ( - {/* */} + !StablePools[CHAIN][i].gauge && (StablePools[CHAIN][i].gauge?.address === gauge.address ?? false)) .map((g) => @@ -84,11 +86,12 @@ export function useGaugeInfo(gauge: IGauge): GaugeInfo { return gaugeInfo[0] } -export function useUserGaugeInfo(gauge: IGauge): UserGaugeInfo { +export function useUserGaugeInfo(gauge: IGauge | undefined): UserGaugeInfo | undefined { const gauges = useUserGauges() - const mobi = useMobi() + if (!gauge) return undefined + const gaugeInfo = gauges .filter( (ug, i) => !StablePools[CHAIN][i].gauge && (StablePools[CHAIN][i].gauge?.address === gauge.address ?? false) diff --git a/src/state/staking/hooks.ts b/src/state/staking/hooks.ts index 7ff7d938b37..7cc97f5c126 100644 --- a/src/state/staking/hooks.ts +++ b/src/state/staking/hooks.ts @@ -3,9 +3,6 @@ import { ExternalRewardsToken } from 'constants/staking' import { useMobi, useVeMobi } from 'hooks/Tokens' import { useSelector } from 'react-redux' import { AppState } from 'state' -import { getPoolInfo } from 'state/stablePools/hooks' -import { StableSwapPool } from 'state/stablePools/reducer' -import { getDepositValues } from 'utils/stableSwaps' import { CHAIN } from '../../constants' import { IStakingState, IUserStakingState } from './reducer' @@ -139,32 +136,32 @@ export type GaugeSummary = { // TODO: fix this hook -export function usePriceOfDeposits() { - const pools = useSelector((state) => { - const allPools = state.stablePools.pools - return Object.values(allPools) - .map(({ pool }) => pool) - .filter((pool) => pool.userStaked && JSBI.greaterThan(pool.userStaked, JSBI.BigInt('0'))) - }) - const prices = useSelector((state: AppState) => ({ - ethPrice: state.application.ethPrice, - btcPrice: state.application.btcPrice, - })) - const dummyToken = useMobi() - return !pools[0] || pools[0].loadingGauge - ? undefined - : new TokenAmount( - dummyToken, - pools.reduce((accum, pool) => { - const address = pool.address - const { valueOfStaked } = getDepositValues(getPoolInfo(pool)) - const price = - address === '0x19260b9b573569dDB105780176547875fE9fedA3' - ? JSBI.BigInt(prices.btcPrice) - : address === '0xE0F2cc70E52f05eDb383313393d88Df2937DA55a' - ? JSBI.BigInt(prices.ethPrice) - : JSBI.BigInt('1') - return JSBI.add(accum, JSBI.multiply(valueOfStaked.raw, price)) - }, JSBI.BigInt('0')) - ) -} +// export function usePriceOfDeposits() { +// const pools = useSelector((state) => { +// const allPools = state.stablePools.pools +// return Object.values(allPools) +// .map(({ pool }) => pool) +// .filter((pool) => pool.userStaked && JSBI.greaterThan(pool.userStaked, JSBI.BigInt('0'))) +// }) +// const prices = useSelector((state: AppState) => ({ +// ethPrice: state.application.ethPrice, +// btcPrice: state.application.btcPrice, +// })) +// const dummyToken = useMobi() +// return !pools[0] || pools[0].loadingGauge +// ? undefined +// : new TokenAmount( +// dummyToken, +// pools.reduce((accum, pool) => { +// const address = pool.address +// const { valueOfStaked } = getDepositValues(getPoolInfo(pool)) +// const price = +// address === '0x19260b9b573569dDB105780176547875fE9fedA3' +// ? JSBI.BigInt(prices.btcPrice) +// : address === '0xE0F2cc70E52f05eDb383313393d88Df2937DA55a' +// ? JSBI.BigInt(prices.ethPrice) +// : JSBI.BigInt('1') +// return JSBI.add(accum, JSBI.multiply(valueOfStaked.raw, price)) +// }, JSBI.BigInt('0')) +// ) +// } diff --git a/src/theme/index.tsx b/src/theme/index.tsx index 37528444a7d..57996f7f694 100644 --- a/src/theme/index.tsx +++ b/src/theme/index.tsx @@ -99,7 +99,6 @@ export function colors(darkMode: boolean): Colors { polygon: '#BF97FF', ethereum: '#2E3338', solana: '#9DB6FF', - white: '#FFFFFF', // dont wanna forget these blue yet // blue4: darkMode ? '#153d6f70' : '#C4D9F8', From 16944b28c2d9c87cc30bb280e309520815e22522 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 16:42:41 -0500 Subject: [PATCH 35/72] price refactor --- src/constants/pools.ts | 28 ++++++++++++++- src/constants/tokens.ts | 48 ++++++++++++++++++------- src/state/application/actions.ts | 5 ++- src/state/application/hooks.ts | 28 +++++---------- src/state/application/reducer.ts | 15 +++----- src/state/application/updater.ts | 61 ++++++++++++++++++++------------ 6 files changed, 118 insertions(+), 67 deletions(-) diff --git a/src/constants/pools.ts b/src/constants/pools.ts index 5b3946046d5..dbd42bb6e00 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -2,7 +2,7 @@ import { ChainId, Percent, Token, TokenAmount } from '@ubeswap/sdk' import JSBI from 'jsbi' import { CHAIN } from './' -import { CELO, CUSD, UST } from './tokens' +import { CELO, CETH, CUSD, UST, WETH } from './tokens' export type Fees = { trade: Percent @@ -60,6 +60,7 @@ export interface Peg { symbol: string position: 'before' | 'after' decimals: number + priceQuery: string | null } const Bitcoin: Peg = { @@ -67,6 +68,7 @@ const Bitcoin: Peg = { symbol: '₿', position: 'after', decimals: 2, + priceQuery: 'bitcoin', } const Ether: Peg = { @@ -74,6 +76,7 @@ const Ether: Peg = { symbol: 'Ξ', position: 'after', decimals: 2, + priceQuery: 'ethereum', } const Dollar: Peg = { @@ -81,6 +84,7 @@ const Dollar: Peg = { symbol: '$', position: 'before', decimals: 0, + priceQuery: null, } const Celo: Peg = { @@ -88,6 +92,7 @@ const Celo: Peg = { symbol: 'Celo', position: 'after', decimals: 0, + priceQuery: 'celo', } const Euro: Peg = { @@ -95,6 +100,7 @@ const Euro: Peg = { symbol: '€', position: 'before', decimals: 0, + priceQuery: 'celo-euro', } export enum Chain { @@ -157,6 +163,26 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { additionalRewards: [new TokenAmount(CELO[CHAIN], '12000000000000000')], }, }, + { + name: 'WETH (Optics V2)', + chain: Chain.Ethereum, + peg: Ether, + pool: { + address: '0x74ef28D635c6C5800DD3Cd62d4c4f8752DaACB09', + lpToken: new Token( + ChainId.MAINNET, + '0x4fF08e2a4E7114af4B575AeF9250144f95790982', + 18, + 'MobLP', + 'Mobius cETH/wETH LP' + ), + tokens: [CETH[ChainId.MAINNET], WETH[ChainId.MAINNET]], + }, + gauge: { + address: '0x487c30CB18AA9Ced435911E2B414e0e85D7E52bB', + additionalRewards: [], + }, + }, ], [ChainId.ALFAJORES]: [], [ChainId.BAKLAVA]: [], diff --git a/src/constants/tokens.ts b/src/constants/tokens.ts index 0e46534f0e0..bda4db4d7e6 100644 --- a/src/constants/tokens.ts +++ b/src/constants/tokens.ts @@ -17,18 +17,6 @@ const makeTokens = ( }) } -export const UST = makeTokens( - { - [ChainId.MAINNET]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', - [ChainId.ALFAJORES]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', - [ChainId.BAKLAVA]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', - }, - 18, - 'UST', - 'TerraUSD', - 'https://raw.githubusercontent.com/kyscott18/default-token-list/master/assets/asset_UST.png' -) - export const MOBI = makeTokens( { [ChainId.MAINNET]: '0x73a210637f6F6B7005512677Ba6B3C96bb4AA44B', @@ -101,6 +89,42 @@ export const VEMOBI = makeTokens( 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_MOBI.png' ) +export const UST = makeTokens( + { + [ChainId.MAINNET]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', + [ChainId.ALFAJORES]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', + [ChainId.BAKLAVA]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', + }, + 18, + 'UST', + 'Terra USD', + 'https://raw.githubusercontent.com/kyscott18/default-token-list/master/assets/asset_UST.png' +) + +export const CETH = makeTokens( + { + [ChainId.MAINNET]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', + [ChainId.ALFAJORES]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', + [ChainId.BAKLAVA]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', + }, + 18, + 'cETH', + 'Wrapped Ethereum', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cETH.svg' +) + +export const WETH = makeTokens( + { + [ChainId.MAINNET]: '0x122013fd7dF1C6F636a5bb8f03108E876548b455', + [ChainId.ALFAJORES]: '0x122013fd7dF1C6F636a5bb8f03108E876548b455', + [ChainId.BAKLAVA]: '0x122013fd7dF1C6F636a5bb8f03108E876548b455', + }, + 18, + 'wETH', + 'Wrapped Ether (Optics Bridge)', + 'https://etherscan.io/token/images/weth_28.png' +) + export const ExternalRewards: { [K in ChainId]: WrappedTokenInfo[] } = { [ChainId.MAINNET]: [ new WrappedTokenInfo( diff --git a/src/state/application/actions.ts b/src/state/application/actions.ts index 82ef3a8a434..8afb0e74804 100644 --- a/src/state/application/actions.ts +++ b/src/state/application/actions.ts @@ -1,5 +1,4 @@ import { createAction } from '@reduxjs/toolkit' -import { Fraction } from '@ubeswap/sdk' export type PopupContent = { txn: { @@ -25,6 +24,6 @@ export const setOpenModal = createAction('application/s export const addPopup = createAction<{ key?: string; removeAfterMs?: number | null; content: PopupContent }>('application/addPopup') export const removePopup = createAction<{ key: string }>('application/removePopup') -export const btcEthPrice = createAction<{ ethPrice: string; btcPrice: string }>('application/btcEthPrice') -export const addPrice = createAction<{ token: string; price: Fraction }>('application/addPrice') + +export const addPrice = createAction<{ token: string; price: string }>('application/addPrice') export const addPrices = createAction<{ prices: { [address: string]: string } }>('application/addPrices') diff --git a/src/state/application/hooks.ts b/src/state/application/hooks.ts index a20915e712e..5f642173fbe 100644 --- a/src/state/application/hooks.ts +++ b/src/state/application/hooks.ts @@ -1,6 +1,6 @@ +import { ApolloClient, NormalizedCacheObject } from '@apollo/client' import { Fraction } from '@ubeswap/sdk' import { useWeb3Context } from 'hooks' -import JSBI from 'jsbi' import { useCallback, useMemo } from 'react' import { useDispatch, useSelector } from 'react-redux' @@ -63,6 +63,10 @@ export function useToggleVoteModal(): () => void { return useToggleModal(ApplicationModal.VOTE) } +export function useUbeswapClient(): ApolloClient { + return useSelector>((state) => state.application.ubeswapClient) +} + // returns a function that allows adding a popup export function useAddPopup(): (content: PopupContent, key?: string) => void { const dispatch = useDispatch() @@ -92,25 +96,11 @@ export function useActivePopups(): AppState['application']['popupList'] { return useMemo(() => list.filter((item) => item.show), [list]) } -export function useEthBtcPrice(address: string): JSBI { - const prices = useSelector((state: AppState) => ({ - ethPrice: state.application.ethPrice, - btcPrice: state.application.btcPrice, - })) - return address === '0x19260b9b573569dDB105780176547875fE9fedA3' || - address === '0xBe50a3013A1c94768A1ABb78c3cB79AB28fc1aCE' - ? JSBI.BigInt(prices.btcPrice) - : address === '0xE0F2cc70E52f05eDb383313393d88Df2937DA55a' || - address === '0xE919F65739c26a42616b7b8eedC6b5524d1e3aC4' - ? JSBI.BigInt(prices.ethPrice) - : JSBI.BigInt('1') -} - export function useTokenPrice(address: string | undefined): Fraction | undefined { - const priceString = useSelector((state: AppState) => { - return state.application.tokenPrices[address?.toLowerCase()] - }) - return priceStringToFraction(priceString) + const prices = useTokenPrices() + if (!address) return undefined + + return priceStringToFraction(prices[address]) } export function priceStringToFraction(priceString: string | undefined): Fraction | undefined { diff --git a/src/state/application/reducer.ts b/src/state/application/reducer.ts index 5f2c0eb0845..4073057d313 100644 --- a/src/state/application/reducer.ts +++ b/src/state/application/reducer.ts @@ -6,7 +6,6 @@ import { addPrice, addPrices, ApplicationModal, - btcEthPrice, PopupContent, removePopup, setOpenModal, @@ -14,6 +13,7 @@ import { } from './actions' type PopupList = Array<{ key: string; show: boolean; content: PopupContent; removeAfterMs: number | null }> + export type TokenPrices = { [address: string]: string } @@ -22,8 +22,6 @@ export interface ApplicationState { readonly blockNumber: { readonly [chainId: number]: number } readonly popupList: PopupList readonly openModal: ApplicationModal | null - readonly btcPrice: string - readonly ethPrice: string readonly tokenPrices: TokenPrices readonly ubeswapClient: ApolloClient } @@ -32,8 +30,6 @@ const initialState: ApplicationState = { blockNumber: {}, popupList: [], openModal: null, - btcPrice: '41000', - ethPrice: '2700', tokenPrices: {}, ubeswapClient: new ApolloClient({ uri: 'https://api.thegraph.com/subgraphs/name/ubeswap/ubeswap', @@ -54,10 +50,6 @@ export default createReducer(initialState, (builder) => .addCase(setOpenModal, (state, action) => { state.openModal = action.payload }) - .addCase(btcEthPrice, (state, { payload: { ethPrice, btcPrice } }) => { - state.ethPrice = ethPrice - state.btcPrice = btcPrice - }) .addCase(addPopup, (state, { payload: { content, key, removeAfterMs = 15000 } }) => { state.popupList = (key ? state.popupList.filter((popup) => popup.key !== key) : state.popupList).concat([ { @@ -82,6 +74,9 @@ export default createReducer(initialState, (builder) => } }) .addCase(addPrices, (state, { payload: { prices } }) => { - state.tokenPrices = prices + state.tokenPrices = { + ...state.tokenPrices, + ...prices, + } }) ) diff --git a/src/state/application/updater.ts b/src/state/application/updater.ts index d5ebb4365f1..509404c01b1 100644 --- a/src/state/application/updater.ts +++ b/src/state/application/updater.ts @@ -1,31 +1,48 @@ -import { ApolloClient, gql, InMemoryCache, useQuery } from '@apollo/client' +import { gql, useQuery } from '@apollo/client' import axios from 'axios' +import { StablePools } from 'constants/pools' import { useWeb3Context } from 'hooks' -import { useCallback, useEffect, useState } from 'react' +import { useMobi } from 'hooks/Tokens' +import { Dispatch, useCallback, useEffect, useState } from 'react' import { useDispatch } from 'react-redux' import { CHAIN } from '../../constants' import useDebounce from '../../hooks/useDebounce' import useIsWindowVisible from '../../hooks/useIsWindowVisible' -import { addPrices, btcEthPrice, updateBlockNumber } from './actions' +import { addPrice, addPrices, updateBlockNumber } from './actions' +import { useUbeswapClient } from './hooks' +import { TokenPrices } from './reducer' -const fetchEthBtcPrices = async (dispatch: any) => { +const dedupe = (strings: string[]): string[] => { + const seen = new Set() + return strings.filter((str) => { + if (seen.has(str)) { + return false + } else { + seen.add(str) + return true + } + }) +} + +const fetchPegPrices = async (dispatch: Dispatch) => { + // https://api.coingecko.com/api/v3/simple/price?ids=bitcoin%2Ccelo&vs_currencies=usd + const pegQueries = dedupe(StablePools[CHAIN].map(({ peg }) => peg.priceQuery).filter((s) => s !== null) as string[]) + const ids = pegQueries.reduce((acc, cur) => acc.concat(cur).concat('%2'), '') const resp = await axios.get( - 'https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses=0x2260fac5e5542a773aa44fbcfedf7c193bc2c599%2C0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&vs_currencies=usd' + `https://api.coingecko.com/api/v3/simple/price?ids=${ids.slice(0, -2)}&vs_currencies=usd` ) - const btcPrice: string = resp.data['0x2260fac5e5542a773aa44fbcfedf7c193bc2c599']?.['usd'] - const ethPrice: string = resp.data['0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2']?.['usd'] - dispatch(btcEthPrice({ btcPrice: parseInt(btcPrice).toFixed(0), ethPrice: parseInt(ethPrice).toFixed(0) })) + + const prices: TokenPrices = pegQueries.reduce((acc, cur) => { + console.log(resp.data[cur]?.['usd']) + return { ...acc, [cur]: resp.data[cur]?.['usd'] } + }, {}) + dispatch(addPrices({ prices: prices })) } -// 0x17700282592d6917f6a73d0bf8accf4d578c131e -const ubeswapClient = new ApolloClient({ - uri: 'https://api.thegraph.com/subgraphs/name/ubeswap/ubeswap', - cache: new InMemoryCache(), -}) -const priceQuery = gql` +const mobiPriceQuery = gql` { - tokens(where: { derivedCUSD_gt: "0" }) { + token(id: "0x73a210637f6f6b7005512677ba6b3c96bb4aa44b") { id derivedCUSD } @@ -34,15 +51,16 @@ const priceQuery = gql` export function PriceData(): null { const dispatch = useDispatch() - const { data, loading, error } = useQuery(priceQuery, { client: ubeswapClient }) + const ubeswapClient = useUbeswapClient() + const mobi = useMobi() + const { data, loading, error } = useQuery(mobiPriceQuery, { client: ubeswapClient }) useEffect(() => { if (!loading && !error && data) { - const prices: { [address: string]: string } = data.tokens.reduce((accum, cur) => { - return { ...accum, [cur.id.toLowerCase()]: cur.derivedCUSD } - }, {}) - dispatch(addPrices({ prices })) + console.log('update prices') + fetchPegPrices(dispatch) + dispatch(addPrice({ token: mobi.address, price: data.token.derivedCUSD })) } - }, [data, loading, dispatch, error]) + }, [data, loading, dispatch, error, mobi.address]) return null } @@ -55,7 +73,6 @@ export default function Updater(): null { chainId: CHAIN, blockNumber: null, }) - fetchEthBtcPrices(dispatch) const blockNumberCallback = useCallback( (blockNumber: number) => { From 95ec8697b6cbddd4d5f09112f603656366d544d6 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 16:50:32 -0500 Subject: [PATCH 36/72] fixed token price reducer --- src/state/application/reducer.test.ts | 85 --------------------------- src/state/application/updater.ts | 2 +- src/state/stablePools/hooks.ts | 27 ++++----- 3 files changed, 14 insertions(+), 100 deletions(-) delete mode 100644 src/state/application/reducer.test.ts diff --git a/src/state/application/reducer.test.ts b/src/state/application/reducer.test.ts deleted file mode 100644 index ed494e7fd56..00000000000 --- a/src/state/application/reducer.test.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { ChainId } from '@ubeswap/sdk' -import { createStore, Store } from 'redux' - -import { addPopup, ApplicationModal, removePopup, setOpenModal, updateBlockNumber } from './actions' -import reducer, { ApplicationState } from './reducer' - -describe('application reducer', () => { - let store: Store - - beforeEach(() => { - store = createStore(reducer, { - popupList: [], - blockNumber: { - [ChainId.MAINNET]: 3, - }, - openModal: null, - }) - }) - - describe('addPopup', () => { - it('adds the popup to list with a generated id', () => { - store.dispatch(addPopup({ content: { txn: { hash: 'abc', summary: 'test', success: true } } })) - const list = store.getState().popupList - expect(list).toHaveLength(1) - expect(typeof list[0].key).toEqual('string') - expect(list[0].show).toEqual(true) - expect(list[0].content).toEqual({ txn: { hash: 'abc', summary: 'test', success: true } }) - expect(list[0].removeAfterMs).toEqual(15000) - }) - - it('replaces any existing popups with the same key', () => { - store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'abc', summary: 'test', success: true } } })) - store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'def', summary: 'test2', success: false } } })) - const list = store.getState().popupList - expect(list).toHaveLength(1) - expect(list[0].key).toEqual('abc') - expect(list[0].show).toEqual(true) - expect(list[0].content).toEqual({ txn: { hash: 'def', summary: 'test2', success: false } }) - expect(list[0].removeAfterMs).toEqual(15000) - }) - }) - - describe('setOpenModal', () => { - it('set wallet modal', () => { - store.dispatch(setOpenModal(ApplicationModal.WALLET)) - expect(store.getState().openModal).toEqual(ApplicationModal.WALLET) - store.dispatch(setOpenModal(ApplicationModal.WALLET)) - expect(store.getState().openModal).toEqual(ApplicationModal.WALLET) - store.dispatch(setOpenModal(ApplicationModal.CLAIM_POPUP)) - expect(store.getState().openModal).toEqual(ApplicationModal.CLAIM_POPUP) - store.dispatch(setOpenModal(null)) - expect(store.getState().openModal).toEqual(null) - }) - }) - - describe('updateBlockNumber', () => { - it('updates block number', () => { - store.dispatch(updateBlockNumber({ chainId: ChainId.MAINNET, blockNumber: 4 })) - expect(store.getState().blockNumber[ChainId.MAINNET]).toEqual(4) - }) - it('no op if late', () => { - store.dispatch(updateBlockNumber({ chainId: ChainId.MAINNET, blockNumber: 2 })) - expect(store.getState().blockNumber[ChainId.MAINNET]).toEqual(3) - }) - it('works with non-set chains', () => { - store.dispatch(updateBlockNumber({ chainId: ChainId.ALFAJORES, blockNumber: 2 })) - expect(store.getState().blockNumber).toEqual({ - [ChainId.MAINNET]: 3, - [ChainId.ALFAJORES]: 2, - }) - }) - }) - - describe('removePopup', () => { - beforeEach(() => { - store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'abc', summary: 'test', success: true } } })) - }) - it('hides the popup', () => { - expect(store.getState().popupList[0].show).toBe(true) - store.dispatch(removePopup({ key: 'abc' })) - expect(store.getState().popupList).toHaveLength(1) - expect(store.getState().popupList[0].show).toBe(false) - }) - }) -}) diff --git a/src/state/application/updater.ts b/src/state/application/updater.ts index 509404c01b1..512e6b1750f 100644 --- a/src/state/application/updater.ts +++ b/src/state/application/updater.ts @@ -58,7 +58,7 @@ export function PriceData(): null { if (!loading && !error && data) { console.log('update prices') fetchPegPrices(dispatch) - dispatch(addPrice({ token: mobi.address, price: data.token.derivedCUSD })) + dispatch(addPrice({ token: mobi.address.toLowerCase(), price: data.token.derivedCUSD })) } }, [data, loading, dispatch, error, mobi.address]) return null diff --git a/src/state/stablePools/hooks.ts b/src/state/stablePools/hooks.ts index d08fd4be868..7017889d917 100644 --- a/src/state/stablePools/hooks.ts +++ b/src/state/stablePools/hooks.ts @@ -6,7 +6,6 @@ import { addressToToken } from 'hooks/Tokens' import { useLiquidityGaugeContract, useStableSwapContract } from 'hooks/useContract' import { useEffect, useMemo, useState } from 'react' import { useSelector } from 'react-redux' -import { useEthBtcPrice } from 'state/application/hooks' import { useSingleContractMultipleData } from 'state/multicall/hooks' import { tryParseAmount } from 'state/swap/hooks' import invariant from 'tiny-invariant' @@ -189,19 +188,19 @@ export function useMathUtil(pool: StableSwapPool | string): StableSwapMath | und return math } -export function usePriceOfLp(address: string, amountOfLp: TokenAmount): TokenAmount | undefined { - const pool = useStablePoolInfoByName(address) - const price = useEthBtcPrice(pool?.poolAddress ?? '') - return pool && price && amountOfLp - ? new TokenAmount( - amountOfLp.token, - JSBI.divide( - JSBI.multiply(amountOfLp.raw, JSBI.multiply(pool?.virtualPrice, price)), - JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) - ) - ) - : undefined -} +// export function usePriceOfLp(address: string, amountOfLp: TokenAmount): TokenAmount | undefined { +// const pool = useStablePoolInfoByName(address) +// const price = useEthBtcPrice(pool?.poolAddress ?? '') +// return pool && price && amountOfLp +// ? new TokenAmount( +// amountOfLp.token, +// JSBI.divide( +// JSBI.multiply(amountOfLp.raw, JSBI.multiply(pool?.virtualPrice, price)), +// JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) +// ) +// ) +// : undefined +// } export function useExternalRewards({ address }: { address: string }): TokenAmount[] { const pool = useSelector((state) => state.stablePools.pools[address.toLowerCase()]?.pool) From b7ce977323ed5a22af05f661155335f3540eaf58 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 17:43:44 -0500 Subject: [PATCH 37/72] use mobi price hook --- src/pages/Pool/index.tsx | 10 ++--- src/state/application/hooks.ts | 11 ++++- src/utils/useCUSDPrice.ts | 79 ---------------------------------- 3 files changed, 14 insertions(+), 86 deletions(-) delete mode 100644 src/utils/useCUSDPrice.ts diff --git a/src/pages/Pool/index.tsx b/src/pages/Pool/index.tsx index 50baa87b64c..c13a226b40a 100644 --- a/src/pages/Pool/index.tsx +++ b/src/pages/Pool/index.tsx @@ -1,13 +1,13 @@ import { ErrorBoundary } from '@sentry/react' -import { cUSD, JSBI, TokenAmount } from '@ubeswap/sdk' +import { JSBI, TokenAmount } from '@ubeswap/sdk' import QuestionHelper from 'components/QuestionHelper' import { RowFixed } from 'components/Row' import { Chain, Coins, PRICE } from 'constants/StablePools' -import { useMobi } from 'hooks/Tokens' +import { CUSD } from 'constants/tokens' import React from 'react' import { isMobile } from 'react-device-detect' +import { useMobiPrice } from 'state/application/hooks' import styled from 'styled-components' -import { useCUSDPrice } from 'utils/useCUSDPrice' import { AutoColumn } from '../../components/Column' import { StablePoolCard } from '../../components/earn/StablePoolCard' @@ -80,8 +80,8 @@ export default function Pool() { const priceDeposited = JSBI.multiply(poolInfo?.totalDeposited?.raw ?? JSBI.BigInt('0'), lpPrice) return JSBI.add(accum, priceDeposited) }, JSBI.BigInt('0')) - const tvlAsTokenAmount = new TokenAmount(cUSD[CHAIN], tvl) - const mobiprice = useCUSDPrice(useMobi()) + const tvlAsTokenAmount = new TokenAmount(CUSD[CHAIN], tvl) + const mobiprice = useMobiPrice() const sortCallback = (pool1: StablePoolInfo, pool2: StablePoolInfo) => { if (!pool1 || !pool2) return true const isStaking1 = pool1.amountDeposited?.greaterThan(JSBI.BigInt('0')) || pool1.stakedAmount?.greaterThan('0') diff --git a/src/state/application/hooks.ts b/src/state/application/hooks.ts index 5f642173fbe..ee61a99c405 100644 --- a/src/state/application/hooks.ts +++ b/src/state/application/hooks.ts @@ -1,6 +1,7 @@ import { ApolloClient, NormalizedCacheObject } from '@apollo/client' import { Fraction } from '@ubeswap/sdk' import { useWeb3Context } from 'hooks' +import { useMobi } from 'hooks/Tokens' import { useCallback, useMemo } from 'react' import { useDispatch, useSelector } from 'react-redux' @@ -103,11 +104,17 @@ export function useTokenPrice(address: string | undefined): Fraction | undefined return priceStringToFraction(prices[address]) } -export function priceStringToFraction(priceString: string | undefined): Fraction | undefined { +export function useMobiPrice(): Fraction { + const mobi = useMobi() + const prices = useTokenPrices() + return priceStringToFraction(prices[mobi.address.toLowerCase()]) ?? new Fraction('0') +} + +function priceStringToFraction(priceString: string | undefined): Fraction | undefined { if (!priceString) return undefined const price = parseFloat(priceString) * 10 ** 4 const asFraction = new Fraction(price.toFixed(0), '10000') - return asFraction ?? undefined + return asFraction } export function useTokenPrices() { diff --git a/src/utils/useCUSDPrice.ts b/src/utils/useCUSDPrice.ts deleted file mode 100644 index 824039c76a3..00000000000 --- a/src/utils/useCUSDPrice.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { cUSD, Fraction, Price, Token } from '@ubeswap/sdk' -import { TokenPrices } from 'state/application/reducer' - -import { CHAIN } from '../constants' -import { priceStringToFraction, useTokenPrice } from '../state/application/hooks' - -type TokenPair = [Token | undefined, Token | undefined] - -export function getCUSDPrices(prices?: TokenPrices): { [address: string]: Fraction } { - return ( - Object.entries(prices ?? {})?.reduce( - (accum, [address, price]) => ({ ...accum, [address]: priceStringToFraction(price) }), - {} - ) ?? {} - ) -} - -/** - * Returns the price in cUSD of the input currency - * @param currency currency to compute the cUSD price of - */ -export function useCUSDPrice(tokens?: Token[] | Token): Price | undefined { - const CUSD = cUSD[CHAIN] - if (tokens instanceof Token) { - tokens = [tokens] - } - - const p1 = useTokenPrice(tokens?.[0]?.address) - const p2 = useTokenPrice(tokens?.[1]?.address) - return p1 - ? new Price(tokens?.[0], CUSD, p1.denominator, p1.numerator) - : p2 - ? new Price(tokens?.[1], CUSD, p2.denominator, p2.numerator) - : undefined - - // const CUSD = cUSD[chainId as unknown as UbeswapChainId] - // const celo = CELO[chainId as unknown as UbeswapChainId] - // const tokenPairs: TokenPair[] = useMemo( - // () => - // tokens - // ?.map((token) => [ - // [token && currencyEquals(token, CUSD) ? undefined : token, CUSD], - // [token && currencyEquals(token, celo) ? undefined : token, celo], - // [celo, CUSD], - // ]) - // .flat() as TokenPair[], - // [CUSD, celo, tokens] - // ) - // const pairs = usePairs(tokenPairs).map((x) => x[1]) - - // return useMemo(() => { - // if (!tokens || !chainId) { - // return undefined - // } - - // const prices = tokens.map((token, idx) => { - // const start = idx * 3 - // const [cUSDPair, celoPair, celoCUSDPair] = [pairs[start], pairs[start + 1], pairs[start + 2]] - - // // handle cUSD - // if (token.equals(CUSD)) { - // return new Price(CUSD, CUSD, '1', '1') - // } - // let price: Price | undefined = undefined - - // if (celoPair && celoCUSDPair) { - // price = celoPair.priceOf(token).multiply(celoCUSDPair.priceOf(celo)) - // } - - // if (cUSDPair) { - // const newPrice = cUSDPair.priceOf(token) - // price = !price || newPrice.greaterThan(new Fraction(price.numerator, price.denominator)) ? newPrice : price - // } - - // return price - // }) - // return prices.filter((p: Price | undefined) => !p)[0] ?? undefined - // }, [chainId, tokens, CUSD, celo, pairs]) -} From 6976b9882504e6f089b0c62ac94987e5c537dab0 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 18:35:07 -0500 Subject: [PATCH 38/72] mobi token utils --- package.json | 2 + src/constants/mento.ts | 2 +- src/constants/poolManager.ts | 7 -- src/constants/pools.ts | 30 +++---- src/constants/staking.ts | 2 +- src/constants/tokens.ts | 69 ++++++--------- src/lib/calculator/amounts.ts | 85 +++++++++++------- src/lib/calculator/curve.ts | 4 +- src/lib/calculator/price.ts | 29 +++---- src/lib/token-utils/index.ts | 22 +++++ src/lib/token-utils/price.ts | 44 ++++++++++ src/lib/token-utils/splTokenRegistry.ts | 98 +++++++++++++++++++++ src/lib/token-utils/token.ts | 109 ++++++++++++++++++++++++ src/lib/token-utils/tokenAmount.ts | 100 ++++++++++++++++++++++ src/lib/token-utils/tokenList.ts | 97 +++++++++++++++++++++ yarn.lock | 22 ++++- 16 files changed, 599 insertions(+), 123 deletions(-) delete mode 100644 src/constants/poolManager.ts create mode 100644 src/lib/token-utils/index.ts create mode 100644 src/lib/token-utils/price.ts create mode 100644 src/lib/token-utils/splTokenRegistry.ts create mode 100644 src/lib/token-utils/token.ts create mode 100644 src/lib/token-utils/tokenAmount.ts create mode 100644 src/lib/token-utils/tokenList.ts diff --git a/package.json b/package.json index 78cdb8d8b81..b5d5b13e140 100644 --- a/package.json +++ b/package.json @@ -139,11 +139,13 @@ "@types/react-date-range": "^1.1.8", "@types/react-vis": "^1.11.7", "@ubeswap/sdk": "^2.1.0", + "@ubeswap/token-math": "^4.4.4", "@walletconnect/web3-provider": "^1.7.1", "@web3-react/abstract-connector": "^6.0.7", "axios": "^0.21.4", "bignumber.js": "^9.0.1", "graphql": "^15.7.1", + "jsbi": "^4.1.0", "lodash": "^4.17.21", "lodash.mapvalues": "^4.6.0", "randombytes": "^2.1.0", diff --git a/src/constants/mento.ts b/src/constants/mento.ts index 0c65e6bf1b4..80dcef0def9 100644 --- a/src/constants/mento.ts +++ b/src/constants/mento.ts @@ -1,5 +1,5 @@ import { CeloContract, StableToken } from '@celo/contractkit' -import { ChainId, Percent, TokenAmount } from '@ubeswap/sdk' +import { ChainId, Percent, TokenAmount } from 'lib/token-utils' /** * Static definition of a Mento exchange. diff --git a/src/constants/poolManager.ts b/src/constants/poolManager.ts deleted file mode 100644 index ce376418686..00000000000 --- a/src/constants/poolManager.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ChainId } from '@ubeswap/sdk' - -//todo: replace Mainnet and Baklava PoolManager Addresses -export const POOL_MANAGER = { - [ChainId.MAINNET]: '0x9Ee3600543eCcc85020D6bc77EB553d1747a65D2', - [ChainId.ALFAJORES]: '0x9Ee3600543eCcc85020D6bc77EB553d1747a65D2', -} diff --git a/src/constants/pools.ts b/src/constants/pools.ts index dbd42bb6e00..5092a63f51b 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -1,5 +1,5 @@ -import { ChainId, Percent, Token, TokenAmount } from '@ubeswap/sdk' import JSBI from 'jsbi' +import { ChainId, Percent, Token, TokenAmount } from 'lib/token-utils' import { CHAIN } from './' import { CELO, CETH, CUSD, UST, WETH } from './tokens' @@ -149,13 +149,13 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { peg: Dollar, pool: { address: '0x9F4AdBD0af281C69a582eB2E6fa2A594D4204CAe', - lpToken: new Token( - ChainId.MAINNET, - '0x9438e7281D7E3e99A9dD21e0EAd9c6a254e17ab2', - 18, - 'MobLP', - 'Mobius cUSD/aUST LP' - ), + lpToken: new Token({ + chainId: ChainId.MAINNET, + address: '0x9438e7281D7E3e99A9dD21e0EAd9c6a254e17ab2', + decimals: 18, + symbol: 'MobLP', + name: 'Mobius cUSD/aUST LP', + }), tokens: [CUSD[ChainId.MAINNET], UST[ChainId.MAINNET]], }, gauge: { @@ -169,13 +169,13 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { peg: Ether, pool: { address: '0x74ef28D635c6C5800DD3Cd62d4c4f8752DaACB09', - lpToken: new Token( - ChainId.MAINNET, - '0x4fF08e2a4E7114af4B575AeF9250144f95790982', - 18, - 'MobLP', - 'Mobius cETH/wETH LP' - ), + lpToken: new Token({ + chainId: ChainId.MAINNET, + address: '0x4fF08e2a4E7114af4B575AeF9250144f95790982', + decimals: 18, + symbol: 'MobLP', + name: 'Mobius cUSD/aUST LP', + }), tokens: [CETH[ChainId.MAINNET], WETH[ChainId.MAINNET]], }, gauge: { diff --git a/src/constants/staking.ts b/src/constants/staking.ts index 99f8b4f7de2..a7bc445ef79 100644 --- a/src/constants/staking.ts +++ b/src/constants/staking.ts @@ -1,4 +1,4 @@ -import { ChainId } from '@ubeswap/sdk' +import { ChainId } from 'lib/token-utils' import { CELO } from './tokens' diff --git a/src/constants/tokens.ts b/src/constants/tokens.ts index bda4db4d7e6..6e6212ba2b4 100644 --- a/src/constants/tokens.ts +++ b/src/constants/tokens.ts @@ -1,6 +1,5 @@ -import { ChainId } from '@ubeswap/sdk' +import { ChainId, Token } from 'lib/token-utils' import mapValues from 'lodash/mapValues' -import { WrappedTokenInfo } from 'state/lists/hooks' const makeTokens = ( addresses: { [net in ChainId]: string }, @@ -8,12 +7,9 @@ const makeTokens = ( symbol: string, name: string, logoURI: string -): { [net in ChainId]: WrappedTokenInfo } => { +): { [net in ChainId]: Token } => { return mapValues(addresses, (tokenAddress, network) => { - return new WrappedTokenInfo( - { chainId: parseInt(network), address: tokenAddress, decimals, symbol, name, logoURI }, - [] - ) + return new Token({ chainId: parseInt(network), address: tokenAddress, decimals, symbol, name, logoURI }) }) } @@ -125,41 +121,32 @@ export const WETH = makeTokens( 'https://etherscan.io/token/images/weth_28.png' ) -export const ExternalRewards: { [K in ChainId]: WrappedTokenInfo[] } = { +export const ExternalRewards: { [K in ChainId]: Token[] } = { [ChainId.MAINNET]: [ - new WrappedTokenInfo( - { - address: '0x00400FcbF0816bebB94654259de7273f4A05c762', - name: 'Poof', - symbol: 'POOF', - chainId: ChainId.MAINNET, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_POOF.png', - }, - [] - ), - new WrappedTokenInfo( - { - address: '0x17700282592D6917F6A73D0bF8AcCf4D578c131e', - name: 'Moola', - symbol: 'MOO', - chainId: ChainId.MAINNET, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_MOO.png', - }, - [] - ), - new WrappedTokenInfo( - { - address: '0x471EcE3750Da237f93B8E339c536989b8978a438', - name: 'Celo', - symbol: 'CELO', - chainId: ChainId.MAINNET, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_CELO.png', - }, - [] - ), + new Token({ + address: '0x00400FcbF0816bebB94654259de7273f4A05c762', + name: 'Poof', + symbol: 'POOF', + chainId: ChainId.MAINNET, + decimals: 18, + logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_POOF.png', + }), + new Token({ + address: '0x17700282592D6917F6A73D0bF8AcCf4D578c131e', + name: 'Moola', + symbol: 'MOO', + chainId: ChainId.MAINNET, + decimals: 18, + logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_MOO.png', + }), + new Token({ + address: '0x471EcE3750Da237f93B8E339c536989b8978a438', + name: 'Celo', + symbol: 'CELO', + chainId: ChainId.MAINNET, + decimals: 18, + logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_CELO.png', + }), ], [ChainId.ALFAJORES]: [], [ChainId.BAKLAVA]: [], diff --git a/src/lib/calculator/amounts.ts b/src/lib/calculator/amounts.ts index a54f37a0af6..85e9ef20ca6 100644 --- a/src/lib/calculator/amounts.ts +++ b/src/lib/calculator/amounts.ts @@ -1,13 +1,11 @@ -import { Fraction, Token, TokenAmount } from '@ubeswap/sdk' +import type { Fees, IExchangeInfo } from 'constants/pools' import JSBI from 'jsbi' +import type { Token } from 'lib/token-utils' +import { Fraction, ONE, TokenAmount, ZERO } from 'lib/token-utils' import mapValues from 'lodash.mapvalues' -import type { Fees, IExchangeInfo } from '../../constants/pools' import { computeD, computeY } from './curve' -const ZERO = JSBI.BigInt(0) -const ONE = JSBI.BigInt(1) - /** * Calculates the current virtual price of the exchange. * @param exchange @@ -15,7 +13,7 @@ const ONE = JSBI.BigInt(1) */ export const calculateVirtualPrice = (exchange: IExchangeInfo): Fraction | null => { const amount = exchange.lpTotalSupply - if (amount === undefined || amount.equalTo('0')) { + if (amount === undefined || amount.equalTo(0)) { // pool has no tokens return null } @@ -38,12 +36,12 @@ export const calculateEstimatedSwapOutputAmount = ( ): { [K in 'outputAmountBeforeFees' | 'outputAmount' | 'fee' | 'lpFee' | 'adminFee']: TokenAmount } => { - const [fromReserves, toReserves] = fromAmount.token.equals(exchange.reserves[0].token) + const [fromReserves, toReserves] = fromAmount.token.equals(exchange.reserves[0].amount.token) ? [exchange.reserves[0], exchange.reserves[1]] : [exchange.reserves[1], exchange.reserves[0]] - if (fromAmount.equalTo('0')) { - const zero = new TokenAmount(toReserves.token, ZERO) + if (fromAmount.equalTo(0)) { + const zero = new TokenAmount(toReserves.amount.token, ZERO) return { outputAmountBeforeFees: zero, outputAmount: zero, @@ -56,18 +54,28 @@ export const calculateEstimatedSwapOutputAmount = ( const amp = exchange.ampFactor const amountBeforeFees = JSBI.subtract( - toReserves.raw, - computeY(amp, JSBI.add(fromReserves.raw, fromAmount.raw), computeD(amp, fromReserves.raw, toReserves.raw)) + toReserves.amount.raw, + computeY( + amp, + JSBI.add(fromReserves.amount.raw, fromAmount.raw), + computeD(amp, fromReserves.amount.raw, toReserves.amount.raw) + ) ) - const outputAmountBeforeFees = new TokenAmount(toReserves.token, amountBeforeFees) + const outputAmountBeforeFees = new TokenAmount(toReserves.amount.token, amountBeforeFees) - const fee = new TokenAmount(toReserves.token, exchange.fees.trade.multiply(amountBeforeFees).toFixed(0)) + const fee = new TokenAmount( + toReserves.amount.token, + exchange.fees.trade.asFraction.multiply(amountBeforeFees).toFixed(0) + ) - const adminFee = new TokenAmount(toReserves.token, exchange.fees.admin.multiply(fee.raw).toFixed(0)) + const adminFee = new TokenAmount( + toReserves.amount.token, + exchange.fees.adminTrade.asFraction.multiply(fee.raw).toFixed(0) + ) const lpFee = fee.subtract(adminFee) - const outputAmount = new TokenAmount(toReserves.token, JSBI.subtract(amountBeforeFees, fee.raw)) + const outputAmount = new TokenAmount(toReserves.amount.token, JSBI.subtract(amountBeforeFees, fee.raw)) return { outputAmountBeforeFees, @@ -86,7 +94,9 @@ export interface IWithdrawOneResult { swapFee: TokenAmount withdrawFee: TokenAmount lpSwapFee: TokenAmount + lpWithdrawFee: TokenAmount adminSwapFee: TokenAmount + adminWithdrawFee: TokenAmount } /** @@ -102,7 +112,7 @@ export const calculateEstimatedWithdrawOneAmount = ({ poolTokenAmount: TokenAmount withdrawToken: Token }): IWithdrawOneResult => { - if (poolTokenAmount.equalTo('0')) { + if (poolTokenAmount.equalTo(0)) { // final quantities const quantities = { withdrawAmount: ZERO, @@ -110,7 +120,9 @@ export const calculateEstimatedWithdrawOneAmount = ({ swapFee: ZERO, withdrawFee: ZERO, lpSwapFee: ZERO, + lpWithdrawFee: ZERO, adminSwapFee: ZERO, + adminWithdrawFee: ZERO, } return mapValues(quantities, (q) => new TokenAmount(withdrawToken, q)) } @@ -118,8 +130,8 @@ export const calculateEstimatedWithdrawOneAmount = ({ const { ampFactor, fees } = exchange const [baseReserves, quoteReserves] = [ - exchange.reserves.find((r) => r.token.equals(withdrawToken))?.raw ?? ZERO, - exchange.reserves.find((r) => !r.token.equals(withdrawToken))?.raw ?? ZERO, + exchange.reserves.find((r) => r.amount.token.equals(withdrawToken))?.amount.raw ?? ZERO, + exchange.reserves.find((r) => !r.amount.token.equals(withdrawToken))?.amount.raw ?? ZERO, ] const d_0 = computeD(ampFactor, baseReserves, quoteReserves) @@ -132,25 +144,27 @@ export const calculateEstimatedWithdrawOneAmount = ({ // expected_quote_amount = swap_quote_amount - swap_quote_amount * d_1 / d_0; const expected_quote_amount = JSBI.subtract(quoteReserves, JSBI.divide(JSBI.multiply(quoteReserves, d_1), d_0)) // new_base_amount = swap_base_amount - expected_base_amount * fee / fee_denominator; - const new_base_amount = new Fraction(baseReserves.toString(), '1').subtract( + const new_base_amount = new Fraction(baseReserves.toString(), 1).subtract( normalizedTradeFee(fees, N_COINS, expected_base_amount) ) // new_quote_amount = swap_quote_amount - expected_quote_amount * fee / fee_denominator; - const new_quote_amount = new Fraction(quoteReserves.toString(), '1').subtract( + const new_quote_amount = new Fraction(quoteReserves.toString(), 1).subtract( normalizedTradeFee(fees, N_COINS, expected_quote_amount) ) const dy = new_base_amount.subtract(computeY(ampFactor, JSBI.BigInt(new_quote_amount.toFixed(0)), d_1).toString()) const dy_0 = JSBI.subtract(baseReserves, new_y) // lp fees - const swapFee = new Fraction(dy_0.toString(), '1').subtract(dy) - const withdrawFee = dy.multiply(fees.withdraw) + const swapFee = new Fraction(dy_0.toString(), 1).subtract(dy) + const withdrawFee = dy.multiply(fees.withdraw.asFraction) // admin fees - const adminSwapFee = swapFee.multiply(fees.admin) + const adminSwapFee = swapFee.multiply(fees.adminTrade.asFraction) + const adminWithdrawFee = withdrawFee.multiply(fees.adminWithdraw.asFraction) // final LP fees const lpSwapFee = swapFee.subtract(adminSwapFee) + const lpWithdrawFee = withdrawFee.subtract(adminWithdrawFee) // final withdraw amount const withdrawAmount = dy.subtract(withdrawFee).subtract(swapFee) @@ -162,7 +176,9 @@ export const calculateEstimatedWithdrawOneAmount = ({ swapFee, withdrawFee, lpSwapFee, + lpWithdrawFee, adminSwapFee, + adminWithdrawFee, } return mapValues(quantities, (q) => new TokenAmount(withdrawToken, q.toFixed(0))) @@ -173,7 +189,7 @@ export const calculateEstimatedWithdrawOneAmount = ({ */ export const normalizedTradeFee = ({ trade }: Fees, n_coins: JSBI, amount: JSBI): Fraction => { const adjustedTradeFee = new Fraction(n_coins, JSBI.multiply(JSBI.subtract(n_coins, ONE), JSBI.BigInt(4))) - return new Fraction(amount, '1').multiply(trade).multiply(adjustedTradeFee) + return new Fraction(amount, 1).multiply(trade).multiply(adjustedTradeFee) } export const calculateEstimatedWithdrawAmount = ({ @@ -191,8 +207,8 @@ export const calculateEstimatedWithdrawAmount = ({ withdrawAmountsBeforeFees: readonly [TokenAmount, TokenAmount] fees: readonly [TokenAmount, TokenAmount] } => { - if (lpTotalSupply.equalTo('0')) { - const zero = reserves.map((r) => new TokenAmount(r.token, ZERO)) as [TokenAmount, TokenAmount] + if (lpTotalSupply.equalTo(0)) { + const zero = reserves.map((r) => new TokenAmount(r.amount.token, ZERO)) as [TokenAmount, TokenAmount] return { withdrawAmounts: zero, withdrawAmountsBeforeFees: zero, @@ -202,9 +218,9 @@ export const calculateEstimatedWithdrawAmount = ({ const share = poolTokenAmount.divide(lpTotalSupply) - const withdrawAmounts = reserves.map((amount) => { + const withdrawAmounts = reserves.map(({ amount }) => { const baseAmount = share.multiply(amount.raw) - const fee = baseAmount.multiply(fees.withdraw) + const fee = baseAmount.multiply(fees.withdraw.asFraction) return [ new TokenAmount(amount.token, JSBI.BigInt(baseAmount.subtract(fee).toFixed(0))), { @@ -250,20 +266,23 @@ export const calculateEstimatedMintAmount = ( const amp = exchange.ampFactor const [reserveA, reserveB] = exchange.reserves - const d0 = computeD(amp, reserveA.raw, reserveB.raw) + const d0 = computeD(amp, reserveA.amount.raw, reserveB.amount.raw) - const d1 = computeD(amp, JSBI.add(reserveA.raw, depositAmountA), JSBI.add(reserveB.raw, depositAmountB)) + const d1 = computeD(amp, JSBI.add(reserveA.amount.raw, depositAmountA), JSBI.add(reserveB.amount.raw, depositAmountB)) if (JSBI.lessThan(d1, d0)) { throw new Error('New D cannot be less than previous D') } - const oldBalances = exchange.reserves.map((r) => r.raw) as [JSBI, JSBI] - const newBalances = [JSBI.add(reserveA.raw, depositAmountA), JSBI.add(reserveB.raw, depositAmountB)] as const + const oldBalances = exchange.reserves.map((r) => r.amount.raw) as [JSBI, JSBI] + const newBalances = [ + JSBI.add(reserveA.amount.raw, depositAmountA), + JSBI.add(reserveB.amount.raw, depositAmountB), + ] as const const adjustedBalances = newBalances.map((newBalance, i) => { const oldBalance = oldBalances[i] as JSBI const idealBalance = new Fraction(d1, d0).multiply(oldBalance) const difference = idealBalance.subtract(newBalance) - const diffAbs = difference.greaterThan('0') ? difference : difference.multiply('-1') + const diffAbs = difference.greaterThan(0) ? difference : difference.multiply(-1) const fee = normalizedTradeFee(exchange.fees, N_COINS, JSBI.BigInt(diffAbs.toFixed(0))) return JSBI.subtract(newBalance, JSBI.BigInt(fee.toFixed(0))) }) as [JSBI, JSBI] diff --git a/src/lib/calculator/curve.ts b/src/lib/calculator/curve.ts index 24f953e6471..4f3e07ca97a 100644 --- a/src/lib/calculator/curve.ts +++ b/src/lib/calculator/curve.ts @@ -1,7 +1,5 @@ import JSBI from 'jsbi' - -const ZERO = JSBI.BigInt(0) -const ONE = JSBI.BigInt(1) +import { ONE, ZERO } from 'lib/token-utils' const N_COINS = JSBI.BigInt(2) // n diff --git a/src/lib/calculator/price.ts b/src/lib/calculator/price.ts index 08f7f0dc16e..5b503e2ff9e 100644 --- a/src/lib/calculator/price.ts +++ b/src/lib/calculator/price.ts @@ -1,7 +1,8 @@ -import { JSBI, Price, TokenAmount } from '@ubeswap/sdk' +import BN from 'bn.js' +import type { IExchangeInfo } from 'constants/pools' +import { Price, TokenAmount } from 'lib/token-utils' -import type { IExchangeInfo } from '../../constants/pools' -import { calculateEstimatedSwapOutputAmount } from '.' +import { calculateEstimatedSwapOutputAmount } from './' /** * Gets the price of the second token in the swap, i.e. "Token 1", with respect to "Token 0". @@ -9,15 +10,6 @@ import { calculateEstimatedSwapOutputAmount } from '.' * To get the price of "Token 0", use `.invert()` on the result of this function. * @returns */ - -function min(a: JSBI, b: JSBI): JSBI { - return JSBI.greaterThan(a, b) ? b : a -} - -function max(a: JSBI, b: JSBI): JSBI { - return JSBI.greaterThan(a, b) ? a : b -} - export const calculateSwapPrice = (exchangeInfo: IExchangeInfo): Price => { const reserve0 = exchangeInfo.reserves[0] const reserve1 = exchangeInfo.reserves[1] @@ -25,16 +17,15 @@ export const calculateSwapPrice = (exchangeInfo: IExchangeInfo): Price => { // We try to get at least 4 decimal points of precision here // Otherwise, we attempt to swap 1% of total supply of the pool // or at most, $1 - const inputAmountNum = max( - JSBI.BigInt('10000'), - min( - JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt(reserve0.token.decimals)), - JSBI.divide(reserve0.raw, JSBI.BigInt('100')) - ) + const inputAmountNum = Math.max( + 10_000, + Math.min(10 ** reserve0.token.decimals, Math.floor(parseInt(reserve0.toU64().div(new BN(100)).toString()))) ) const inputAmount = new TokenAmount(reserve0.token, inputAmountNum) const outputAmount = calculateEstimatedSwapOutputAmount(exchangeInfo, inputAmount) - return new Price(reserve0.token, reserve1.token, outputAmount.outputAmountBeforeFees.raw, inputAmount.raw) + const frac = outputAmount.outputAmountBeforeFees.asFraction.divide(inputAmount.asFraction) + + return new Price(reserve0.token, reserve1.token, frac.denominator, frac.numerator) } diff --git a/src/lib/token-utils/index.ts b/src/lib/token-utils/index.ts new file mode 100644 index 00000000000..fe636675f14 --- /dev/null +++ b/src/lib/token-utils/index.ts @@ -0,0 +1,22 @@ +export * from './price' +export * from './token' +export * from './tokenAmount' + +// re-export token-math types +// so consumers don't need to use them +export { ChainId } from '@ubeswap/sdk' +export type { BigintIsh, IFormatUint, NumberFormat } from '@ubeswap/token-math' +export { + Fraction, + makeDecimalMultiplier, + MAX_U64, + MAX_U256, + ONE, + parseBigintIsh, + Percent, + Rounding, + TEN, + validateU64, + validateU256, + ZERO, +} from '@ubeswap/token-math' diff --git a/src/lib/token-utils/price.ts b/src/lib/token-utils/price.ts new file mode 100644 index 00000000000..190285ed919 --- /dev/null +++ b/src/lib/token-utils/price.ts @@ -0,0 +1,44 @@ +import type { BigintIsh } from '@ubeswap/token-math' +import { Price as UPrice } from '@ubeswap/token-math' +import invariant from 'tiny-invariant' + +import type { Token } from './token' +import { TokenAmount } from './tokenAmount' + +/** + * A price of one token relative to another. + */ +export class Price extends UPrice { + /** + * Constructs a price. + * @param baseCurrency + * @param quoteCurrency + * @param denominator + * @param numerator + */ + constructor(baseCurrency: Token, quoteCurrency: Token, denominator: BigintIsh, numerator: BigintIsh) { + super(baseCurrency, quoteCurrency, denominator, numerator) + } + + override invert(): Price { + return new Price(this.quoteCurrency, this.baseCurrency, this.numerator, this.denominator) + } + + override multiply(other: Price): Price { + invariant( + this.quoteCurrency.equals(other.baseCurrency), + `multiply token mismatch: ${this.quoteCurrency.toString()} !== ${other.baseCurrency.toString()}` + ) + const fraction = super.asFraction.multiply(other) + return new Price(this.baseCurrency, other.quoteCurrency, fraction.denominator, fraction.numerator) + } + + override quote(tokenAmount: TokenAmount): TokenAmount { + const amt = super.quote(tokenAmount) + return new TokenAmount(this.quoteCurrency, amt.raw) + } + + static fromUPrice(price: UPrice): Price { + return new Price(price.baseCurrency, price.quoteCurrency, price.denominator, price.numerator) + } +} diff --git a/src/lib/token-utils/splTokenRegistry.ts b/src/lib/token-utils/splTokenRegistry.ts new file mode 100644 index 00000000000..d720e09e0e9 --- /dev/null +++ b/src/lib/token-utils/splTokenRegistry.ts @@ -0,0 +1,98 @@ +import { ChainId } from '@ubeswap/sdk' +/** + * These types all come from the @solana/spl-token-registry package. + * + * We re-export them here so we do not have to have a hard dependency on + * that package, which is massive. + */ + +export declare enum NetworkNames { + Alfajores = 'Alfajores', + Baklava = 'Baklava', + Mainnet = 'Mainnet', +} + +export interface Network { + name: NetworkNames + rpcUrl: string + graphQl: string + explorer: string + chainId: ChainId +} + +export declare const Alfajores: { + readonly name: NetworkNames.Alfajores + readonly rpcUrl: 'https://alfajores-forno.celo-testnet.org' + readonly graphQl: 'https://alfajores-blockscout.celo-testnet.org/graphiql' + readonly explorer: 'https://alfajores-blockscout.celo-testnet.org' + readonly chainId: ChainId.ALFAJORES +} +export declare const Baklava: { + readonly name: NetworkNames.Baklava + readonly rpcUrl: 'https://baklava-forno.celo-testnet.org' + readonly graphQl: 'https://baklava-blockscout.celo-testnet.org/graphiql' + readonly explorer: 'https://baklava-blockscout.celo-testnet.org' + readonly chainId: ChainId.BAKLAVA +} +export declare const Mainnet: { + readonly name: NetworkNames.Mainnet + readonly rpcUrl: 'https://forno.celo.org' + readonly graphQl: 'https://explorer.celo.org/graphiql' + readonly explorer: 'https://explorer.celo.org' + readonly chainId: ChainId.MAINNET +} + +/** + * A token list. + */ +export interface SPLTokenList { + readonly name: string + readonly logoURI: string + readonly tags: { [tag: string]: TagDetails } + readonly timestamp: string + readonly tokens: SPLTokenInfo[] +} + +/** + * Tag details. + */ +export interface TagDetails { + readonly name: string + readonly description: string +} + +/** + * TokenExtensions. + */ +export interface SPLTokenExtensions { + readonly website?: string + readonly bridgeContract?: string + readonly assetContract?: string + readonly address?: string + readonly explorer?: string + readonly twitter?: string + readonly github?: string + readonly medium?: string + readonly tgann?: string + readonly tggroup?: string + readonly discord?: string + readonly serumV3Usdt?: string + readonly serumV3Usdc?: string + readonly coingeckoId?: string + readonly imageUrl?: string + readonly description?: string +} + +/** + * TokenInfo. + */ +export interface SPLTokenInfo { + readonly chainId: number + readonly address: string + readonly name: string + readonly decimals: number + readonly symbol: string + readonly logoURI?: string + readonly tags?: string[] + readonly extensions?: SPLTokenExtensions +} diff --git a/src/lib/token-utils/token.ts b/src/lib/token-utils/token.ts new file mode 100644 index 00000000000..e9eea59924c --- /dev/null +++ b/src/lib/token-utils/token.ts @@ -0,0 +1,109 @@ +import { ChainId } from '@ubeswap/sdk' +import type { Token as UToken } from '@ubeswap/token-math' + +import { Alfajores, Baklava, Mainnet, Network } from './splTokenRegistry' +import type { TokenInfo } from './tokenList' + +/** + * Token information. + */ +export class Token implements UToken { + /** + * The network that the Token is on. + */ + readonly network: Network + + constructor(readonly info: TokenInfo) { + this.network = chainIdToNetwork(info.chainId) ?? 'localnet' + } + + /** + * The Base58 string representation of the mint address. + */ + get address(): string { + return this.info.address + } + + /** + * The chain ID of the token. + */ + get chainId(): number { + return this.info.chainId + } + + /** + * Number of decimals of the token. + */ + get decimals(): number { + return this.info.decimals + } + + /** + * The name of the token. + */ + get name(): string { + return this.info.name + } + + /** + * The symbol of the token. + */ + get symbol(): string { + return this.info.symbol + } + + /** + * The token's icon to render. + */ + get icon(): string | undefined { + return this.info.logoURI + } + + equals(other: Token): boolean { + return tokensEqual(this, other) + } + + toString(): string { + return `Token[address=${this.address}, decimals=${this.decimals}, network=${this.network}]` + } + + toJSON(): unknown { + return this.info + } + + /** + * Returns true if the given tag is present. + * @param tag The tag to check. + * @returns + */ + hasTag(tag: string): boolean { + return !!this.info.tags?.includes(tag) + } +} + +/** + * Checks if two tokens are equal. + * @param a + * @param b + * @returns + */ +export const tokensEqual = (a: Token | undefined, b: Token | undefined): boolean => + a !== undefined && b !== undefined && a.address === b.address && a.network === b.network + +/** + * Map of network to Token + */ +export type TokenMap = { [c in ChainId]: Token } + +export const CHAIN_ID_TO_NETWORK = { + [ChainId.MAINNET]: Mainnet, + [ChainId.ALFAJORES]: Alfajores, + [ChainId.BAKLAVA]: Baklava, +} + +/** + * Gets the Network associated with a chain id. + * @param network + * @returns + */ +export const chainIdToNetwork = (env: ChainId): Network => CHAIN_ID_TO_NETWORK[env] diff --git a/src/lib/token-utils/tokenAmount.ts b/src/lib/token-utils/tokenAmount.ts new file mode 100644 index 00000000000..a68939b7387 --- /dev/null +++ b/src/lib/token-utils/tokenAmount.ts @@ -0,0 +1,100 @@ +import type { BigintIsh, NumberFormat, Percent } from '@ubeswap/token-math' +import { parseBigintIsh, TokenAmount as UTokenAmount, validateU64 } from '@ubeswap/token-math' +import BN from 'bn.js' + +import type { Token } from './token' + +export interface IFormatUint { + /** + * If specified, format this according to `toLocaleString` + */ + numberFormatOptions?: Intl.NumberFormatOptions + /** + * Locale of the number + */ + locale?: string +} + +export class TokenAmount extends UTokenAmount { + // amount _must_ be raw, i.e. in the native representation + constructor(token: Token, amount: BigintIsh) { + super(token, amount) + validateU64(this.raw) + } + + /** + * Parses a token amount from a decimal representation. + * @param token + * @param uiAmount + * @returns + */ + static parse(token: Token, uiAmount: string): TokenAmount { + const prev = UTokenAmount.parseFromString(token, uiAmount) + return new TokenAmount(token, prev.raw) + } + + override add(other: TokenAmount): TokenAmount { + const result = super.add(other) + return new TokenAmount(this.token, result.raw) + } + override subtract(other: TokenAmount): TokenAmount { + const result = super.subtract(other) + return new TokenAmount(this.token, result.raw) + } + override multiplyBy(percent: Percent): TokenAmount { + const result = super.multiplyBy(percent) + return new TokenAmount(this.token, result.raw) + } + override reduceBy(percent: Percent): TokenAmount { + const result = super.reduceBy(percent) + return new TokenAmount(this.token, result.raw) + } + + /** + * Divides this TokenAmount by a raw integer. + * @param other + * @returns + */ + divideByInteger(other: BigintIsh): TokenAmount { + return new TokenAmount(this.token, this.toU64().div(new BN(parseBigintIsh(other).toString()))) + } + + /** + * Formats the token amount with units and decimal adjustment, e.g. "100.42 SOL" + * @returns + */ + formatUnits(format: NumberFormat = { groupSeparator: ',' }): string { + return `${this.toExact(format)} ${this.token.symbol}` + } + + /** + * String representation of this token amount. + */ + override toString(): string { + return `TokenAmount[Token=(${this.token.toString()}), amount=${this.toExact()}` + } + + /** + * JSON representation of the token amount. + */ + toJSON(): { + /** + * Discriminator to show this is a token amount. + */ + _isTA: true + /** + * Mint of the token. + */ + mint: string + /** + * Amount of tokens in string representation. + */ + uiAmount: string + } { + return { + _isTA: true, + mint: this.token.address, + uiAmount: this.toExact(), + } + } +} diff --git a/src/lib/token-utils/tokenList.ts b/src/lib/token-utils/tokenList.ts new file mode 100644 index 00000000000..97350e9e712 --- /dev/null +++ b/src/lib/token-utils/tokenList.ts @@ -0,0 +1,97 @@ +import type { SPLTokenExtensions, SPLTokenInfo, SPLTokenList } from './splTokenRegistry' +import { Token } from './token' + +/** + * Known origin chains. + */ +export const ORIGIN_CHAINS = [ + 'bitcoin', + 'ethereum', + 'terra', + 'avalanche', + 'binance', + 'celo', + 'polygon', + 'fantom', + 'polygon', + 'heco', +] as const + +/** + * Known origin chains. + */ +export type OriginChain = typeof ORIGIN_CHAINS[number] + +/** + * Token extensions with additional information. + */ +export type TokenExtensions = SPLTokenExtensions & { + /** + * Mints of the underlying tokens that make up this token. + * E.g. a Saber USDC-USDT LP token would use the USDC and USDT mints. + */ + readonly underlyingTokens?: string[] + /** + * The protocol that this token comes from. + * E.g. `wormhole-v1`, `wormhole-v2`, `allbridge`, `sollet`, `saber`. + */ + readonly source?: string + + /* + ** Link to the source's website where you can acquire this token + */ + readonly sourceUrl?: string + /** + * The currency code of what this token represents, e.g. BTC, ETH, USD. + */ + readonly currency?: string + /** + * If this token is a bridged token, this is the chain that the asset originates from. + */ + readonly originChain?: OriginChain +} + +/** + * Token info. + */ +export type TokenInfo = Omit & { + readonly extensions?: TokenExtensions +} + +/** + * A list of tokens, based off of the Uniswap standard. + */ +export type TokenList = Omit & { + readonly tokens: TokenInfo[] +} + +/** + * Creates a token map from a TokenList. + * @param tokens + * @returns + */ +export const makeTokenMap = (tokenList: TokenList): Record => { + const ret: Record = {} + tokenList.tokens.forEach((item) => { + ret[item.address] = new Token(item) + }) + return ret +} + +/** + * Dedupes a list of tokens, picking the first instance of the token in a list. + * @param tokens + * @returns + */ +export const dedupeTokens = (tokens: TokenInfo[]): TokenInfo[] => { + const seen = new Set() + return tokens.filter((token) => { + const tokenID = `${token.address}_${token.chainId}` + if (seen.has(tokenID)) { + return false + } else { + seen.add(tokenID) + return true + } + }) +} diff --git a/yarn.lock b/yarn.lock index 0bbd931bf3c..654865634fe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3633,6 +3633,17 @@ tiny-warning "^1.0.3" toformat "^2.0.0" +"@ubeswap/token-math@^4.4.4": + version "4.4.4" + resolved "https://registry.yarnpkg.com/@ubeswap/token-math/-/token-math-4.4.4.tgz#98ff131a4371a6229245d8aa79bf198a35682b9c" + integrity sha512-AbcyDhKVPaFQOuzak1UPyBPNbo6IHCKY4C2xq5DOcW6qmlI+4EaxI9mU2jpG/joYAtqPYrx2BbLizU+TfB6bmg== + dependencies: + big.js "^6.1.1" + decimal.js-light "^2.5.1" + tiny-invariant "^1.2.0" + toformat "^2.0.0" + tslib "^2.3.1" + "@uniswap/governance@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@uniswap/governance/-/governance-1.0.2.tgz#7371ab54dea9a5c045275001e2d5325ff2c11a93" @@ -4994,7 +5005,7 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -big.js@^6.0.3: +big.js@^6.0.3, big.js@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.1.1.tgz#63b35b19dc9775c94991ee5db7694880655d5537" integrity sha512-1vObw81a8ylZO5ePrtMay0n018TcftpTA5HFKDaSuiUDBo8biRBtjIobw60OpwuvrGk+FsxKamqN4cnmj/eXdg== @@ -10617,6 +10628,11 @@ jsbi@^3.1.4: resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-3.2.5.tgz#b37bb90e0e5c2814c1c2a1bcd8c729888a2e37d6" integrity sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ== +jsbi@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-4.1.0.tgz#f0c25ed8881bc09891334b03a3952efaa7add337" + integrity sha512-384Z4keIsJtYpnVggsxaB255MZctILbxv+ihtwoWPF7KNOlYHn1LFpRnUw5qsAspUAA2+I7qzjVJxVYtHVjxNw== + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -16259,7 +16275,7 @@ timsort@^0.3.0: resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= -tiny-invariant@^1.0.2, tiny-invariant@^1.1.0: +tiny-invariant@^1.0.2, tiny-invariant@^1.1.0, tiny-invariant@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9" integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== @@ -16463,7 +16479,7 @@ tslib@^1.0.0, tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0: +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== From cdd9d44cb398b1eac2a6ce50b686cb4699e7a3d1 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 18:48:51 -0500 Subject: [PATCH 39/72] calculator --- src/lib/calculator/amounts.ts | 55 +++++++++++------------------------ src/lib/calculator/price.ts | 18 ++++++++---- 2 files changed, 30 insertions(+), 43 deletions(-) diff --git a/src/lib/calculator/amounts.ts b/src/lib/calculator/amounts.ts index 85e9ef20ca6..e0ceb12bdb2 100644 --- a/src/lib/calculator/amounts.ts +++ b/src/lib/calculator/amounts.ts @@ -36,12 +36,12 @@ export const calculateEstimatedSwapOutputAmount = ( ): { [K in 'outputAmountBeforeFees' | 'outputAmount' | 'fee' | 'lpFee' | 'adminFee']: TokenAmount } => { - const [fromReserves, toReserves] = fromAmount.token.equals(exchange.reserves[0].amount.token) + const [fromReserves, toReserves] = fromAmount.token.equals(exchange.reserves[0].token) ? [exchange.reserves[0], exchange.reserves[1]] : [exchange.reserves[1], exchange.reserves[0]] if (fromAmount.equalTo(0)) { - const zero = new TokenAmount(toReserves.amount.token, ZERO) + const zero = new TokenAmount(toReserves.token, ZERO) return { outputAmountBeforeFees: zero, outputAmount: zero, @@ -54,28 +54,18 @@ export const calculateEstimatedSwapOutputAmount = ( const amp = exchange.ampFactor const amountBeforeFees = JSBI.subtract( - toReserves.amount.raw, - computeY( - amp, - JSBI.add(fromReserves.amount.raw, fromAmount.raw), - computeD(amp, fromReserves.amount.raw, toReserves.amount.raw) - ) + toReserves.raw, + computeY(amp, JSBI.add(fromReserves.raw, fromAmount.raw), computeD(amp, fromReserves.raw, toReserves.raw)) ) - const outputAmountBeforeFees = new TokenAmount(toReserves.amount.token, amountBeforeFees) + const outputAmountBeforeFees = new TokenAmount(toReserves.token, amountBeforeFees) - const fee = new TokenAmount( - toReserves.amount.token, - exchange.fees.trade.asFraction.multiply(amountBeforeFees).toFixed(0) - ) + const fee = new TokenAmount(toReserves.token, exchange.fees.trade.asFraction.multiply(amountBeforeFees).toFixed(0)) - const adminFee = new TokenAmount( - toReserves.amount.token, - exchange.fees.adminTrade.asFraction.multiply(fee.raw).toFixed(0) - ) + const adminFee = new TokenAmount(toReserves.token, exchange.fees.admin.asFraction.multiply(fee.raw).toFixed(0)) const lpFee = fee.subtract(adminFee) - const outputAmount = new TokenAmount(toReserves.amount.token, JSBI.subtract(amountBeforeFees, fee.raw)) + const outputAmount = new TokenAmount(toReserves.token, JSBI.subtract(amountBeforeFees, fee.raw)) return { outputAmountBeforeFees, @@ -94,9 +84,7 @@ export interface IWithdrawOneResult { swapFee: TokenAmount withdrawFee: TokenAmount lpSwapFee: TokenAmount - lpWithdrawFee: TokenAmount adminSwapFee: TokenAmount - adminWithdrawFee: TokenAmount } /** @@ -120,9 +108,7 @@ export const calculateEstimatedWithdrawOneAmount = ({ swapFee: ZERO, withdrawFee: ZERO, lpSwapFee: ZERO, - lpWithdrawFee: ZERO, adminSwapFee: ZERO, - adminWithdrawFee: ZERO, } return mapValues(quantities, (q) => new TokenAmount(withdrawToken, q)) } @@ -130,8 +116,8 @@ export const calculateEstimatedWithdrawOneAmount = ({ const { ampFactor, fees } = exchange const [baseReserves, quoteReserves] = [ - exchange.reserves.find((r) => r.amount.token.equals(withdrawToken))?.amount.raw ?? ZERO, - exchange.reserves.find((r) => !r.amount.token.equals(withdrawToken))?.amount.raw ?? ZERO, + exchange.reserves.find((r) => r.token.equals(withdrawToken))?.raw ?? ZERO, + exchange.reserves.find((r) => !r.token.equals(withdrawToken))?.raw ?? ZERO, ] const d_0 = computeD(ampFactor, baseReserves, quoteReserves) @@ -159,12 +145,10 @@ export const calculateEstimatedWithdrawOneAmount = ({ const withdrawFee = dy.multiply(fees.withdraw.asFraction) // admin fees - const adminSwapFee = swapFee.multiply(fees.adminTrade.asFraction) - const adminWithdrawFee = withdrawFee.multiply(fees.adminWithdraw.asFraction) + const adminSwapFee = swapFee.multiply(fees.admin.asFraction) // final LP fees const lpSwapFee = swapFee.subtract(adminSwapFee) - const lpWithdrawFee = withdrawFee.subtract(adminWithdrawFee) // final withdraw amount const withdrawAmount = dy.subtract(withdrawFee).subtract(swapFee) @@ -176,9 +160,7 @@ export const calculateEstimatedWithdrawOneAmount = ({ swapFee, withdrawFee, lpSwapFee, - lpWithdrawFee, adminSwapFee, - adminWithdrawFee, } return mapValues(quantities, (q) => new TokenAmount(withdrawToken, q.toFixed(0))) @@ -208,7 +190,7 @@ export const calculateEstimatedWithdrawAmount = ({ fees: readonly [TokenAmount, TokenAmount] } => { if (lpTotalSupply.equalTo(0)) { - const zero = reserves.map((r) => new TokenAmount(r.amount.token, ZERO)) as [TokenAmount, TokenAmount] + const zero = reserves.map((r) => new TokenAmount(r.token, ZERO)) as [TokenAmount, TokenAmount] return { withdrawAmounts: zero, withdrawAmountsBeforeFees: zero, @@ -218,7 +200,7 @@ export const calculateEstimatedWithdrawAmount = ({ const share = poolTokenAmount.divide(lpTotalSupply) - const withdrawAmounts = reserves.map(({ amount }) => { + const withdrawAmounts = reserves.map((amount) => { const baseAmount = share.multiply(amount.raw) const fee = baseAmount.multiply(fees.withdraw.asFraction) return [ @@ -266,18 +248,15 @@ export const calculateEstimatedMintAmount = ( const amp = exchange.ampFactor const [reserveA, reserveB] = exchange.reserves - const d0 = computeD(amp, reserveA.amount.raw, reserveB.amount.raw) + const d0 = computeD(amp, reserveA.raw, reserveB.raw) - const d1 = computeD(amp, JSBI.add(reserveA.amount.raw, depositAmountA), JSBI.add(reserveB.amount.raw, depositAmountB)) + const d1 = computeD(amp, JSBI.add(reserveA.raw, depositAmountA), JSBI.add(reserveB.raw, depositAmountB)) if (JSBI.lessThan(d1, d0)) { throw new Error('New D cannot be less than previous D') } - const oldBalances = exchange.reserves.map((r) => r.amount.raw) as [JSBI, JSBI] - const newBalances = [ - JSBI.add(reserveA.amount.raw, depositAmountA), - JSBI.add(reserveB.amount.raw, depositAmountB), - ] as const + const oldBalances = exchange.reserves.map((r) => r.raw) as [JSBI, JSBI] + const newBalances = [JSBI.add(reserveA.raw, depositAmountA), JSBI.add(reserveB.raw, depositAmountB)] as const const adjustedBalances = newBalances.map((newBalance, i) => { const oldBalance = oldBalances[i] as JSBI const idealBalance = new Fraction(d1, d0).multiply(oldBalance) diff --git a/src/lib/calculator/price.ts b/src/lib/calculator/price.ts index 5b503e2ff9e..c7e745976e5 100644 --- a/src/lib/calculator/price.ts +++ b/src/lib/calculator/price.ts @@ -1,9 +1,17 @@ -import BN from 'bn.js' import type { IExchangeInfo } from 'constants/pools' -import { Price, TokenAmount } from 'lib/token-utils' +import JSBI from 'jsbi' +import { Price, TEN, TokenAmount } from 'lib/token-utils' import { calculateEstimatedSwapOutputAmount } from './' +function min(a: JSBI, b: JSBI): JSBI { + return JSBI.greaterThanOrEqual(a, b) ? b : a +} + +function max(a: JSBI, b: JSBI): JSBI { + return JSBI.greaterThanOrEqual(a, b) ? a : b +} + /** * Gets the price of the second token in the swap, i.e. "Token 1", with respect to "Token 0". * @@ -17,9 +25,9 @@ export const calculateSwapPrice = (exchangeInfo: IExchangeInfo): Price => { // We try to get at least 4 decimal points of precision here // Otherwise, we attempt to swap 1% of total supply of the pool // or at most, $1 - const inputAmountNum = Math.max( - 10_000, - Math.min(10 ** reserve0.token.decimals, Math.floor(parseInt(reserve0.toU64().div(new BN(100)).toString()))) + const inputAmountNum = max( + JSBI.BigInt(10_000), + min(JSBI.exponentiate(TEN, JSBI.BigInt(reserve0.token.decimals)), reserve0.divide(100).quotient) ) const inputAmount = new TokenAmount(reserve0.token, inputAmountNum) From 210a01b3c2f5dcfdf4d5b149670cb28886c73224 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 23:15:13 -0500 Subject: [PATCH 40/72] . --- src/components/CurrencyInputPanel/index.tsx | 36 +- src/components/CurrencyLogo/index.tsx | 13 +- src/components/CurrencyPoolLogo/index.tsx | 2 +- src/components/DoubleLogo/index.tsx | 2 +- .../FormattedCurrencyAmount/index.tsx | 3 +- src/components/Header/URLWarning.tsx | 2 +- src/components/Header/UbeBalanceContent.tsx | 6 +- src/components/Header/index.tsx | 3 +- src/components/Header/useCirculatingSupply.ts | 5 +- .../PoolSearchModal/CurrencyList.tsx | 4 +- .../PoolSearchModal/CurrencySearch.tsx | 2 +- .../PoolSearchModal/CurrencySearchModal.tsx | 2 +- src/components/SearchModal/CurrencyList.tsx | 7 +- src/components/SearchModal/CurrencySearch.tsx | 2 +- .../SearchModal/CurrencySearchModal.tsx | 2 +- src/components/SearchModal/filtering.ts | 2 +- src/components/SearchModal/sorting.ts | 2 +- .../TransactionConfirmationModal/index.tsx | 2 +- .../earn/ClaimExternalRewardsModal.tsx | 2 +- src/components/earn/ClaimRewardModal.tsx | 2 +- src/components/earn/DepositModal.tsx | 3 +- src/components/earn/StablePoolCard.tsx | 3 +- src/components/earn/StakingModal.tsx | 2 +- src/components/earn/UnstakingModal.tsx | 2 +- src/components/earn/WithdrawLP.tsx | 3 +- src/components/earn/WithdrawTokens.tsx | 3 +- src/components/swap/ConfirmSwapModal.tsx | 5 +- src/components/swap/FormattedPriceImpact.tsx | 2 +- src/components/swap/TradePrice.tsx | 2 +- src/connectors/index.ts | 3 +- src/connectors/ledger/LedgerConnector.tsx | 3 +- src/constants/ConstantSum.ts | 2 +- src/constants/NetworkInfo.ts | 2 +- src/constants/StablePools.ts | 3 +- src/constants/index.ts | 3 +- src/constants/multicall/index.ts | 2 +- src/data/Allowances.ts | 2 +- src/data/TotalSupply.ts | 2 +- src/hooks/Tokens.ts | 2 +- src/hooks/useApproveCallback.ts | 2 +- src/hooks/useColor.ts | 2 +- src/hooks/useExternalStakingRewards.ts | 3 +- src/hooks/useMentoCallback.ts | 3 +- src/hooks/useSwapCallback.ts | 3 +- src/lib/mentoCalculator/amounts.ts | 2 +- src/lib/mentoCalculator/price.ts | 2 +- src/lib/token-utils/index.ts | 2 + src/lib/token-utils/splTokenRegistry.ts | 38 +- src/lib/token-utils/token.ts | 3 +- .../CreateProposal/ProposalActionDetail.tsx | 2 +- src/pages/CreateProposal/index.tsx | 2 +- src/pages/Mento/index.tsx | 3 +- src/pages/OpenSum/index.tsx | 2 +- src/pages/Pool/Manage.tsx | 3 +- src/pages/Pool/index.tsx | 3 +- src/pages/Staking/CalcBoost.tsx | 3 +- src/pages/Staking/GaugeWeights.tsx | 2 +- src/pages/Staking/Lock/IncreaseLockAmount.tsx | 3 +- src/pages/Staking/Lock/Lock.tsx | 3 +- src/pages/Staking/Positions.tsx | 3 +- src/pages/Staking/index.tsx | 2 +- src/pages/Swap/index.tsx | 21 +- src/pages/Vote/VotePage.tsx | 4 +- src/pages/Vote/index.tsx | 2 +- src/state/application/hooks.ts | 2 +- src/state/claim/hooks.ts | 2 +- src/state/claim/updater.ts | 2 +- src/state/gauges/hooks.ts | 3 +- src/state/gauges/reducer.ts | 2 +- src/state/gauges/updater.ts | 2 +- src/state/governance/hooks.ts | 4 +- src/state/lists/hooks.ts | 2 +- src/state/mento/hooks.ts | 4 +- src/state/mentoPools/hooks.ts | 2 +- src/state/mentoPools/reducer.ts | 2 +- src/state/mentoPools/updater.ts | 3 +- src/state/mobiusPools/hooks.ts | 11 +- src/state/mobiusPools/reducer.ts | 2 +- src/state/mobiusPools/updater.ts | 5 +- src/state/openSum/actions.ts | 2 +- src/state/openSum/hooks.ts | 4 +- src/state/openSum/reducer.ts | 2 +- src/state/openSum/updater.ts | 7 +- src/state/stablePools/hooks.ts | 472 +++++++++--------- src/state/stablePools/reducer.ts | 2 +- src/state/stablePools/updater.ts | 440 ++++++++-------- src/state/stake/hooks.ts | 2 +- src/state/staking/hooks.ts | 3 +- src/state/staking/reducer.ts | 2 +- src/state/staking/updater.ts | 2 +- src/state/swap/hooks.ts | 4 +- src/state/transactions/actions.ts | 2 +- src/state/wallet/hooks.ts | 3 +- src/utils/StablePairMath.ts | 2 +- src/utils/calcExpectedVeMobi.ts | 3 +- src/utils/currencyId.ts | 2 +- src/utils/index.ts | 3 +- src/utils/maxAmountSpend.ts | 2 +- src/utils/prices.ts | 13 +- src/utils/stableSwapMath.ts | 3 +- src/utils/stableSwaps.ts | 3 +- src/utils/tokens.ts | 2 +- 102 files changed, 661 insertions(+), 635 deletions(-) diff --git a/src/components/CurrencyInputPanel/index.tsx b/src/components/CurrencyInputPanel/index.tsx index d5da3476b79..9e4e2344d51 100644 --- a/src/components/CurrencyInputPanel/index.tsx +++ b/src/components/CurrencyInputPanel/index.tsx @@ -1,5 +1,5 @@ -import { Pair, Token } from '@ubeswap/sdk' import { useColor } from 'hooks/useColor' +import { Token } from 'lib/token-utils' import { darken } from 'polished' import React, { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -12,7 +12,6 @@ import { useIsDarkMode } from '../../state/user/hooks' import { useTokenBalance } from '../../state/wallet/hooks' import { TYPE } from '../../theme' import CurrencyLogo from '../CurrencyLogo' -import DoubleCurrencyLogo from '../DoubleLogo' import { Input as NumericalInput } from '../NumericalInput' import { RowBetween } from '../Row' import CurrencySearchModal from '../SearchModal/CurrencySearchModal' @@ -47,7 +46,6 @@ const CurrencySelect = styled.button<{ walletConnected: boolean bgColor: any isDarkMode: boolean - pair: boolean }>` display: flex; align-items: center; @@ -64,7 +62,7 @@ const CurrencySelect = styled.button<{ cursor: pointer; user-select: none; border: none; - width: ${({ pair }) => (pair ? '14rem' : '10rem')}; + width: 10rem; height: 2.4rem; padding: 0 8px; @@ -146,7 +144,6 @@ interface CurrencyInputPanelProps { currency?: Token | null disableCurrencySelect?: boolean hideBalance?: boolean - pair?: Pair | null hideInput?: boolean disableInput?: boolean otherCurrency?: Token | null @@ -165,7 +162,6 @@ export default function CurrencyInputPanel({ disableCurrencySelect = false, hideBalance = false, disableInput = false, - pair = null, // used for double token logo hideInput = false, otherCurrency, id, @@ -217,7 +213,6 @@ export default function CurrencyInputPanel({ bgColor={tokenSelectBackground} selected={!!currency} walletConnected={connected} - pair={!!pair} className="open-currency-select-button" onClick={() => { if (!disableCurrencySelect) { @@ -226,24 +221,15 @@ export default function CurrencyInputPanel({ }} > - {pair ? ( - - ) : currency ? ( - - ) : null} - {pair ? ( - - {pair?.token0.symbol}:{pair?.token1.symbol} - - ) : ( - - {(currency && currency.symbol && currency.symbol.length > 20 - ? currency.symbol.slice(0, 4) + - '...' + - currency.symbol.slice(currency.symbol.length - 5, currency.symbol.length) - : currency?.symbol) || t('Select Token')} - - )} + {currency ? : null} + + {(currency && currency.symbol && currency.symbol.length > 20 + ? currency.symbol.slice(0, 4) + + '...' + + currency.symbol.slice(currency.symbol.length - 5, currency.symbol.length) + : currency?.symbol) || t('Select Token')} + + {!disableCurrencySelect && } diff --git a/src/components/CurrencyLogo/index.tsx b/src/components/CurrencyLogo/index.tsx index 7c71b04f0ff..3d1accbede5 100644 --- a/src/components/CurrencyLogo/index.tsx +++ b/src/components/CurrencyLogo/index.tsx @@ -1,9 +1,8 @@ -import { Token } from '@ubeswap/sdk' +import { Token } from 'lib/token-utils' import React, { useMemo } from 'react' import styled from 'styled-components' import useHttpLocations from '../../hooks/useHttpLocations' -import { WrappedTokenInfo } from '../../state/lists/hooks' import Logo from '../Logo' const StyledLogo = styled(Logo)<{ size: string }>` @@ -23,15 +22,11 @@ export default function CurrencyLogo({ size?: string style?: React.CSSProperties }) { - const uriLocations = useHttpLocations(currency instanceof WrappedTokenInfo ? currency.logoURI : undefined) + const uriLocations = useHttpLocations(currency?.icon ?? undefined) const srcs: string[] = useMemo(() => { - if (currency instanceof Token) { - if (currency instanceof WrappedTokenInfo) { - return [...uriLocations, currency.logoURI ?? currency.address] - } - - return [] + if (currency) { + return [...uriLocations, currency.icon ?? currency.address] } return [] }, [currency, uriLocations]) diff --git a/src/components/CurrencyPoolLogo/index.tsx b/src/components/CurrencyPoolLogo/index.tsx index 2f76f69dc01..25b1ba410aa 100644 --- a/src/components/CurrencyPoolLogo/index.tsx +++ b/src/components/CurrencyPoolLogo/index.tsx @@ -1,4 +1,4 @@ -import { Token } from '@ubeswap/sdk' +import { Token } from 'lib/token-utils' import React from 'react' import styled from 'styled-components' diff --git a/src/components/DoubleLogo/index.tsx b/src/components/DoubleLogo/index.tsx index 466d2a32afc..ca0152ee226 100644 --- a/src/components/DoubleLogo/index.tsx +++ b/src/components/DoubleLogo/index.tsx @@ -1,4 +1,4 @@ -import { Token } from '@ubeswap/sdk' +import { Token } from 'lib/token-utils' import React from 'react' import styled from 'styled-components' diff --git a/src/components/FormattedCurrencyAmount/index.tsx b/src/components/FormattedCurrencyAmount/index.tsx index ade4ff8f505..ba53952f838 100644 --- a/src/components/FormattedCurrencyAmount/index.tsx +++ b/src/components/FormattedCurrencyAmount/index.tsx @@ -1,4 +1,5 @@ -import { Fraction, JSBI, TokenAmount } from '@ubeswap/sdk' +import JSBI from 'jsbi' +import { Fraction, TokenAmount } from 'lib/token-utils' import React from 'react' const CURRENCY_AMOUNT_MIN = new Fraction(JSBI.BigInt(1), JSBI.BigInt(1000000)) diff --git a/src/components/Header/URLWarning.tsx b/src/components/Header/URLWarning.tsx index b1a0fc20ca8..a51e55a8d3e 100644 --- a/src/components/Header/URLWarning.tsx +++ b/src/components/Header/URLWarning.tsx @@ -1,4 +1,4 @@ -import { ChainId } from '@ubeswap/sdk' +import { ChainId } from 'lib/token-utils' import React from 'react' import { isMobile } from 'react-device-detect' import { AlertTriangle, X } from 'react-feather' diff --git a/src/components/Header/UbeBalanceContent.tsx b/src/components/Header/UbeBalanceContent.tsx index 95c0207bbd9..eeb40146a2b 100644 --- a/src/components/Header/UbeBalanceContent.tsx +++ b/src/components/Header/UbeBalanceContent.tsx @@ -1,10 +1,9 @@ import Loader from 'components/Loader' import QuestionHelper from 'components/QuestionHelper' -import { useMobi } from 'hooks/Tokens' import React from 'react' import { X } from 'react-feather' +import { useMobiPrice } from 'state/application/hooks' import styled from 'styled-components' -import { useCUSDPrice } from 'utils/useCUSDPrice' import tokenLogo from '../../assets/images/MOBI-200.png' import { CHAIN, MOBI } from '../../constants' @@ -44,8 +43,7 @@ export default function UbeBalanceContent({ setShowUbeBalanceModal }: { setShowU const ube = MOBI[CHAIN] const total = useAggregateUbeBalance() - const mobi = useMobi() - const mobiprice = useCUSDPrice(mobi) + const mobiprice = useMobiPrice() const ret = useCirculatingSupply() return ( diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 7ffbbf59ede..f01c19491f8 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,7 +1,7 @@ -import { CELO, TokenAmount } from '@ubeswap/sdk' import { CardNoise } from 'components/earn/styled' import Modal from 'components/Modal' import usePrevious from 'hooks/usePrevious' +import { TokenAmount } from 'lib/token-utils' import { darken } from 'polished' import React, { useState } from 'react' import { isMobile } from 'react-device-detect' @@ -17,6 +17,7 @@ import { CountUp } from 'use-count-up' import Logo from '../../assets/svg/mobius.svg' import { CHAIN } from '../../constants' +import { CELO } from '../../constants/tokens' import { useWeb3Context } from '../../hooks' import useTheme from '../../hooks/useTheme' import { useDarkModeManager } from '../../state/user/hooks' diff --git a/src/components/Header/useCirculatingSupply.ts b/src/components/Header/useCirculatingSupply.ts index 829f5fa5cab..033122fa28a 100644 --- a/src/components/Header/useCirculatingSupply.ts +++ b/src/components/Header/useCirculatingSupply.ts @@ -1,7 +1,8 @@ import { BigNumber } from '@ethersproject/bignumber' -import { JSBI, Percent, TokenAmount } from '@ubeswap/sdk' import { MOBI } from 'constants/tokens' import { useMobiContract } from 'hooks/useContract' +import JSBI from 'jsbi' +import { TokenAmount } from 'lib/token-utils' import { useEffect, useState } from 'react' import { useSingleContractMultipleData } from 'state/multicall/hooks' @@ -21,7 +22,7 @@ const nonCirculatingAddresses = { /** * Fetches the circulating supply */ -export const useCirculatingSupply = (): { supply: TokenAmount; staked: Percent } | undefined => { +export const useCirculatingSupply = (): { supply: TokenAmount; staked: TokenAmount } | undefined => { const mobi = MOBI[CHAIN] const mobiContract = useMobiContract() diff --git a/src/components/PoolSearchModal/CurrencyList.tsx b/src/components/PoolSearchModal/CurrencyList.tsx index 2475254904c..328f0559364 100644 --- a/src/components/PoolSearchModal/CurrencyList.tsx +++ b/src/components/PoolSearchModal/CurrencyList.tsx @@ -1,4 +1,4 @@ -import { currencyEquals, Token } from '@ubeswap/sdk' +import { Token } from 'lib/token-utils' import React, { CSSProperties, MutableRefObject, useCallback } from 'react' import { FixedSizeList } from 'react-window' import { Text } from 'rebass' @@ -121,7 +121,7 @@ export default function CurrencyList({ const Row = useCallback( ({ data, index, style }) => { const currency: Token = data[index] - const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency)) + const isSelected = Boolean(selectedCurrency && selectedCurrency.equals(currency)) const handleSelect = () => onCurrencySelect(currency) // const token = currency diff --git a/src/components/PoolSearchModal/CurrencySearch.tsx b/src/components/PoolSearchModal/CurrencySearch.tsx index 4cbd63c0974..ac5a65aea31 100644 --- a/src/components/PoolSearchModal/CurrencySearch.tsx +++ b/src/components/PoolSearchModal/CurrencySearch.tsx @@ -1,8 +1,8 @@ -import { Token } from '@ubeswap/sdk' import { StablePools } from 'constants/pools' import { useOnClickOutside } from 'hooks/useOnClickOutside' import useTheme from 'hooks/useTheme' import useToggle from 'hooks/useToggle' +import { Token } from 'lib/token-utils' import React, { useCallback, useRef } from 'react' import AutoSizer from 'react-virtualized-auto-sizer' import { FixedSizeList } from 'react-window' diff --git a/src/components/PoolSearchModal/CurrencySearchModal.tsx b/src/components/PoolSearchModal/CurrencySearchModal.tsx index b3bee60783f..8f691601744 100644 --- a/src/components/PoolSearchModal/CurrencySearchModal.tsx +++ b/src/components/PoolSearchModal/CurrencySearchModal.tsx @@ -1,4 +1,4 @@ -import { Token } from '@ubeswap/sdk' +import { Token } from 'lib/token-utils' import React, { useCallback } from 'react' import Modal from '../Modal' diff --git a/src/components/SearchModal/CurrencyList.tsx b/src/components/SearchModal/CurrencyList.tsx index 8613ce2dcac..4cfbfe947f6 100644 --- a/src/components/SearchModal/CurrencyList.tsx +++ b/src/components/SearchModal/CurrencyList.tsx @@ -1,4 +1,5 @@ -import { currencyEquals, JSBI, Token, TokenAmount } from '@ubeswap/sdk' +import JSBI from 'jsbi' +import { Token, TokenAmount } from 'lib/token-utils' import React, { CSSProperties, MutableRefObject, useCallback } from 'react' import { FixedSizeList } from 'react-window' import { Text } from 'rebass' @@ -151,8 +152,8 @@ export default function CurrencyList({ const Row = useCallback( ({ data, index, style }) => { const currency: Token = data[index] - const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency)) - const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency)) + const isSelected = Boolean(selectedCurrency && selectedCurrency.equals(currency)) + const otherSelected = Boolean(otherCurrency && otherCurrency.equals(currency)) const handleSelect = () => onCurrencySelect(currency) return ( diff --git a/src/components/SearchModal/CurrencySearch.tsx b/src/components/SearchModal/CurrencySearch.tsx index 26d1b6103c0..515066d54a0 100644 --- a/src/components/SearchModal/CurrencySearch.tsx +++ b/src/components/SearchModal/CurrencySearch.tsx @@ -1,7 +1,7 @@ -import { cUSD, Token } from '@ubeswap/sdk' import { useOnClickOutside } from 'hooks/useOnClickOutside' import useTheme from 'hooks/useTheme' import useToggle from 'hooks/useToggle' +import { Token } from 'lib/token-utils' import React, { KeyboardEvent, RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react' import ReactGA from 'react-ga' import { useTranslation } from 'react-i18next' diff --git a/src/components/SearchModal/CurrencySearchModal.tsx b/src/components/SearchModal/CurrencySearchModal.tsx index 016f8c40684..477948765cf 100644 --- a/src/components/SearchModal/CurrencySearchModal.tsx +++ b/src/components/SearchModal/CurrencySearchModal.tsx @@ -1,4 +1,4 @@ -import { Token } from '@ubeswap/sdk' +import { Token } from 'lib/token-utils' import React, { useCallback, useEffect, useState } from 'react' import { useLocation } from 'react-router' diff --git a/src/components/SearchModal/filtering.ts b/src/components/SearchModal/filtering.ts index e1af52a0e91..a6838f9ba5d 100644 --- a/src/components/SearchModal/filtering.ts +++ b/src/components/SearchModal/filtering.ts @@ -1,4 +1,4 @@ -import { Token } from '@ubeswap/sdk' +import { Token } from 'lib/token-utils' import { isAddress } from '../../utils' diff --git a/src/components/SearchModal/sorting.ts b/src/components/SearchModal/sorting.ts index bb45f8668fd..48f34e670ef 100644 --- a/src/components/SearchModal/sorting.ts +++ b/src/components/SearchModal/sorting.ts @@ -1,4 +1,4 @@ -import { Token, TokenAmount } from '@ubeswap/sdk' +import { Token, TokenAmount } from 'lib/token-utils' import { useMemo } from 'react' import { useAllTokenBalances } from '../../state/wallet/hooks' diff --git a/src/components/TransactionConfirmationModal/index.tsx b/src/components/TransactionConfirmationModal/index.tsx index f652d6ebe55..5ccdeca670f 100644 --- a/src/components/TransactionConfirmationModal/index.tsx +++ b/src/components/TransactionConfirmationModal/index.tsx @@ -1,4 +1,4 @@ -import { ChainId } from '@ubeswap/sdk' +import { ChainId } from 'lib/token-utils' import React, { useContext } from 'react' import { AlertTriangle, ArrowUpCircle } from 'react-feather' import { Text } from 'rebass' diff --git a/src/components/earn/ClaimExternalRewardsModal.tsx b/src/components/earn/ClaimExternalRewardsModal.tsx index edce65f6ef9..949e945ef97 100644 --- a/src/components/earn/ClaimExternalRewardsModal.tsx +++ b/src/components/earn/ClaimExternalRewardsModal.tsx @@ -1,6 +1,6 @@ import { TransactionResponse } from '@ethersproject/providers' -import { TokenAmount } from '@ubeswap/sdk' import { useMobi } from 'hooks/Tokens' +import { TokenAmount } from 'lib/token-utils' import React, { useEffect, useState } from 'react' import { useBlockNumber } from 'state/application/hooks' import { StablePoolInfo, useExternalRewards } from 'state/stablePools/hooks' diff --git a/src/components/earn/ClaimRewardModal.tsx b/src/components/earn/ClaimRewardModal.tsx index 255cea03c84..d4bd6e4deec 100644 --- a/src/components/earn/ClaimRewardModal.tsx +++ b/src/components/earn/ClaimRewardModal.tsx @@ -1,6 +1,6 @@ import { TransactionResponse } from '@ethersproject/providers' -import { TokenAmount } from '@ubeswap/sdk' import { useMobi } from 'hooks/Tokens' +import { TokenAmount } from 'lib/token-utils' import React, { useEffect, useState } from 'react' import { useBlockNumber } from 'state/application/hooks' import { StablePoolInfo } from 'state/stablePools/hooks' diff --git a/src/components/earn/DepositModal.tsx b/src/components/earn/DepositModal.tsx index 155d5f55544..11d04867b55 100644 --- a/src/components/earn/DepositModal.tsx +++ b/src/components/earn/DepositModal.tsx @@ -1,6 +1,7 @@ import { TransactionResponse } from '@ethersproject/providers' -import { JSBI, TokenAmount } from '@ubeswap/sdk' import CurrencyLogo from 'components/CurrencyLogo' +import JSBI from 'jsbi' +import { TokenAmount } from 'lib/token-utils' import React, { useState } from 'react' import { tryParseAmount } from 'state/swap/hooks' import styled from 'styled-components' diff --git a/src/components/earn/StablePoolCard.tsx b/src/components/earn/StablePoolCard.tsx index 1768806560e..04abeada330 100644 --- a/src/components/earn/StablePoolCard.tsx +++ b/src/components/earn/StablePoolCard.tsx @@ -1,9 +1,10 @@ -import { cUSD, Fraction, JSBI, Percent, Price, TokenAmount } from '@ubeswap/sdk' import Loader from 'components/Loader' import QuestionHelper from 'components/QuestionHelper' import { ChainLogo, Coins } from 'constants/StablePools' import { useWeb3Context } from 'hooks' import { useMobi } from 'hooks/Tokens' +import JSBI from 'jsbi' +import { Fraction, Percent, Price, TokenAmount } from 'lib/token-utils' import { darken } from 'polished' import React, { useState } from 'react' import { isMobile } from 'react-device-detect' diff --git a/src/components/earn/StakingModal.tsx b/src/components/earn/StakingModal.tsx index 9a4a31a7c18..c179bc21f76 100644 --- a/src/components/earn/StakingModal.tsx +++ b/src/components/earn/StakingModal.tsx @@ -1,7 +1,7 @@ import { TransactionResponse } from '@ethersproject/providers' -import { JSBI, Token, TokenAmount } from '@ubeswap/sdk' import Loader from 'components/Loader' import { useMobi } from 'hooks/Tokens' +import { JSBI, Token, TokenAmount } from 'lib/token-utils' import React, { useCallback, useState } from 'react' import { StablePoolInfo } from 'state/stablePools/hooks' import styled from 'styled-components' diff --git a/src/components/earn/UnstakingModal.tsx b/src/components/earn/UnstakingModal.tsx index dad85d4aca7..8da7603e222 100644 --- a/src/components/earn/UnstakingModal.tsx +++ b/src/components/earn/UnstakingModal.tsx @@ -1,6 +1,6 @@ import { TransactionResponse } from '@ethersproject/providers' -import { TokenAmount } from '@ubeswap/sdk' import { useMobi } from 'hooks/Tokens' +import { TokenAmount } from 'lib/token-utils' import React, { useState } from 'react' import { StablePoolInfo } from 'state/stablePools/hooks' import styled from 'styled-components' diff --git a/src/components/earn/WithdrawLP.tsx b/src/components/earn/WithdrawLP.tsx index 98c8f2d966e..e581dcfe30f 100644 --- a/src/components/earn/WithdrawLP.tsx +++ b/src/components/earn/WithdrawLP.tsx @@ -1,6 +1,7 @@ import { TransactionResponse } from '@ethersproject/providers' -import { JSBI, Token, TokenAmount } from '@ubeswap/sdk' import CurrencyLogo from 'components/CurrencyLogo' +import JSBI from 'jsbi' +import { Token, TokenAmount } from 'lib/token-utils' import React, { useState } from 'react' import styled from 'styled-components' diff --git a/src/components/earn/WithdrawTokens.tsx b/src/components/earn/WithdrawTokens.tsx index 9e5be76de1d..a37c94cb228 100644 --- a/src/components/earn/WithdrawTokens.tsx +++ b/src/components/earn/WithdrawTokens.tsx @@ -1,6 +1,7 @@ import { TransactionResponse } from '@ethersproject/providers' -import { JSBI, TokenAmount } from '@ubeswap/sdk' import CurrencyLogo from 'components/CurrencyLogo' +import JSBI from 'jsbi' +import { TokenAmount } from 'lib/token-utils' import React, { useState } from 'react' import styled from 'styled-components' diff --git a/src/components/swap/ConfirmSwapModal.tsx b/src/components/swap/ConfirmSwapModal.tsx index c25dbddacb8..ccfdd2668ab 100644 --- a/src/components/swap/ConfirmSwapModal.tsx +++ b/src/components/swap/ConfirmSwapModal.tsx @@ -1,4 +1,3 @@ -import { currencyEquals } from '@ubeswap/sdk' import React, { useCallback, useMemo } from 'react' import { useLocation } from 'react-router' import { MentoTrade } from 'state/mento/hooks' @@ -19,9 +18,9 @@ import SwapModalHeader from './SwapModalHeader' */ function tradeMeaningfullyDiffers(tradeA: MobiusTrade | MentoTrade, tradeB: MobiusTrade | MentoTrade): boolean { return ( - !currencyEquals(tradeA.input.currency, tradeB.input.currency) || + !tradeA.input.token.equals(tradeB.input.token) || !tradeA.input.equalTo(tradeB.input) || - !currencyEquals(tradeA.output.currency, tradeB.output.currency) || + !tradeA.output.token.equals(tradeB.output.token) || !tradeA.output.equalTo(tradeB.output) ) } diff --git a/src/components/swap/FormattedPriceImpact.tsx b/src/components/swap/FormattedPriceImpact.tsx index 02b539eb6d0..095b8b48104 100644 --- a/src/components/swap/FormattedPriceImpact.tsx +++ b/src/components/swap/FormattedPriceImpact.tsx @@ -1,4 +1,4 @@ -import { Percent } from '@ubeswap/sdk' +import { Percent } from 'lib/token-utils' import React from 'react' import { ONE_BIPS } from '../../constants' diff --git a/src/components/swap/TradePrice.tsx b/src/components/swap/TradePrice.tsx index 1d5a768bd2d..14b07de02cc 100644 --- a/src/components/swap/TradePrice.tsx +++ b/src/components/swap/TradePrice.tsx @@ -1,4 +1,4 @@ -import { Price } from '@ubeswap/sdk' +import { Price } from 'lib/token-utils' import React, { useContext } from 'react' import { Repeat } from 'react-feather' import { Text } from 'rebass' diff --git a/src/connectors/index.ts b/src/connectors/index.ts index a5f3f2e0677..55aa9294c5c 100644 --- a/src/connectors/index.ts +++ b/src/connectors/index.ts @@ -1,4 +1,5 @@ -import { ChainId, parseNetwork } from '@ubeswap/sdk' +import { parseNetwork } from '@ubeswap/sdk' +import { ChainId } from 'lib/token-utils' const networkChainIDFromHostname: ChainId = window.location.hostname.includes('alfajores') ? ChainId.ALFAJORES diff --git a/src/connectors/ledger/LedgerConnector.tsx b/src/connectors/ledger/LedgerConnector.tsx index a5d192fb227..306153ba9d5 100644 --- a/src/connectors/ledger/LedgerConnector.tsx +++ b/src/connectors/ledger/LedgerConnector.tsx @@ -4,10 +4,11 @@ import { ContractKit, newKit } from '@celo/contractkit' import { AddressValidation, LedgerWallet, newLedgerWalletWithSetup } from '@celo/wallet-ledger' import TransportWebUSB from '@ledgerhq/hw-transport-webusb' -import { CHAIN_INFO, ChainId } from '@ubeswap/sdk' +import { CHAIN_INFO } from '@ubeswap/sdk' import { AbstractConnector } from '@web3-react/abstract-connector' import { ConnectorUpdate } from '@web3-react/types' import LedgerConnectorModal from 'components/WalletModal/LedgerWalletSelector' +import { ChainId } from 'lib/token-utils' import React from 'react' import * as ReactDOM from 'react-dom' import { EventController } from 'utils/EventController' diff --git a/src/constants/ConstantSum.ts b/src/constants/ConstantSum.ts index b37f51f4e90..072451ebfdb 100644 --- a/src/constants/ConstantSum.ts +++ b/src/constants/ConstantSum.ts @@ -1,4 +1,4 @@ -import { ChainId } from '@ubeswap/sdk' +import { ChainId } from 'lib/token-utils' import { WrappedTokenInfo } from 'state/lists/hooks' export type ConstantSumInfo = { diff --git a/src/constants/NetworkInfo.ts b/src/constants/NetworkInfo.ts index 8ec0ca9ce67..41e4816757d 100644 --- a/src/constants/NetworkInfo.ts +++ b/src/constants/NetworkInfo.ts @@ -1,4 +1,4 @@ -import { ChainId } from '@ubeswap/sdk' +import { ChainId } from 'lib/token-utils' export function getExplorerLink( chainId: ChainId, diff --git a/src/constants/StablePools.ts b/src/constants/StablePools.ts index 07f7e5071f9..263f5da52bf 100644 --- a/src/constants/StablePools.ts +++ b/src/constants/StablePools.ts @@ -1,5 +1,6 @@ -import { ChainId, JSBI, Token } from '@ubeswap/sdk' import BigNumber from 'bignumber.js' +import JSBI from 'jsbi' +import { ChainId, Token } from 'lib/token-utils' import { VestType } from 'state/claim/reducer' import { WrappedTokenInfo } from 'state/lists/hooks' diff --git a/src/constants/index.ts b/src/constants/index.ts index e28e9aec38b..b0fe4add792 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -1,4 +1,5 @@ -import { ChainId, JSBI, Percent, Token } from '@ubeswap/sdk' +import JSBI from 'jsbi' +import { ChainId, Percent, Token } from 'lib/token-utils' export { MOBI } from './tokens' diff --git a/src/constants/multicall/index.ts b/src/constants/multicall/index.ts index 83076eb0d6b..0c8d04a2f98 100644 --- a/src/constants/multicall/index.ts +++ b/src/constants/multicall/index.ts @@ -1,4 +1,4 @@ -import { ChainId } from '@ubeswap/sdk' +import { ChainId } from 'lib/token-utils' import MULTICALL_ABI from './abi.json' diff --git a/src/data/Allowances.ts b/src/data/Allowances.ts index fed9d652294..3b5e74f5e56 100644 --- a/src/data/Allowances.ts +++ b/src/data/Allowances.ts @@ -1,5 +1,5 @@ -import { Token, TokenAmount } from '@ubeswap/sdk' import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp' +import { Token, TokenAmount } from 'lib/token-utils' import { useEffect, useMemo, useState } from 'react' import { useBlockNumber } from 'state/application/hooks' diff --git a/src/data/TotalSupply.ts b/src/data/TotalSupply.ts index 6ec319f636c..5cdae3ea294 100644 --- a/src/data/TotalSupply.ts +++ b/src/data/TotalSupply.ts @@ -1,5 +1,5 @@ import { BigNumber } from '@ethersproject/bignumber' -import { Token, TokenAmount } from '@ubeswap/sdk' +import { Token, TokenAmount } from 'lib/token-utils' import { useTokenContract } from '../hooks/useContract' import { useSingleCallResult } from '../state/multicall/hooks' diff --git a/src/hooks/Tokens.ts b/src/hooks/Tokens.ts index 7a07e9cca31..37bf5492afd 100644 --- a/src/hooks/Tokens.ts +++ b/src/hooks/Tokens.ts @@ -1,6 +1,6 @@ -import { Token } from '@ubeswap/sdk' import { MENTO_POOL_INFO } from 'constants/mento' import { IExchange, StablePools } from 'constants/pools' +import { Token } from 'lib/token-utils' import { stableToToken } from 'state/mentoPools/hooks' import { dedupeTokens } from 'utils/tokens' diff --git a/src/hooks/useApproveCallback.ts b/src/hooks/useApproveCallback.ts index a32770667f1..6f9ff2a214d 100644 --- a/src/hooks/useApproveCallback.ts +++ b/src/hooks/useApproveCallback.ts @@ -1,5 +1,5 @@ import { MaxUint256 } from '@ethersproject/constants' -import { TokenAmount } from '@ubeswap/sdk' +import { TokenAmount } from 'lib/token-utils' import { useCallback, useMemo } from 'react' import { MobiusTrade } from 'state/swap/hooks' import { useUserMinApprove } from 'state/user/hooks' diff --git a/src/hooks/useColor.ts b/src/hooks/useColor.ts index 45a7a0e6552..3c93a170b7f 100644 --- a/src/hooks/useColor.ts +++ b/src/hooks/useColor.ts @@ -1,6 +1,6 @@ -import { ChainId, Token } from '@ubeswap/sdk' import { DisplayPool } from 'constants/pools' import { Coins, STATIC_POOL_INFO } from 'constants/StablePools' +import { ChainId, Token } from 'lib/token-utils' import Vibrant from 'node-vibrant' import { shade } from 'polished' import { useLayoutEffect, useState } from 'react' diff --git a/src/hooks/useExternalStakingRewards.ts b/src/hooks/useExternalStakingRewards.ts index 2e402771cc4..19c1d2cda4e 100644 --- a/src/hooks/useExternalStakingRewards.ts +++ b/src/hooks/useExternalStakingRewards.ts @@ -1,6 +1,7 @@ -import { JSBI, Percent, TokenAmount } from '@ubeswap/sdk' import { calcApy } from 'components/earn/StablePoolCard' import { ExternalRewardsToken } from 'constants/staking' +import JSBI from 'jsbi' +import { Percent, TokenAmount } from 'lib/token-utils' import { useTokenPrice } from 'state/application/hooks' import { useStakingState, useStakingStateCombined } from 'state/staking/hooks' diff --git a/src/hooks/useMentoCallback.ts b/src/hooks/useMentoCallback.ts index 6275b2951a8..6539e9ddcc7 100644 --- a/src/hooks/useMentoCallback.ts +++ b/src/hooks/useMentoCallback.ts @@ -1,7 +1,8 @@ import { BigNumber } from '@ethersproject/bignumber' import { Contract } from '@ethersproject/contracts' -import { JSBI, SwapParameters } from '@ubeswap/sdk' +import { SwapParameters } from '@ubeswap/sdk' import { ContractTransaction } from 'ethers' +import JSBI from 'jsbi' import { useMemo } from 'react' import { BIPS_BASE, CHAIN, INITIAL_ALLOWED_SLIPPAGE } from '../constants' diff --git a/src/hooks/useSwapCallback.ts b/src/hooks/useSwapCallback.ts index f295dcc6eb2..1beeabbc761 100644 --- a/src/hooks/useSwapCallback.ts +++ b/src/hooks/useSwapCallback.ts @@ -1,7 +1,8 @@ import { BigNumber } from '@ethersproject/bignumber' import { Contract } from '@ethersproject/contracts' -import { JSBI, SwapParameters } from '@ubeswap/sdk' +import { SwapParameters } from '@ubeswap/sdk' import { ContractTransaction } from 'ethers' +import JSBI from 'jsbi' import { useMemo } from 'react' import isZero from 'utils/isZero' diff --git a/src/lib/mentoCalculator/amounts.ts b/src/lib/mentoCalculator/amounts.ts index 4e09d5e3ae0..b6f65b1da87 100644 --- a/src/lib/mentoCalculator/amounts.ts +++ b/src/lib/mentoCalculator/amounts.ts @@ -1,5 +1,5 @@ -import { TokenAmount } from '@ubeswap/sdk' import JSBI from 'jsbi' +import { TokenAmount } from 'lib/token-utils' import { BIPS_BASE } from '../../constants' import type { IMentoExchangeInfo } from '../../constants/mento' diff --git a/src/lib/mentoCalculator/price.ts b/src/lib/mentoCalculator/price.ts index 0a2f76d1e8d..848dec5ae65 100644 --- a/src/lib/mentoCalculator/price.ts +++ b/src/lib/mentoCalculator/price.ts @@ -1,4 +1,4 @@ -import { Price } from '@ubeswap/sdk' +import { Price } from 'lib/token-utils' import type { IMentoExchangeInfo } from '../../constants/mento' diff --git a/src/lib/token-utils/index.ts b/src/lib/token-utils/index.ts index fe636675f14..7f55ba73836 100644 --- a/src/lib/token-utils/index.ts +++ b/src/lib/token-utils/index.ts @@ -1,6 +1,8 @@ export * from './price' +export * from './splTokenRegistry' export * from './token' export * from './tokenAmount' +export * from './tokenList' // re-export token-math types // so consumers don't need to use them diff --git a/src/lib/token-utils/splTokenRegistry.ts b/src/lib/token-utils/splTokenRegistry.ts index d720e09e0e9..8e1fb046271 100644 --- a/src/lib/token-utils/splTokenRegistry.ts +++ b/src/lib/token-utils/splTokenRegistry.ts @@ -1,4 +1,4 @@ -import { ChainId } from '@ubeswap/sdk' +import { ChainId } from './' /** * These types all come from the @solana/spl-token-registry package. * @@ -20,26 +20,26 @@ export interface Network { chainId: ChainId } -export declare const Alfajores: { - readonly name: NetworkNames.Alfajores - readonly rpcUrl: 'https://alfajores-forno.celo-testnet.org' - readonly graphQl: 'https://alfajores-blockscout.celo-testnet.org/graphiql' - readonly explorer: 'https://alfajores-blockscout.celo-testnet.org' - readonly chainId: ChainId.ALFAJORES +export const Alfajores: Network = { + name: NetworkNames.Alfajores, + rpcUrl: 'https://alfajores-forno.celo-testnet.org', + graphQl: 'https://alfajores-blockscout.celo-testnet.org/graphiql', + explorer: 'https://alfajores-blockscout.celo-testnet.org', + chainId: ChainId.ALFAJORES, } -export declare const Baklava: { - readonly name: NetworkNames.Baklava - readonly rpcUrl: 'https://baklava-forno.celo-testnet.org' - readonly graphQl: 'https://baklava-blockscout.celo-testnet.org/graphiql' - readonly explorer: 'https://baklava-blockscout.celo-testnet.org' - readonly chainId: ChainId.BAKLAVA +export const Baklava: Network = { + name: NetworkNames.Baklava, + rpcUrl: 'https://baklava-forno.celo-testnet.org', + graphQl: 'https://baklava-blockscout.celo-testnet.org/graphiql', + explorer: 'https://baklava-blockscout.celo-testnet.org', + chainId: ChainId.BAKLAVA, } -export declare const Mainnet: { - readonly name: NetworkNames.Mainnet - readonly rpcUrl: 'https://forno.celo.org' - readonly graphQl: 'https://explorer.celo.org/graphiql' - readonly explorer: 'https://explorer.celo.org' - readonly chainId: ChainId.MAINNET +export const Mainnet: Network = { + name: NetworkNames.Mainnet, + rpcUrl: 'https://forno.celo.org', + graphQl: 'https://explorer.celo.org/graphiql', + explorer: 'https://explorer.celo.org', + chainId: ChainId.MAINNET, } /** diff --git a/src/lib/token-utils/token.ts b/src/lib/token-utils/token.ts index e9eea59924c..4c79f6577bd 100644 --- a/src/lib/token-utils/token.ts +++ b/src/lib/token-utils/token.ts @@ -1,7 +1,6 @@ -import { ChainId } from '@ubeswap/sdk' import type { Token as UToken } from '@ubeswap/token-math' -import { Alfajores, Baklava, Mainnet, Network } from './splTokenRegistry' +import { Alfajores, Baklava, ChainId, Mainnet, Network } from './' import type { TokenInfo } from './tokenList' /** diff --git a/src/pages/CreateProposal/ProposalActionDetail.tsx b/src/pages/CreateProposal/ProposalActionDetail.tsx index 5471bbc5487..2745320d34a 100644 --- a/src/pages/CreateProposal/ProposalActionDetail.tsx +++ b/src/pages/CreateProposal/ProposalActionDetail.tsx @@ -1,6 +1,6 @@ -import { Token } from '@ubeswap/sdk' import AddressInputPanel from 'components/AddressInputPanel' import CurrencyInputPanel from 'components/CurrencyInputPanel' +import { Token } from 'lib/token-utils' import React from 'react' import styled from 'styled-components/macro' diff --git a/src/pages/CreateProposal/index.tsx b/src/pages/CreateProposal/index.tsx index 331a57a7b19..b85fe1f90ee 100644 --- a/src/pages/CreateProposal/index.tsx +++ b/src/pages/CreateProposal/index.tsx @@ -1,12 +1,12 @@ import { defaultAbiCoder } from '@ethersproject/abi' import { getAddress, isAddress } from '@ethersproject/address' -import { Token, TokenAmount } from '@ubeswap/sdk' import { ButtonError } from 'components/Button' import { BlueCard } from 'components/Card' import { AutoColumn } from 'components/Column' import { GAUGE_CONTROLLER, GAUGE_PROXY } from 'constants/StablePools' import { useWeb3Context } from 'hooks' import JSBI from 'jsbi' +import { Token, TokenAmount } from 'lib/token-utils' import AppBody from 'pages/AppBody' import { Wrapper } from 'pages/Pool/styleds' import React, { useCallback, useMemo, useState } from 'react' diff --git a/src/pages/Mento/index.tsx b/src/pages/Mento/index.tsx index 3debc3224aa..0b5bd4f2bf1 100644 --- a/src/pages/Mento/index.tsx +++ b/src/pages/Mento/index.tsx @@ -1,6 +1,7 @@ -import { JSBI, TokenAmount } from '@ubeswap/sdk' import { describeTrade } from 'components/swap/routing/describeTrade' import { useMentoTradeCallback } from 'components/swap/routing/useMentoTradeCallback' +import JSBI from 'jsbi' +import { TokenAmount } from 'lib/token-utils' import React, { useCallback, useContext, useEffect, useState } from 'react' import { isMobile } from 'react-device-detect' import { ArrowDown } from 'react-feather' diff --git a/src/pages/OpenSum/index.tsx b/src/pages/OpenSum/index.tsx index 3bd63c7799f..d7b8555fa62 100644 --- a/src/pages/OpenSum/index.tsx +++ b/src/pages/OpenSum/index.tsx @@ -1,6 +1,6 @@ -import { Token, TokenAmount } from '@ubeswap/sdk' import { useConstantSumContract } from 'hooks/useContract' import useTransactionDeadline from 'hooks/useTransactionDeadline' +import { Token, TokenAmount } from 'lib/token-utils' import React, { useCallback, useContext, useEffect, useState } from 'react' import { isMobile } from 'react-device-detect' import { ArrowDown } from 'react-feather' diff --git a/src/pages/Pool/Manage.tsx b/src/pages/Pool/Manage.tsx index 8b4f0e8b80d..2584bfd227d 100644 --- a/src/pages/Pool/Manage.tsx +++ b/src/pages/Pool/Manage.tsx @@ -1,9 +1,10 @@ -import { Fraction, JSBI, TokenAmount } from '@ubeswap/sdk' import CurrencyPoolLogo from 'components/CurrencyPoolLogo' import ExternalRewardsModal from 'components/earn/ClaimExternalRewardsModal' import Loader from 'components/Loader' import QuestionHelper from 'components/QuestionHelper' import { useMobi } from 'hooks/Tokens' +import JSBI from 'jsbi' +import { Fraction, JSBI, TokenAmount } from 'lib/token-utils' import React, { useCallback, useState } from 'react' import { Link, RouteComponentProps } from 'react-router-dom' import { useExternalRewards, useStablePoolInfoByName } from 'state/stablePools/hooks' diff --git a/src/pages/Pool/index.tsx b/src/pages/Pool/index.tsx index c13a226b40a..742ab8393c6 100644 --- a/src/pages/Pool/index.tsx +++ b/src/pages/Pool/index.tsx @@ -1,9 +1,10 @@ import { ErrorBoundary } from '@sentry/react' -import { JSBI, TokenAmount } from '@ubeswap/sdk' import QuestionHelper from 'components/QuestionHelper' import { RowFixed } from 'components/Row' import { Chain, Coins, PRICE } from 'constants/StablePools' import { CUSD } from 'constants/tokens' +import JSBI from 'jsbi' +import { TokenAmount } from 'lib/token-utils' import React from 'react' import { isMobile } from 'react-device-detect' import { useMobiPrice } from 'state/application/hooks' diff --git a/src/pages/Staking/CalcBoost.tsx b/src/pages/Staking/CalcBoost.tsx index ccba435cde1..37e46cab2c1 100644 --- a/src/pages/Staking/CalcBoost.tsx +++ b/src/pages/Staking/CalcBoost.tsx @@ -1,4 +1,3 @@ -import { JSBI, TokenAmount } from '@ubeswap/sdk' import { AutoColumn } from 'components/Column' import QuestionHelper from 'components/QuestionHelper' import { RowBetween } from 'components/Row' @@ -6,6 +5,8 @@ import { DisplayPool, StablePools } from 'constants/pools' import { useVeMobi } from 'hooks/Tokens' import { useColor } from 'hooks/useColor' import useTheme from 'hooks/useTheme' +import JSBI from 'jsbi' +import { TokenAmount } from 'lib/token-utils' import { darken } from 'polished' import React, { useCallback, useState } from 'react' import { GaugeInfo, UserGaugeInfo } from 'state/gauges/hooks' diff --git a/src/pages/Staking/GaugeWeights.tsx b/src/pages/Staking/GaugeWeights.tsx index a021384556f..acdf20bb3a8 100644 --- a/src/pages/Staking/GaugeWeights.tsx +++ b/src/pages/Staking/GaugeWeights.tsx @@ -1,9 +1,9 @@ -import { JSBI } from '@ubeswap/sdk' import { AutoColumn } from 'components/Column' import Loader from 'components/Loader' import { AutoRow, RowBetween, RowFixed } from 'components/Row' import { StablePools } from 'constants/pools' import { useWindowSize } from 'hooks/useWindowSize' +import JSBI from 'jsbi' import { darken } from 'polished' import React from 'react' import { isMobile } from 'react-device-detect' diff --git a/src/pages/Staking/Lock/IncreaseLockAmount.tsx b/src/pages/Staking/Lock/IncreaseLockAmount.tsx index 4a37b061a58..dbca61cf772 100644 --- a/src/pages/Staking/Lock/IncreaseLockAmount.tsx +++ b/src/pages/Staking/Lock/IncreaseLockAmount.tsx @@ -1,13 +1,14 @@ import 'react-date-range/dist/styles.css' // main style file import 'react-date-range/dist/theme/default.css' // theme css file -import { JSBI, Token, TokenAmount } from '@ubeswap/sdk' import CurrencyLogo from 'components/CurrencyLogo' import Loader from 'components/Loader' import { AutoRow, RowBetween } from 'components/Row' import { DisplayPool } from 'constants/pools' import { useMobi } from 'hooks/Tokens' import { useDoTransaction } from 'hooks/useDoTransaction' +import JSBI from 'jsbi' +import { Token, TokenAmount } from 'lib/token-utils' import React, { useState } from 'react' import { Text } from 'rebass' import { useTokenBalance } from 'state/wallet/hooks' diff --git a/src/pages/Staking/Lock/Lock.tsx b/src/pages/Staking/Lock/Lock.tsx index fa75914c0e4..e8a0292f1e5 100644 --- a/src/pages/Staking/Lock/Lock.tsx +++ b/src/pages/Staking/Lock/Lock.tsx @@ -1,13 +1,14 @@ import 'react-date-range/dist/styles.css' // main style file import 'react-date-range/dist/theme/default.css' // theme css file -import { JSBI, Token, TokenAmount } from '@ubeswap/sdk' import CurrencyLogo from 'components/CurrencyLogo' import Loader from 'components/Loader' import { AutoRow, RowBetween } from 'components/Row' import { StablePools } from 'constants/pools' import { useMobi } from 'hooks/Tokens' import { useDoTransaction } from 'hooks/useDoTransaction' +import JSBI from 'jsbi' +import { Token, TokenAmount } from 'lib/token-utils' import React, { useState } from 'react' import { Calendar } from 'react-date-range' import { Text } from 'rebass' diff --git a/src/pages/Staking/Positions.tsx b/src/pages/Staking/Positions.tsx index bd3e5ca2ae8..39b6922a623 100644 --- a/src/pages/Staking/Positions.tsx +++ b/src/pages/Staking/Positions.tsx @@ -1,4 +1,3 @@ -import { JSBI, TokenAmount } from '@ubeswap/sdk' import { ButtonPrimary } from 'components/Button' import { AutoColumn } from 'components/Column' import { CardNoise } from 'components/earn/styled' @@ -7,6 +6,8 @@ import { DisplayPool, IGauge, StablePools } from 'constants/pools' import { ChainLogo } from 'constants/StablePools' import { CUSD } from 'constants/tokens' import { usePoolColor } from 'hooks/useColor' +import JSBI from 'jsbi' +import { TokenAmount } from 'lib/token-utils' import React, { useState } from 'react' import { isMobile } from 'react-device-detect' import { ChevronDown, ChevronUp } from 'react-feather' diff --git a/src/pages/Staking/index.tsx b/src/pages/Staking/index.tsx index fe0f20eef8d..12aaf7225aa 100644 --- a/src/pages/Staking/index.tsx +++ b/src/pages/Staking/index.tsx @@ -1,5 +1,5 @@ -import { TokenAmount } from '@ubeswap/sdk' import { useMobi } from 'hooks/Tokens' +import { TokenAmount } from 'lib/token-utils' import React from 'react' import { isMobile } from 'react-device-detect' import { useAllGaugesInfo, useAllUserGaugesInfo, UserGaugeInfo } from 'state/gauges/hooks' diff --git a/src/pages/Swap/index.tsx b/src/pages/Swap/index.tsx index f071de98315..70c8c58820e 100644 --- a/src/pages/Swap/index.tsx +++ b/src/pages/Swap/index.tsx @@ -1,11 +1,12 @@ -import { TokenAmount } from '@ubeswap/sdk' import { describeTrade } from 'components/swap/routing/describeTrade' import { useTradeCallback } from 'components/swap/routing/useTradeCallback' +import { TokenAmount } from 'lib/token-utils' import React, { useCallback, useContext, useEffect, useState } from 'react' import { isMobile } from 'react-device-detect' import { ArrowDown } from 'react-feather' import ReactGA from 'react-ga' import { Text } from 'rebass' +import { poolInfoToExchange } from 'state/mobiusPools/hooks' import { ThemeContext } from 'styled-components' import invariant from 'tiny-invariant' @@ -46,14 +47,7 @@ export default function Swap() { // swap state const { independentField, typedValue } = useSwapState() - const { - v2Trade, - currencyBalances, - parsedAmount, - currencies, - inputError: swapInputError, - priceImpact, - } = useMobiusTradeInfo() + const { v2Trade, currencyBalances, parsedAmount, currencies, inputError: swapInputError } = useMobiusTradeInfo() const trade = v2Trade @@ -100,7 +94,10 @@ export default function Swap() { } // check whether the user has approved the router on the input token - const [approval, approveCallback] = useApproveCallback(trade?.input, trade?.pool.address) + const [approval, approveCallback] = useApproveCallback( + trade?.input, + trade?.pool ? poolInfoToExchange(trade?.pool).address : undefined + ) // check if user has gone through approval process, used to show two step buttons, reset on token change const [approvalSubmitted, setApprovalSubmitted] = useState(false) @@ -128,7 +125,7 @@ export default function Swap() { ReactGA.event({ category: 'Swap', action: 'Swap', - label: [trade?.input?.currency?.symbol, trade?.output?.currency?.symbol].join('/'), + label: [trade?.input?.token.symbol, trade?.output?.token.symbol].join('/'), }) }) .catch((error) => { @@ -146,7 +143,7 @@ export default function Swap() { const [showInverted, setShowInverted] = useState(false) // warnings on slippage - const priceImpactSeverity = warningSeverity(priceImpact) + const priceImpactSeverity = warningSeverity(v2Trade?.priceImpact) // show approve flow when: no error on inputs, not approved or pending, or approved in current session // never show if price impact is above threshold in non expert mode diff --git a/src/pages/Vote/VotePage.tsx b/src/pages/Vote/VotePage.tsx index 991b1ed140d..974473d1aa8 100644 --- a/src/pages/Vote/VotePage.tsx +++ b/src/pages/Vote/VotePage.tsx @@ -1,9 +1,9 @@ import { BigNumber } from '@ethersproject/bignumber' -// eslint-disable-next-line no-restricted-imports -import { TokenAmount } from '@ubeswap/sdk' import { CardNoise } from 'components/claim/styled' import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp' import JSBI from 'jsbi' +// eslint-disable-next-line no-restricted-imports +import { TokenAmount } from 'lib/token-utils' import { DateTime } from 'luxon/src/luxon' import React, { useState } from 'react' import { ArrowLeft } from 'react-feather' diff --git a/src/pages/Vote/index.tsx b/src/pages/Vote/index.tsx index 03eed2de656..b6b5814b5b5 100644 --- a/src/pages/Vote/index.tsx +++ b/src/pages/Vote/index.tsx @@ -1,4 +1,3 @@ -import { TokenAmount } from '@ubeswap/sdk' import { ButtonPrimary } from 'components/Button' import { CardNoise } from 'components/claim/styled' import { AutoColumn } from 'components/Column' @@ -8,6 +7,7 @@ import Loader from 'components/Loader' import { AutoRow, RowBetween } from 'components/Row' import ProposalEmptyState from 'components/vote/ProposalEmptyState' import { useWeb3Context } from 'hooks' +import { TokenAmount } from 'lib/token-utils' import { darken } from 'polished' import React from 'react' import { Link } from 'react-router-dom' diff --git a/src/state/application/hooks.ts b/src/state/application/hooks.ts index ee61a99c405..aa0967ab91f 100644 --- a/src/state/application/hooks.ts +++ b/src/state/application/hooks.ts @@ -1,7 +1,7 @@ import { ApolloClient, NormalizedCacheObject } from '@apollo/client' -import { Fraction } from '@ubeswap/sdk' import { useWeb3Context } from 'hooks' import { useMobi } from 'hooks/Tokens' +import { Fraction } from 'lib/token-utils' import { useCallback, useMemo } from 'react' import { useDispatch, useSelector } from 'react-redux' diff --git a/src/state/claim/hooks.ts b/src/state/claim/hooks.ts index 382caa6471e..65d99369901 100644 --- a/src/state/claim/hooks.ts +++ b/src/state/claim/hooks.ts @@ -1,5 +1,5 @@ // To-Do: Implement Hooks to update Client-Side contract representation -import { JSBI } from '@ubeswap/sdk' +import JSBI from 'jsbi' import { useSelector } from 'react-redux' import { AppState } from '..' diff --git a/src/state/claim/updater.ts b/src/state/claim/updater.ts index 5d455f4432e..1437ca1b43d 100644 --- a/src/state/claim/updater.ts +++ b/src/state/claim/updater.ts @@ -1,4 +1,4 @@ -import { JSBI } from '@ubeswap/sdk' +import JSBI from 'jsbi' import { useEffect } from 'react' import { useDispatch } from 'react-redux' diff --git a/src/state/gauges/hooks.ts b/src/state/gauges/hooks.ts index 0e90ccd5588..f346f29feb2 100644 --- a/src/state/gauges/hooks.ts +++ b/src/state/gauges/hooks.ts @@ -1,7 +1,8 @@ import { invariant } from '@apollo/client/utilities/globals' -import { JSBI, Percent, TokenAmount } from '@ubeswap/sdk' import { IGauge, StablePools } from 'constants/pools' import { useMobi } from 'hooks/Tokens' +import JSBI from 'jsbi' +import { Percent, TokenAmount } from 'lib/token-utils' import { useSelector } from 'react-redux' import { CHAIN } from '../../constants' diff --git a/src/state/gauges/reducer.ts b/src/state/gauges/reducer.ts index e854db5cfde..8bdaa7b67e4 100644 --- a/src/state/gauges/reducer.ts +++ b/src/state/gauges/reducer.ts @@ -1,6 +1,6 @@ import { createReducer } from '@reduxjs/toolkit' -import { JSBI } from '@ubeswap/sdk' import { IGauge, StablePools } from 'constants/pools' +import JSBI from 'jsbi' import { CHAIN } from '../../constants' import { updateGauges, updateGaugesUser } from './actions' diff --git a/src/state/gauges/updater.ts b/src/state/gauges/updater.ts index e4c8a2e336c..42dac3a10c8 100644 --- a/src/state/gauges/updater.ts +++ b/src/state/gauges/updater.ts @@ -1,7 +1,7 @@ import { Interface } from '@ethersproject/abi' -import { JSBI } from '@ubeswap/sdk' import { IGauge, StablePools } from 'constants/pools' import { useWeb3Context } from 'hooks' +import JSBI from 'jsbi' import { useEffect } from 'react' import { useDispatch } from 'react-redux' import { AppDispatch } from 'state' diff --git a/src/state/governance/hooks.ts b/src/state/governance/hooks.ts index 186dd954aa9..f6619770698 100644 --- a/src/state/governance/hooks.ts +++ b/src/state/governance/hooks.ts @@ -3,11 +3,11 @@ import { Contract } from '@ethersproject/contracts' import { TransactionResponse } from '@ethersproject/providers' import { toUtf8String, Utf8ErrorFuncs } from '@ethersproject/strings' import { formatUnits } from '@ethersproject/units' -// eslint-disable-next-line no-restricted-imports -import { TokenAmount } from '@ubeswap/sdk' import { abi as GOV_ABI } from '@uniswap/governance/build/GovernorAlpha.json' import { useWeb3Context } from 'hooks' import { useGovernanceContract, useVotingEscrowContract } from 'hooks/useContract' +// eslint-disable-next-line no-restricted-imports +import { TokenAmount } from 'lib/token-utils' import { useCallback, useMemo } from 'react' import { calculateGasMargin } from 'utils/calculateGasMargin' diff --git a/src/state/lists/hooks.ts b/src/state/lists/hooks.ts index 4cff6ae02ff..b173b4f21b6 100644 --- a/src/state/lists/hooks.ts +++ b/src/state/lists/hooks.ts @@ -1,5 +1,5 @@ -import { Token } from '@ubeswap/sdk' import { Tags, TokenInfo } from '@uniswap/token-lists' +import { Token } from 'lib/token-utils' type TagDetails = Tags[keyof Tags] export interface TagInfo extends TagDetails { diff --git a/src/state/mento/hooks.ts b/src/state/mento/hooks.ts index aabd76957fd..d2405417522 100644 --- a/src/state/mento/hooks.ts +++ b/src/state/mento/hooks.ts @@ -1,12 +1,14 @@ import { parseUnits } from '@ethersproject/units' -import { JSBI, Percent, Price, Token, TokenAmount, TradeType } from '@ubeswap/sdk' +import { TradeType } from '@ubeswap/sdk' import { IMentoExchangeInfo } from 'constants/mento' import { CELO } from 'constants/tokens' +import JSBI from 'jsbi' import { calculateEstimatedSwapInputAmount, calculateEstimatedSwapOutputAmount, calculateSwapPrice, } from 'lib/mentoCalculator' +import { Percent, Price, Token, TokenAmount } from 'lib/token-utils' import { useCallback } from 'react' import { useDispatch, useSelector } from 'react-redux' import invariant from 'tiny-invariant' diff --git a/src/state/mentoPools/hooks.ts b/src/state/mentoPools/hooks.ts index 07886019771..6d5643e59d0 100644 --- a/src/state/mentoPools/hooks.ts +++ b/src/state/mentoPools/hooks.ts @@ -1,8 +1,8 @@ import { invariant } from '@apollo/client/utilities/globals' import { StableToken } from '@celo/contractkit' -import { Token } from '@ubeswap/sdk' import { IMentoExchangeInfo } from 'constants/mento' import { CEUR, CREAL, CUSD } from 'constants/tokens' +import { Token } from 'lib/token-utils' import { useSelector } from 'react-redux' import { CHAIN } from '../../constants' diff --git a/src/state/mentoPools/reducer.ts b/src/state/mentoPools/reducer.ts index 07a62b0a67a..b3e5bf378a4 100644 --- a/src/state/mentoPools/reducer.ts +++ b/src/state/mentoPools/reducer.ts @@ -1,7 +1,7 @@ import { createReducer } from '@reduxjs/toolkit' -import { Percent, TokenAmount } from '@ubeswap/sdk' import { IMentoExchange, IMentoExchangeInfo } from 'constants/mento' import { CELO } from 'constants/tokens' +import { Percent, TokenAmount } from 'lib/token-utils' import { CHAIN } from '../../constants' import { MENTO_POOL_INFO } from '../../constants/mento' diff --git a/src/state/mentoPools/updater.ts b/src/state/mentoPools/updater.ts index 6915d3aa4bb..019a4778d5d 100644 --- a/src/state/mentoPools/updater.ts +++ b/src/state/mentoPools/updater.ts @@ -1,9 +1,10 @@ import { invariant } from '@apollo/client/utilities/globals' import { newKit } from '@celo/contractkit' -import { JSBI, Percent, TokenAmount } from '@ubeswap/sdk' import { IMentoExchange } from 'constants/mento' import { CELO } from 'constants/tokens' import { Exchange } from 'generated' +import JSBI from 'jsbi' +import { Percent, TokenAmount } from 'lib/token-utils' import { useEffect } from 'react' import { useDispatch } from 'react-redux' import { useBlockNumber } from 'state/application/hooks' diff --git a/src/state/mobiusPools/hooks.ts b/src/state/mobiusPools/hooks.ts index 3fa4b879e50..b13403a51d7 100644 --- a/src/state/mobiusPools/hooks.ts +++ b/src/state/mobiusPools/hooks.ts @@ -1,7 +1,8 @@ -import { IExchangeInfo, Volume } from 'constants/pools' +import { IExchange, IExchangeInfo, StablePools, Volume } from 'constants/pools' import { useSelector } from 'react-redux' import invariant from 'tiny-invariant' +import { CHAIN } from '../../constants' import { AppState } from '..' export function useCurrentPool(token0: string, token1: string): IExchangeInfo | null { @@ -40,3 +41,11 @@ export function useCurrentPoolVolume(exchangeAddress: string): Volume | null { export function usePoolsVolume(): readonly Volume[] { return useSelector((state) => state.pools.pools) } + +export function poolInfoToExchange(info: IExchangeInfo): IExchange { + const exchange = StablePools[CHAIN].filter( + (e) => e.pool.lpToken.address.toLowerCase() === info.lpTotalSupply.token.address.toLowerCase() + ) + invariant(exchange.length === 1, 'cant find exchange') + return exchange[0].pool +} diff --git a/src/state/mobiusPools/reducer.ts b/src/state/mobiusPools/reducer.ts index f21bd758b70..de23e7a8c51 100644 --- a/src/state/mobiusPools/reducer.ts +++ b/src/state/mobiusPools/reducer.ts @@ -1,6 +1,6 @@ import { createReducer } from '@reduxjs/toolkit' -import { TokenAmount } from '@ubeswap/sdk' import { IExchange, IExchangeInfo, RECOMMENDED_AMP, RECOMMENDED_FEES, StablePools, Volume } from 'constants/pools' +import { TokenAmount } from 'lib/token-utils' import { CHAIN } from '../../constants' import { updatePools } from './actions' diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index 5d6b4e2b6e7..04ee910eb4e 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -1,12 +1,13 @@ import { gql, useQuery } from '@apollo/client' import { Interface } from '@ethersproject/abi' -import { JSBI, TokenAmount } from '@ubeswap/sdk' import { RECOMMENDED_AMP, RECOMMENDED_FEES, StablePools } from 'constants/pools' +import JSBI from 'jsbi' +import { TokenAmount } from 'lib/token-utils' import { useEffect } from 'react' import { useDispatch } from 'react-redux' import { useBlockNumber } from 'state/application/hooks' import { useMultipleContractSingleData } from 'state/multicall/hooks' -import { BigIntToJSBI } from 'state/stablePools/updater' +import { BigIntToJSBI } from 'state/openSum/updater' import { CHAIN } from '../../constants' import LP from '../../constants/abis/LPToken.json' diff --git a/src/state/openSum/actions.ts b/src/state/openSum/actions.ts index 436d653a350..515b176ef4d 100644 --- a/src/state/openSum/actions.ts +++ b/src/state/openSum/actions.ts @@ -1,4 +1,4 @@ import { createAction } from '@reduxjs/toolkit' -import { JSBI } from '@ubeswap/sdk' +import JSBI from 'jsbi' export const updateBalances = createAction<{ balances: JSBI[][] }>('openSum/updateBalances') diff --git a/src/state/openSum/hooks.ts b/src/state/openSum/hooks.ts index ae109b1487e..411d6fce1c2 100644 --- a/src/state/openSum/hooks.ts +++ b/src/state/openSum/hooks.ts @@ -1,6 +1,7 @@ // To-Do: Implement Hooks to update Client-Side contract representation -import { ChainId, JSBI, Price, Token, TokenAmount } from '@ubeswap/sdk' import { ConstantSum, ConstantSumInfo } from 'constants/ConstantSum' +import JSBI from 'jsbi' +import { ChainId, Price, Token, TokenAmount, ZERO } from 'lib/token-utils' import { useSelector } from 'react-redux' import { tryParseAmount } from 'state/swap/hooks' @@ -8,7 +9,6 @@ import { CHAIN } from '../../constants' import { AppState } from '..' import { ConstantSumPool } from './reducer' -const ZERO = JSBI.BigInt('0') export interface MentoPoolInfo { readonly poolAddress?: string readonly tokens: readonly Token[] diff --git a/src/state/openSum/reducer.ts b/src/state/openSum/reducer.ts index fc1cdcfdcc6..de7865eb8ac 100644 --- a/src/state/openSum/reducer.ts +++ b/src/state/openSum/reducer.ts @@ -1,7 +1,7 @@ import { createReducer } from '@reduxjs/toolkit' -import { JSBI } from '@ubeswap/sdk' import { NETWORK_CHAIN_ID } from 'connectors' import { ConstantSum } from 'constants/ConstantSum' +import JSBI from 'jsbi' import { WrappedTokenInfo } from 'state/lists/hooks' import { updateBalances } from './actions' diff --git a/src/state/openSum/updater.ts b/src/state/openSum/updater.ts index cd0bf334aae..ec5f75bce74 100644 --- a/src/state/openSum/updater.ts +++ b/src/state/openSum/updater.ts @@ -1,6 +1,6 @@ import { Interface } from '@ethersproject/abi' -import { JSBI } from '@ubeswap/sdk' import { ConstantSum, ConstantSumInfo } from 'constants/ConstantSum' +import JSBI from 'jsbi' import { useMemo } from 'react' import { useDispatch } from 'react-redux' import { useMultipleContractSingleData } from 'state/multicall/hooks' @@ -8,9 +8,12 @@ import { useMultipleContractSingleData } from 'state/multicall/hooks' import { CHAIN } from '../../constants' import CONSTANT_SUM from '../../constants/abis/ConstantSum.json' import { AppDispatch } from '../index' -import { BigIntToJSBI } from '../stablePools/updater' import { updateBalances } from './actions' +export const BigIntToJSBI = (num: BigInt | undefined, fallBack = '0') => { + return JSBI.BigInt(num?.toString() ?? fallBack) +} + const ConstantSumInterface = new Interface(CONSTANT_SUM.abi) const ZERO = JSBI.BigInt('0') diff --git a/src/state/stablePools/hooks.ts b/src/state/stablePools/hooks.ts index 7017889d917..4315048b3a3 100644 --- a/src/state/stablePools/hooks.ts +++ b/src/state/stablePools/hooks.ts @@ -1,237 +1,239 @@ -// To-Do: Implement Hooks to update Client-Side contract representation -import { JSBI, Percent, Token, TokenAmount } from '@ubeswap/sdk' -import { Chain, Coins } from 'constants/StablePools' -import { useWeb3Context } from 'hooks' -import { addressToToken } from 'hooks/Tokens' -import { useLiquidityGaugeContract, useStableSwapContract } from 'hooks/useContract' -import { useEffect, useMemo, useState } from 'react' -import { useSelector } from 'react-redux' -import { useSingleContractMultipleData } from 'state/multicall/hooks' -import { tryParseAmount } from 'state/swap/hooks' -import invariant from 'tiny-invariant' -import { PairStableSwap } from 'utils/StablePairMath' - -import WARNINGS from '../../constants/PoolWarnings.json' -import { StableSwapMath } from '../../utils/stableSwapMath' -import { AppState } from '..' -import { StableSwapPool, WarningType } from './reducer' -import { BigIntToJSBI } from './updater' - -export type WarningModifications = 'require-equal-deposit' | 'none' - -export interface StablePoolInfo { - readonly name: string - readonly poolAddress?: string - readonly stakingToken?: Token - readonly lpToken?: Token - readonly tokens: readonly Token[] - readonly amountDeposited?: TokenAmount - readonly totalDeposited: TokenAmount - readonly apr?: TokenAmount - readonly totalStakedAmount?: TokenAmount - readonly workingSupply?: JSBI - readonly stakedAmount: TokenAmount - readonly totalVolume?: TokenAmount - readonly peggedTo: string - readonly displayDecimals: number - readonly virtualPrice: JSBI - readonly priceOfStaked: TokenAmount - readonly balances: TokenAmount[] - readonly pegComesAfter: boolean | undefined - readonly mobiRate: JSBI | undefined - readonly pendingMobi: JSBI | undefined - readonly gaugeAddress?: string - readonly workingPercentage: Percent - readonly totalPercentage: Percent - readonly externalRewardRates?: TokenAmount[] - readonly lastClaim?: Date - readonly meta?: string - readonly displayChain: Chain - readonly coin: Coins - readonly isDisabled?: boolean - readonly weeklyVolume?: TokenAmount - readonly poolLoading: boolean - readonly gaugeLoading: boolean - readonly isKilled?: boolean -} - -const tokenAmountScaled = (token: Token, amount: JSBI): TokenAmount => - new TokenAmount(token, JSBI.divide(amount, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt(token.decimals)))) - -export const getPoolInfo = (pool: StableSwapPool): StablePoolInfo | Record | undefined => { - const external = - pool.additionalRewardRate?.map((rate, i) => { - const token = addressToToken(pool.additionalRewards?.[i]) - invariant(token) - return new TokenAmount(token, rate) - }) ?? undefined - return !pool.lpTotalSupply - ? undefined - : { - name: pool.name, - poolAddress: pool.address, - lpToken: pool.lpToken, - tokens: pool.tokens, - amountDeposited: new TokenAmount( - pool.lpToken, - JSBI.add(pool.lpOwned ?? JSBI.BigInt('0'), pool.userStaked ?? JSBI.BigInt('0')) - ), - totalDeposited: new TokenAmount(pool.lpToken, pool.lpTotalSupply ?? JSBI.BigInt('0')), - stakedAmount: new TokenAmount(pool.lpToken, pool.userStaked || JSBI.BigInt('0')), - apr: new TokenAmount(pool.lpToken, JSBI.BigInt('100000000000000000')), - peggedTo: pool.peggedTo, - virtualPrice: pool.virtualPrice, - priceOfStaked: tokenAmountScaled( - pool.lpToken, - JSBI.multiply( - pool.virtualPrice ?? JSBI.BigInt('0'), - JSBI.add(pool.lpOwned ?? JSBI.BigInt('0'), pool.userStaked ?? JSBI.BigInt('0')) - ) - ), - workingSupply: pool.workingLiquidity, - balances: pool.tokens.map( - (token, i) => new TokenAmount(token, pool.balances?.[i] ?? pool.approxBalances?.[i] ?? '0') - ), - pegComesAfter: pool.pegComesAfter, - mobiRate: pool.isKilled ? JSBI.BigInt('0') : pool.totalMobiRate, - pendingMobi: pool.pendingMobi, - gaugeAddress: pool.gaugeAddress, - displayDecimals: pool.displayDecimals, - totalStakedAmount: new TokenAmount(pool.lpToken, pool.totalStakedAmount ?? '0'), - workingPercentage: new Percent(pool.effectiveBalance, pool.totalEffectiveBalance), - totalPercentage: new Percent(pool.userStaked ?? '0', pool.totalStakedAmount ?? '1'), - externalRewardRates: external, - lastClaim: pool.lastClaim, - meta: pool.metaPool, - displayChain: pool.displayChain, - coin: pool.coin, - isDisabled: pool.disabled, - isKilled: pool.isKilled, - weeklyVolume: pool.volume ? tryParseAmount(pool.volume.week.toFixed(6), pool.lpToken) : undefined, - totalVolume: pool.volume ? tryParseAmount(pool.volume.total?.toFixed(6), pool.lpToken) : undefined, - poolLoading: pool.loadingPool, - gaugeLoading: pool.loadingGauge, - } -} - -export function useStablePoolInfoByName(name: string): StablePoolInfo | undefined { - const pool = useSelector((state) => state.stablePools.pools[name.toLowerCase()]?.pool) - return !pool ? undefined : { ...getPoolInfo(pool) } -} - -export function useStablePoolInfo(): readonly StablePoolInfo[] { - const pools = usePools() - return pools.map((pool) => getPoolInfo(pool)).filter((el) => el) -} - -export function useExpectedTokens(pool: StablePoolInfo, lpAmount: TokenAmount): TokenAmount[] { - const contract = useStableSwapContract(pool.poolAddress) - const { tokens } = pool - const { address } = useWeb3Context() - const [expectedOut, setExpectedOut] = useState( - tokens.map((token) => new TokenAmount(token, JSBI.BigInt('0'))) - ) - useEffect(() => { - const updateData = async () => { - try { - const newTokenAmounts = await contract?.calculateRemoveLiquidity(address, lpAmount.raw.toString()) - setExpectedOut(tokens.map((token, i) => new TokenAmount(token, JSBI.BigInt(newTokenAmounts[i].toString())))) - } catch (e) { - console.error(e) - setExpectedOut(tokens.map((token, i) => new TokenAmount(token, JSBI.BigInt('0')))) - } - } - lpAmount && lpAmount.raw && updateData() - }, [address, contract, lpAmount, tokens]) - return expectedOut -} - -export function useExpectedLpTokens( - pool: StablePoolInfo, - tokens: Token[], - input: (string | undefined)[], - isDeposit = true -): [TokenAmount, TokenAmount[]] { - const mathUtil = useMathUtil(pool.poolAddress ?? pool.address) - const tokenAmounts = useMemo( - () => tokens.map((t, i) => tryParseAmount(input[i], t) ?? new TokenAmount(t, '0')), - [input] - ) - - return useMemo(() => { - const allZero = tokenAmounts.reduce((accum, cur) => accum && cur.equalTo('0'), true) - if (allZero) { - return [new TokenAmount(pool.lpToken, '0'), tokenAmounts] - } - - if (!pool.totalDeposited || pool.totalDeposited.equalTo('0')) { - const amount = - tryParseAmount( - tokenAmounts.reduce((accum, cur) => (parseFloat(accum) + parseFloat(cur.toExact())).toString(), '0'), - pool.lpToken - ) ?? new TokenAmount(pool.lpToken, '0') - - return [amount, tokenAmounts] - } - const amount = - mathUtil?.calculateTokenAmount( - tokenAmounts.map((ta) => ta?.raw || JSBI.BigInt('0')), - isDeposit - ) ?? JSBI.BigInt('0') - return [new TokenAmount(pool.lpToken, amount), tokenAmounts] - }, [input, mathUtil, tokenAmounts]) -} - -export function useMathUtil(pool: StableSwapPool | string): StableSwapMath | undefined { - const name = !pool ? '' : typeof pool == 'string' ? pool : pool.address - const math = useSelector((state) => state.stablePools.pools[name.toLowerCase()]?.math) - return math -} - -// export function usePriceOfLp(address: string, amountOfLp: TokenAmount): TokenAmount | undefined { -// const pool = useStablePoolInfoByName(address) -// const price = useEthBtcPrice(pool?.poolAddress ?? '') -// return pool && price && amountOfLp -// ? new TokenAmount( -// amountOfLp.token, -// JSBI.divide( -// JSBI.multiply(amountOfLp.raw, JSBI.multiply(pool?.virtualPrice, price)), -// JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) -// ) -// ) -// : undefined +// // To-Do: Implement Hooks to update Client-Side contract representation +// import { Chain, Coins } from 'constants/StablePools' +// import { useWeb3Context } from 'hooks' +// import { addressToToken } from 'hooks/Tokens' +// import { useLiquidityGaugeContract, useStableSwapContract } from 'hooks/useContract' +// import { JSBI, Percent, Token, TokenAmount } from 'lib/token-utils' +// import { useEffect, useMemo, useState } from 'react' +// import { useSelector } from 'react-redux' +// import { useSingleContractMultipleData } from 'state/multicall/hooks' +// import { tryParseAmount } from 'state/swap/hooks' +// import invariant from 'tiny-invariant' +// import { PairStableSwap } from 'utils/StablePairMath' + +// import WARNINGS from '../../constants/PoolWarnings.json' +// import { StableSwapMath } from '../../utils/stableSwapMath' +// import { AppState } from '..' +// import { StableSwapPool, WarningType } from './reducer' +// import { BigIntToJSBI } from './updater' + +// export type WarningModifications = 'require-equal-deposit' | 'none' + +// export interface StablePoolInfo { +// readonly name: string +// readonly poolAddress?: string +// readonly stakingToken?: Token +// readonly lpToken?: Token +// readonly tokens: readonly Token[] +// readonly amountDeposited?: TokenAmount +// readonly totalDeposited: TokenAmount +// readonly apr?: TokenAmount +// readonly totalStakedAmount?: TokenAmount +// readonly workingSupply?: JSBI +// readonly stakedAmount: TokenAmount +// readonly totalVolume?: TokenAmount +// readonly peggedTo: string +// readonly displayDecimals: number +// readonly virtualPrice: JSBI +// readonly priceOfStaked: TokenAmount +// readonly balances: TokenAmount[] +// readonly pegComesAfter: boolean | undefined +// readonly mobiRate: JSBI | undefined +// readonly pendingMobi: JSBI | undefined +// readonly gaugeAddress?: string +// readonly workingPercentage: Percent +// readonly totalPercentage: Percent +// readonly externalRewardRates?: TokenAmount[] +// readonly lastClaim?: Date +// readonly meta?: string +// readonly displayChain: Chain +// readonly coin: Coins +// readonly isDisabled?: boolean +// readonly weeklyVolume?: TokenAmount +// readonly poolLoading: boolean +// readonly gaugeLoading: boolean +// readonly isKilled?: boolean // } -export function useExternalRewards({ address }: { address: string }): TokenAmount[] { - const pool = useSelector((state) => state.stablePools.pools[address.toLowerCase()]?.pool) - const gauge = useLiquidityGaugeContract(pool?.gaugeAddress ?? undefined) - const { address: userAddress, connected } = useWeb3Context() - gauge?.claimable_reward_write - const claimableTokens = useSingleContractMultipleData( - gauge, - 'claimable_reward_write', - pool?.additionalRewards?.map((token) => [connected ? userAddress : undefined, token ?? undefined]) ?? undefined - ) - // console.log(claimableTokens) - const externalRewards = claimableTokens?.map((result, i) => { - const token = addressToToken(pool.additionalRewards?.[i]) - invariant(token) - return new TokenAmount(token, BigIntToJSBI(result?.result?.[0] ?? '0', '0') ?? '0') - }) - return externalRewards -} - -export function useWarning( - pool: string | undefined -): { warning: string; link?: string; modification?: WarningModifications } | undefined { - const warningType = useSelector( - (state) => state.stablePools.pools[pool?.toLowerCase() ?? '']?.pool?.warningType ?? undefined - ) - if (!warningType) return undefined - return WARNINGS[warningType] as any as { warning: string; link?: string; modification?: WarningModifications } -} - -export function usePairUtil(pool?: StableSwapPool | string): PairStableSwap | undefined { - const name = !pool ? '' : typeof pool == 'string' ? pool : pool.address - return useSelector((state) => state.stablePools.pools[name.toLowerCase()]?.pair) -} +// const tokenAmountScaled = (token: Token, amount: JSBI): TokenAmount => +// new TokenAmount(token, JSBI.divide(amount, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt(token.decimals)))) + +// export const getPoolInfo = (pool: StableSwapPool): StablePoolInfo | Record | undefined => { +// const external = +// pool.additionalRewardRate?.map((rate, i) => { +// const token = addressToToken(pool.additionalRewards?.[i]) +// invariant(token) +// return new TokenAmount(token, rate) +// }) ?? undefined +// return !pool.lpTotalSupply +// ? undefined +// : { +// name: pool.name, +// poolAddress: pool.address, +// lpToken: pool.lpToken, +// tokens: pool.tokens, +// amountDeposited: new TokenAmount( +// pool.lpToken, +// JSBI.add(pool.lpOwned ?? JSBI.BigInt('0'), pool.userStaked ?? JSBI.BigInt('0')) +// ), +// totalDeposited: new TokenAmount(pool.lpToken, pool.lpTotalSupply ?? JSBI.BigInt('0')), +// stakedAmount: new TokenAmount(pool.lpToken, pool.userStaked || JSBI.BigInt('0')), +// apr: new TokenAmount(pool.lpToken, JSBI.BigInt('100000000000000000')), +// peggedTo: pool.peggedTo, +// virtualPrice: pool.virtualPrice, +// priceOfStaked: tokenAmountScaled( +// pool.lpToken, +// JSBI.multiply( +// pool.virtualPrice ?? JSBI.BigInt('0'), +// JSBI.add(pool.lpOwned ?? JSBI.BigInt('0'), pool.userStaked ?? JSBI.BigInt('0')) +// ) +// ), +// workingSupply: pool.workingLiquidity, +// balances: pool.tokens.map( +// (token, i) => new TokenAmount(token, pool.balances?.[i] ?? pool.approxBalances?.[i] ?? '0') +// ), +// pegComesAfter: pool.pegComesAfter, +// mobiRate: pool.isKilled ? JSBI.BigInt('0') : pool.totalMobiRate, +// pendingMobi: pool.pendingMobi, +// gaugeAddress: pool.gaugeAddress, +// displayDecimals: pool.displayDecimals, +// totalStakedAmount: new TokenAmount(pool.lpToken, pool.totalStakedAmount ?? '0'), +// workingPercentage: new Percent(pool.effectiveBalance, pool.totalEffectiveBalance), +// totalPercentage: new Percent(pool.userStaked ?? '0', pool.totalStakedAmount ?? '1'), +// externalRewardRates: external, +// lastClaim: pool.lastClaim, +// meta: pool.metaPool, +// displayChain: pool.displayChain, +// coin: pool.coin, +// isDisabled: pool.disabled, +// isKilled: pool.isKilled, +// weeklyVolume: pool.volume ? tryParseAmount(pool.volume.week.toFixed(6), pool.lpToken) : undefined, +// totalVolume: pool.volume ? tryParseAmount(pool.volume.total?.toFixed(6), pool.lpToken) : undefined, +// poolLoading: pool.loadingPool, +// gaugeLoading: pool.loadingGauge, +// } +// } + +// export function useStablePoolInfoByName(name: string): StablePoolInfo | undefined { +// const pool = useSelector((state) => state.stablePools.pools[name.toLowerCase()]?.pool) +// return !pool ? undefined : { ...getPoolInfo(pool) } +// } + +// export function useStablePoolInfo(): readonly StablePoolInfo[] { +// const pools = usePools() +// return pools.map((pool) => getPoolInfo(pool)).filter((el) => el) +// } + +// export function useExpectedTokens(pool: StablePoolInfo, lpAmount: TokenAmount): TokenAmount[] { +// const contract = useStableSwapContract(pool.poolAddress) +// const { tokens } = pool +// const { address } = useWeb3Context() +// const [expectedOut, setExpectedOut] = useState( +// tokens.map((token) => new TokenAmount(token, JSBI.BigInt('0'))) +// ) +// useEffect(() => { +// const updateData = async () => { +// try { +// const newTokenAmounts = await contract?.calculateRemoveLiquidity(address, lpAmount.raw.toString()) +// setExpectedOut(tokens.map((token, i) => new TokenAmount(token, JSBI.BigInt(newTokenAmounts[i].toString())))) +// } catch (e) { +// console.error(e) +// setExpectedOut(tokens.map((token, i) => new TokenAmount(token, JSBI.BigInt('0')))) +// } +// } +// lpAmount && lpAmount.raw && updateData() +// }, [address, contract, lpAmount, tokens]) +// return expectedOut +// } + +// export function useExpectedLpTokens( +// pool: StablePoolInfo, +// tokens: Token[], +// input: (string | undefined)[], +// isDeposit = true +// ): [TokenAmount, TokenAmount[]] { +// const mathUtil = useMathUtil(pool.poolAddress ?? pool.address) +// const tokenAmounts = useMemo( +// () => tokens.map((t, i) => tryParseAmount(input[i], t) ?? new TokenAmount(t, '0')), +// [input] +// ) + +// return useMemo(() => { +// const allZero = tokenAmounts.reduce((accum, cur) => accum && cur.equalTo('0'), true) +// if (allZero) { +// return [new TokenAmount(pool.lpToken, '0'), tokenAmounts] +// } + +// if (!pool.totalDeposited || pool.totalDeposited.equalTo('0')) { +// const amount = +// tryParseAmount( +// tokenAmounts.reduce((accum, cur) => (parseFloat(accum) + parseFloat(cur.toExact())).toString(), '0'), +// pool.lpToken +// ) ?? new TokenAmount(pool.lpToken, '0') + +// return [amount, tokenAmounts] +// } +// const amount = +// mathUtil?.calculateTokenAmount( +// tokenAmounts.map((ta) => ta?.raw || JSBI.BigInt('0')), +// isDeposit +// ) ?? JSBI.BigInt('0') +// return [new TokenAmount(pool.lpToken, amount), tokenAmounts] +// }, [input, mathUtil, tokenAmounts]) +// } + +// export function useMathUtil(pool: StableSwapPool | string): StableSwapMath | undefined { +// const name = !pool ? '' : typeof pool == 'string' ? pool : pool.address +// const math = useSelector((state) => state.stablePools.pools[name.toLowerCase()]?.math) +// return math +// } + +// // export function usePriceOfLp(address: string, amountOfLp: TokenAmount): TokenAmount | undefined { +// // const pool = useStablePoolInfoByName(address) +// // const price = useEthBtcPrice(pool?.poolAddress ?? '') +// // return pool && price && amountOfLp +// // ? new TokenAmount( +// // amountOfLp.token, +// // JSBI.divide( +// // JSBI.multiply(amountOfLp.raw, JSBI.multiply(pool?.virtualPrice, price)), +// // JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) +// // ) +// // ) +// // : undefined +// // } + +// export function useExternalRewards({ address }: { address: string }): TokenAmount[] { +// const pool = useSelector((state) => state.stablePools.pools[address.toLowerCase()]?.pool) +// const gauge = useLiquidityGaugeContract(pool?.gaugeAddress ?? undefined) +// const { address: userAddress, connected } = useWeb3Context() +// gauge?.claimable_reward_write +// const claimableTokens = useSingleContractMultipleData( +// gauge, +// 'claimable_reward_write', +// pool?.additionalRewards?.map((token) => [connected ? userAddress : undefined, token ?? undefined]) ?? undefined +// ) +// // console.log(claimableTokens) +// const externalRewards = claimableTokens?.map((result, i) => { +// const token = addressToToken(pool.additionalRewards?.[i]) +// invariant(token) +// return new TokenAmount(token, BigIntToJSBI(result?.result?.[0] ?? '0', '0') ?? '0') +// }) +// return externalRewards +// } + +// export function useWarning( +// pool: string | undefined +// ): { warning: string; link?: string; modification?: WarningModifications } | undefined { +// const warningType = useSelector( +// (state) => state.stablePools.pools[pool?.toLowerCase() ?? '']?.pool?.warningType ?? undefined +// ) +// if (!warningType) return undefined +// return WARNINGS[warningType] as any as { warning: string; link?: string; modification?: WarningModifications } +// } + +// export function usePairUtil(pool?: StableSwapPool | string): PairStableSwap | undefined { +// const name = !pool ? '' : typeof pool == 'string' ? pool : pool.address +// return useSelector((state) => state.stablePools.pools[name.toLowerCase()]?.pair) +// } + +export {} diff --git a/src/state/stablePools/reducer.ts b/src/state/stablePools/reducer.ts index 0bfcf6922ba..028aef4bf68 100644 --- a/src/state/stablePools/reducer.ts +++ b/src/state/stablePools/reducer.ts @@ -1,8 +1,8 @@ import { createReducer, current } from '@reduxjs/toolkit' -import { Fraction, Percent, Token } from '@ubeswap/sdk' import { NETWORK_CHAIN_ID } from 'connectors' import { Chain, Coins, STATIC_POOL_INFO } from 'constants/StablePools' import JSBI from 'jsbi' +import { Fraction, Percent, Token } from 'lib/token-utils' import { PairStableSwap } from 'utils/StablePairMath' import { StableSwapMath } from 'utils/stableSwapMath' diff --git a/src/state/stablePools/updater.ts b/src/state/stablePools/updater.ts index 9682785a03b..996396883a1 100644 --- a/src/state/stablePools/updater.ts +++ b/src/state/stablePools/updater.ts @@ -1,231 +1,233 @@ -import { gql, useQuery } from '@apollo/client' -import { Interface } from '@ethersproject/abi' -import { JSBI, Percent } from '@ubeswap/sdk' -import { useMemo } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import { useBlockNumber } from 'state/application/hooks' -import { - useMultipleContractSingleData, - useSingleCallResult, - useSingleContractMultipleData, -} from 'state/multicall/hooks' +// import { gql, useQuery } from '@apollo/client' +// import { Interface } from '@ethersproject/abi' +// import { JSBI, Percent } from 'lib/token-utils' +// import { useMemo } from 'react' +// import { useDispatch, useSelector } from 'react-redux' +// import { useBlockNumber } from 'state/application/hooks' +// import { +// useMultipleContractSingleData, +// useSingleCallResult, +// useSingleContractMultipleData, +// } from 'state/multicall/hooks' -import { CHAIN } from '../../constants' -import GAUGE_V3 from '../../constants/abis/LiquidityGaugeV3.json' -import LP from '../../constants/abis/LPToken.json' -import SWAP from '../../constants/abis/Swap.json' -import { STATIC_POOL_INFO } from '../../constants/StablePools' -import { useWeb3Context } from '../../hooks' -import { useGaugeControllerContract, useMobiContract } from '../../hooks/useContract' -import { AppDispatch, AppState } from '../index' -import { updateGauges, updatePools } from './actions' -import { GaugeOnlyInfo, PoolOnlyInfo, StableSwapConstants } from './reducer' +// import { CHAIN } from '../../constants' +// import GAUGE_V3 from '../../constants/abis/LiquidityGaugeV3.json' +// import LP from '../../constants/abis/LPToken.json' +// import SWAP from '../../constants/abis/Swap.json' +// import { STATIC_POOL_INFO } from '../../constants/StablePools' +// import { useWeb3Context } from '../../hooks' +// import { useGaugeControllerContract, useMobiContract } from '../../hooks/useContract' +// import { AppDispatch, AppState } from '../index' +// import { updateGauges, updatePools } from './actions' +// import { GaugeOnlyInfo, PoolOnlyInfo, StableSwapConstants } from './reducer' -const SwapInterface = new Interface(SWAP.abi) -const lpInterface = new Interface(LP.abi) -const gaugeInterface = new Interface(GAUGE_V3.abi) +// const SwapInterface = new Interface(SWAP.abi) +// const lpInterface = new Interface(LP.abi) +// const gaugeInterface = new Interface(GAUGE_V3.abi) -export const BigIntToJSBI = (num: BigInt | undefined, fallBack = '0') => { - return JSBI.BigInt(num?.toString() ?? fallBack) -} +// export const BigIntToJSBI = (num: BigInt | undefined, fallBack = '0') => { +// return JSBI.BigInt(num?.toString() ?? fallBack) +// } -export function UpdateVariablePoolInfo(): null { - const { connected, address } = useWeb3Context() - const blockNumber = useBlockNumber() - const dispatch = useDispatch() - const pools: StableSwapConstants[] = useSelector((state: AppState) => - Object.values(state.stablePools.pools).map(({ pool }) => pool) - ) - const poolAddresses = pools.map(({ address }) => address) - const lpTokenAddresses = pools.map(({ lpToken: { address } }) => address) - const lpTotalSupplies = useMultipleContractSingleData(lpTokenAddresses, lpInterface, 'totalSupply') - const lpOwned_multiple = useMultipleContractSingleData(lpTokenAddresses, lpInterface, 'balanceOf', [ - connected ? address : undefined, - ]) - const virtualPrices = useMultipleContractSingleData(poolAddresses, SwapInterface, 'getVirtualPrice') - const balances = useMultipleContractSingleData(poolAddresses, SwapInterface, 'getBalances') - const amplificationCoefficients = useMultipleContractSingleData(poolAddresses, SwapInterface, 'getAPrecise') - const query = gql` - { - swaps { - id - A - balances - virtualPrice - dailyVolumes(orderBy: timestamp, orderDirection: desc) { - volume - } - weeklyVolumes(first: 2, orderBy: timestamp, orderDirection: desc) { - volume - } - } - } - ` - const { data, loading, error } = useQuery(query) - const lpInfo: { - [address: string]: { total: JSBI; user: JSBI; virtualPrice: JSBI; balances: JSBI[]; aPrecise: JSBI } - } = lpTotalSupplies - .filter((total, i) => !(total?.loading || lpOwned_multiple[i]?.loading)) - .map((total, i) => [ - BigIntToJSBI((total?.result?.[0] as BigInt) ?? '0'), - BigIntToJSBI((lpOwned_multiple?.[i]?.result?.[0] as BigInt) ?? '0'), - BigIntToJSBI((virtualPrices?.[i]?.result?.[0] as BigInt) ?? '0'), - balances?.[i]?.result?.[0] ? balances?.[i]?.result?.[0].map((amt: BigInt): JSBI => BigIntToJSBI(amt)) : undefined, - poolAddresses[i], - BigIntToJSBI((amplificationCoefficients?.[i]?.result?.[0] as BigInt) ?? '50'), - ]) - .reduce( - (accum, [total, user, virtualPrice, balances, address, aPrecise]) => ({ - ...accum, - [(address as any as string).toLowerCase()]: { total, user, balances, virtualPrice, aPrecise }, - }), - {} - ) - const inSubgraph: Set = - data?.swaps.reduce((accum: Set, cur: any) => new Set([...accum, cur.id]), new Set()) ?? new Set() - const poolsNotInSubgraph = poolAddresses.map((a) => a.toLowerCase()).filter((addr) => !inSubgraph.has(addr)) - return useMemo(() => { - if (error) console.log(error) - if (loading) return null - const poolInfo: PoolOnlyInfo[] = data.swaps - .filter(({ id }) => !!lpInfo[id]) - .map((pool) => ({ - id: pool.id, - volume: { - total: pool.dailyVolumes.reduce((accum: number, el: string) => accum + parseFloat(el.volume), 0), - day: parseFloat(pool.dailyVolumes[0]?.volume ?? '0'), - week: parseFloat(pool.weeklyVolumes[0]?.volume ?? '0'), - }, - approxBalances: pool.balances.map((b: string) => JSBI.BigInt(b)), - balances: lpInfo[pool.id].balances ? lpInfo[pool.id].balances : undefined, - aPrecise: lpInfo[pool.id].aPrecise, - virtualPrice: lpInfo[pool.id].virtualPrice, - lpTotalSupply: lpInfo[pool.id].total, - lpOwned: lpInfo[pool.id].user, - loadingPool: !lpInfo[pool.id].total, - })) +// export function UpdateVariablePoolInfo(): null { +// const { connected, address } = useWeb3Context() +// const blockNumber = useBlockNumber() +// const dispatch = useDispatch() +// const pools: StableSwapConstants[] = useSelector((state: AppState) => +// Object.values(state.stablePools.pools).map(({ pool }) => pool) +// ) +// const poolAddresses = pools.map(({ address }) => address) +// const lpTokenAddresses = pools.map(({ lpToken: { address } }) => address) +// const lpTotalSupplies = useMultipleContractSingleData(lpTokenAddresses, lpInterface, 'totalSupply') +// const lpOwned_multiple = useMultipleContractSingleData(lpTokenAddresses, lpInterface, 'balanceOf', [ +// connected ? address : undefined, +// ]) +// const virtualPrices = useMultipleContractSingleData(poolAddresses, SwapInterface, 'getVirtualPrice') +// const balances = useMultipleContractSingleData(poolAddresses, SwapInterface, 'getBalances') +// const amplificationCoefficients = useMultipleContractSingleData(poolAddresses, SwapInterface, 'getAPrecise') +// const query = gql` +// { +// swaps { +// id +// A +// balances +// virtualPrice +// dailyVolumes(orderBy: timestamp, orderDirection: desc) { +// volume +// } +// weeklyVolumes(first: 2, orderBy: timestamp, orderDirection: desc) { +// volume +// } +// } +// } +// ` +// const { data, loading, error } = useQuery(query) +// const lpInfo: { +// [address: string]: { total: JSBI; user: JSBI; virtualPrice: JSBI; balances: JSBI[]; aPrecise: JSBI } +// } = lpTotalSupplies +// .filter((total, i) => !(total?.loading || lpOwned_multiple[i]?.loading)) +// .map((total, i) => [ +// BigIntToJSBI((total?.result?.[0] as BigInt) ?? '0'), +// BigIntToJSBI((lpOwned_multiple?.[i]?.result?.[0] as BigInt) ?? '0'), +// BigIntToJSBI((virtualPrices?.[i]?.result?.[0] as BigInt) ?? '0'), +// balances?.[i]?.result?.[0] ? balances?.[i]?.result?.[0].map((amt: BigInt): JSBI => BigIntToJSBI(amt)) : undefined, +// poolAddresses[i], +// BigIntToJSBI((amplificationCoefficients?.[i]?.result?.[0] as BigInt) ?? '50'), +// ]) +// .reduce( +// (accum, [total, user, virtualPrice, balances, address, aPrecise]) => ({ +// ...accum, +// [(address as any as string).toLowerCase()]: { total, user, balances, virtualPrice, aPrecise }, +// }), +// {} +// ) +// const inSubgraph: Set = +// data?.swaps.reduce((accum: Set, cur: any) => new Set([...accum, cur.id]), new Set()) ?? new Set() +// const poolsNotInSubgraph = poolAddresses.map((a) => a.toLowerCase()).filter((addr) => !inSubgraph.has(addr)) +// return useMemo(() => { +// if (error) console.log(error) +// if (loading) return null +// const poolInfo: PoolOnlyInfo[] = data.swaps +// .filter(({ id }) => !!lpInfo[id]) +// .map((pool) => ({ +// id: pool.id, +// volume: { +// total: pool.dailyVolumes.reduce((accum: number, el: string) => accum + parseFloat(el.volume), 0), +// day: parseFloat(pool.dailyVolumes[0]?.volume ?? '0'), +// week: parseFloat(pool.weeklyVolumes[0]?.volume ?? '0'), +// }, +// approxBalances: pool.balances.map((b: string) => JSBI.BigInt(b)), +// balances: lpInfo[pool.id].balances ? lpInfo[pool.id].balances : undefined, +// aPrecise: lpInfo[pool.id].aPrecise, +// virtualPrice: lpInfo[pool.id].virtualPrice, +// lpTotalSupply: lpInfo[pool.id].total, +// lpOwned: lpInfo[pool.id].user, +// loadingPool: !lpInfo[pool.id].total, +// })) - dispatch( - updatePools({ - info: - poolsNotInSubgraph.length > 0 - ? poolInfo.concat( - poolsNotInSubgraph.map((id) => ({ - id, - volume: { - total: undefined, - day: undefined, - week: undefined, - }, - balances: lpInfo[id]?.total ? lpInfo[id].balances : undefined, - aPrecise: JSBI.BigInt(50 * 100), - virtualPrice: lpInfo[id]?.virtualPrice, - lpTotalSupply: lpInfo[id]?.total ?? JSBI.BigInt('1'), - lpOwned: lpInfo[id]?.user ?? JSBI.BigInt('0'), - loadingPool: !lpInfo[id]?.total, - approxBalances: lpInfo[id]?.total ? lpInfo[id].balances : undefined, - })) - ) - : poolInfo, - }) - ) - return null - }, [data, loading, error, dispatch, blockNumber]) -} +// dispatch( +// updatePools({ +// info: +// poolsNotInSubgraph.length > 0 +// ? poolInfo.concat( +// poolsNotInSubgraph.map((id) => ({ +// id, +// volume: { +// total: undefined, +// day: undefined, +// week: undefined, +// }, +// balances: lpInfo[id]?.total ? lpInfo[id].balances : undefined, +// aPrecise: JSBI.BigInt(50 * 100), +// virtualPrice: lpInfo[id]?.virtualPrice, +// lpTotalSupply: lpInfo[id]?.total ?? JSBI.BigInt('1'), +// lpOwned: lpInfo[id]?.user ?? JSBI.BigInt('0'), +// loadingPool: !lpInfo[id]?.total, +// approxBalances: lpInfo[id]?.total ? lpInfo[id].balances : undefined, +// })) +// ) +// : poolInfo, +// }) +// ) +// return null +// }, [data, loading, error, dispatch, blockNumber]) +// } -export function BatchUpdateGauges(): null { - const { address, connected } = useWeb3Context() - const blockNumber = useBlockNumber() - const dispatch = useDispatch() - const pools: StableSwapConstants[] = STATIC_POOL_INFO[CHAIN] ?? [] - const gaugeAddresses = pools.map(({ gaugeAddress }) => gaugeAddress) - const gaugeController = useGaugeControllerContract() - const mobiContract = useMobiContract() +// export function BatchUpdateGauges(): null { +// const { address, connected } = useWeb3Context() +// const blockNumber = useBlockNumber() +// const dispatch = useDispatch() +// const pools: StableSwapConstants[] = STATIC_POOL_INFO[CHAIN] ?? [] +// const gaugeAddresses = pools.map(({ gaugeAddress }) => gaugeAddress) +// const gaugeController = useGaugeControllerContract() +// const mobiContract = useMobiContract() - const totalStakedAmount_multi = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'totalSupply') - const lpStaked_multi = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'balanceOf', [ - connected ? address : undefined, - ]) - const workingLiquidityMulti = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_supply') - const pendingMobi_multi = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'claimable_tokens', [ - connected ? address : undefined, - ]) - const mobiRate: JSBI = BigIntToJSBI(useSingleCallResult(mobiContract, 'rate')?.result?.[0] ?? '0') - const weights = useSingleContractMultipleData( - gaugeController, - 'gauge_relative_weight(address)', - gaugeAddresses.map((a) => [a ?? undefined]) - ) - const futureWeights = useSingleContractMultipleData( - gaugeController, - 'get_gauge_weight', - gaugeAddresses.map((a) => [a ?? undefined]) - ) +// const totalStakedAmount_multi = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'totalSupply') +// const lpStaked_multi = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'balanceOf', [ +// connected ? address : undefined, +// ]) +// const workingLiquidityMulti = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_supply') +// const pendingMobi_multi = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'claimable_tokens', [ +// connected ? address : undefined, +// ]) +// const mobiRate: JSBI = BigIntToJSBI(useSingleCallResult(mobiContract, 'rate')?.result?.[0] ?? '0') +// const weights = useSingleContractMultipleData( +// gaugeController, +// 'gauge_relative_weight(address)', +// gaugeAddresses.map((a) => [a ?? undefined]) +// ) +// const futureWeights = useSingleContractMultipleData( +// gaugeController, +// 'get_gauge_weight', +// gaugeAddresses.map((a) => [a ?? undefined]) +// ) - const lastClaims = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'last_claim') +// const lastClaims = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'last_claim') - const effectiveBalances = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_balances', [ - connected ? address : undefined, - ]) - const totalEffectiveBalances = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_supply') - const lastVote = useSingleContractMultipleData( - gaugeController, - 'last_user_vote', - gaugeAddresses.map((a) => [connected ? address : a, a]) - ) - // vote_user_slopes - const slope = useSingleContractMultipleData( - gaugeController, - 'vote_user_slopes', - gaugeAddresses.map((a) => [connected ? address : a, a]) - ) +// const effectiveBalances = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_balances', [ +// connected ? address : undefined, +// ]) +// const totalEffectiveBalances = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_supply') +// const lastVote = useSingleContractMultipleData( +// gaugeController, +// 'last_user_vote', +// gaugeAddresses.map((a) => [connected ? address : a, a]) +// ) +// // vote_user_slopes +// const slope = useSingleContractMultipleData( +// gaugeController, +// 'vote_user_slopes', +// gaugeAddresses.map((a) => [connected ? address : a, a]) +// ) - useMemo(() => { - dispatch( - updateGauges({ - info: pools - .filter((_, i) => !(totalStakedAmount_multi?.[i]?.loading ?? true)) - .map((poolInfo, i) => { - const effectiveBalance: JSBI = BigIntToJSBI((effectiveBalances?.[i]?.result?.[0] as BigInt) ?? '0') - const totalEffectiveBalance: JSBI = BigIntToJSBI( - (totalEffectiveBalances?.[i]?.result?.[0] as BigInt) ?? '1' - ) - const lpStaked: JSBI = BigIntToJSBI((lpStaked_multi?.[i]?.result?.[0] as BigInt) ?? '0') - const pendingMobi: JSBI = BigIntToJSBI((pendingMobi_multi?.[i]?.result?.[0] as BigInt) ?? '0') - const weight: JSBI = BigIntToJSBI((weights?.[i]?.result?.[0] as BigInt) ?? '0') - const futureWeight: JSBI = BigIntToJSBI((futureWeights?.[i]?.result?.[0] as BigInt) ?? '0') - const totalStakedAmount: JSBI = BigIntToJSBI((totalStakedAmount_multi?.[i]?.result?.[0] as BigInt) ?? '0') - const workingLiquidity: JSBI = BigIntToJSBI((workingLiquidityMulti?.[i]?.result?.[0] as BigInt) ?? '0') - const lastUserVote: number = parseInt((lastUserVotes?.[i]?.result?.[0] ?? BigInt('0')).toString() ?? '0') - const lastClaim: Date = new Date( - parseInt((lastClaims?.[i]?.result?.[0] ?? BigInt('0')).toString() ?? '0') * 1000 - ) - const powerAllocated: number = parseInt((slopes?.[i]?.result?.[1] ?? BigInt('0')).toString() ?? '0') +// useMemo(() => { +// dispatch( +// updateGauges({ +// info: pools +// .filter((_, i) => !(totalStakedAmount_multi?.[i]?.loading ?? true)) +// .map((poolInfo, i) => { +// const effectiveBalance: JSBI = BigIntToJSBI((effectiveBalances?.[i]?.result?.[0] as BigInt) ?? '0') +// const totalEffectiveBalance: JSBI = BigIntToJSBI( +// (totalEffectiveBalances?.[i]?.result?.[0] as BigInt) ?? '1' +// ) +// const lpStaked: JSBI = BigIntToJSBI((lpStaked_multi?.[i]?.result?.[0] as BigInt) ?? '0') +// const pendingMobi: JSBI = BigIntToJSBI((pendingMobi_multi?.[i]?.result?.[0] as BigInt) ?? '0') +// const weight: JSBI = BigIntToJSBI((weights?.[i]?.result?.[0] as BigInt) ?? '0') +// const futureWeight: JSBI = BigIntToJSBI((futureWeights?.[i]?.result?.[0] as BigInt) ?? '0') +// const totalStakedAmount: JSBI = BigIntToJSBI((totalStakedAmount_multi?.[i]?.result?.[0] as BigInt) ?? '0') +// const workingLiquidity: JSBI = BigIntToJSBI((workingLiquidityMulti?.[i]?.result?.[0] as BigInt) ?? '0') +// const lastUserVote: number = parseInt((lastUserVotes?.[i]?.result?.[0] ?? BigInt('0')).toString() ?? '0') +// const lastClaim: Date = new Date( +// parseInt((lastClaims?.[i]?.result?.[0] ?? BigInt('0')).toString() ?? '0') * 1000 +// ) +// const powerAllocated: number = parseInt((slopes?.[i]?.result?.[1] ?? BigInt('0')).toString() ?? '0') - const totalMobiRate = JSBI.divide( - poolInfo.disabled ? JSBI.BigInt('0') : JSBI.multiply(mobiRate, weight), - JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) - ) +// const totalMobiRate = JSBI.divide( +// poolInfo.disabled ? JSBI.BigInt('0') : JSBI.multiply(mobiRate, weight), +// JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) +// ) - const collectedData: GaugeOnlyInfo = { - id: poolInfo.address.toLowerCase(), - poolWeight: new Percent(weight, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18'))), - userStaked: lpStaked, - pendingMobi, - totalMobiRate, - totalStakedAmount, - workingLiquidity, - effectiveBalance, - totalEffectiveBalance, - lastUserVote, - futureWeight, - lastClaim, - powerAllocated: powerAllocated / 100, - } - return collectedData - }), - }) - ) - }, [blockNumber, dispatch]) - return null -} +// const collectedData: GaugeOnlyInfo = { +// id: poolInfo.address.toLowerCase(), +// poolWeight: new Percent(weight, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18'))), +// userStaked: lpStaked, +// pendingMobi, +// totalMobiRate, +// totalStakedAmount, +// workingLiquidity, +// effectiveBalance, +// totalEffectiveBalance, +// lastUserVote, +// futureWeight, +// lastClaim, +// powerAllocated: powerAllocated / 100, +// } +// return collectedData +// }), +// }) +// ) +// }, [blockNumber, dispatch]) +// return null +// } + +export {} diff --git a/src/state/stake/hooks.ts b/src/state/stake/hooks.ts index 09c7d4ef162..4f8c9d9884b 100644 --- a/src/state/stake/hooks.ts +++ b/src/state/stake/hooks.ts @@ -1,4 +1,4 @@ -import { JSBI, Token, TokenAmount } from '@ubeswap/sdk' +import { JSBI, Token, TokenAmount } from 'lib/token-utils' // Hooks import { useWeb3Context } from '../../hooks' diff --git a/src/state/staking/hooks.ts b/src/state/staking/hooks.ts index 7cc97f5c126..fab27b5e7cf 100644 --- a/src/state/staking/hooks.ts +++ b/src/state/staking/hooks.ts @@ -1,6 +1,7 @@ -import { JSBI, Percent, Token, TokenAmount } from '@ubeswap/sdk' import { ExternalRewardsToken } from 'constants/staking' import { useMobi, useVeMobi } from 'hooks/Tokens' +import JSBI from 'jsbi' +import { Percent, Token, TokenAmount } from 'lib/token-utils' import { useSelector } from 'react-redux' import { AppState } from 'state' diff --git a/src/state/staking/reducer.ts b/src/state/staking/reducer.ts index b6bae887f1a..34571fca245 100644 --- a/src/state/staking/reducer.ts +++ b/src/state/staking/reducer.ts @@ -1,5 +1,5 @@ import { createReducer } from '@reduxjs/toolkit' -import { JSBI } from '@ubeswap/sdk' +import JSBI from 'jsbi' import { updateStaking, updateStakingUser } from './actions' diff --git a/src/state/staking/updater.ts b/src/state/staking/updater.ts index c637cd74ce2..78c796c2dc1 100644 --- a/src/state/staking/updater.ts +++ b/src/state/staking/updater.ts @@ -1,7 +1,7 @@ -import { JSBI } from '@ubeswap/sdk' import { ExternalStakingRewards } from 'constants/staking' import { VEMOBI } from 'constants/tokens' import { useWeb3Context } from 'hooks' +import JSBI from 'jsbi' import { roundDate } from 'pages/Staking/Lock/Lock' import { useEffect } from 'react' import { useDispatch } from 'react-redux' diff --git a/src/state/swap/hooks.ts b/src/state/swap/hooks.ts index dc4ddfdb415..fb8e1906913 100644 --- a/src/state/swap/hooks.ts +++ b/src/state/swap/hooks.ts @@ -1,7 +1,9 @@ import { parseUnits } from '@ethersproject/units' -import { JSBI, Percent, Price, Token, TokenAmount, TradeType } from '@ubeswap/sdk' +import { TradeType } from '@ubeswap/sdk' import { IExchangeInfo } from 'constants/pools' +import JSBI from 'jsbi' import { calculateEstimatedSwapOutputAmount, calculateSwapPrice } from 'lib/calculator' +import { Percent, Price, Token, TokenAmount } from 'lib/token-utils' import { useCallback } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useCurrentPool, usePools } from 'state/mobiusPools/hooks' diff --git a/src/state/transactions/actions.ts b/src/state/transactions/actions.ts index e39ac7af324..b5069f5e947 100644 --- a/src/state/transactions/actions.ts +++ b/src/state/transactions/actions.ts @@ -1,5 +1,5 @@ import { createAction } from '@reduxjs/toolkit' -import { ChainId } from '@ubeswap/sdk' +import { ChainId } from 'lib/token-utils' export interface SerializableTransactionReceipt { to: string diff --git a/src/state/wallet/hooks.ts b/src/state/wallet/hooks.ts index a9473eb1ee1..e270d99e7e7 100644 --- a/src/state/wallet/hooks.ts +++ b/src/state/wallet/hooks.ts @@ -1,6 +1,7 @@ import { invariant } from '@apollo/client/utilities/globals' -import { JSBI, Token, TokenAmount } from '@ubeswap/sdk' import { getAllTokens } from 'hooks/Tokens' +import JSBI from 'jsbi' +import { Token, TokenAmount } from 'lib/token-utils' import { useEffect, useMemo, useState } from 'react' import { useBlockNumber } from 'state/application/hooks' diff --git a/src/utils/StablePairMath.ts b/src/utils/StablePairMath.ts index 6a2415d91fe..5b7a232b900 100644 --- a/src/utils/StablePairMath.ts +++ b/src/utils/StablePairMath.ts @@ -1,5 +1,5 @@ -import { JSBI } from '@ubeswap/sdk' import BigNumber from 'bignumber.js' +import JSBI from 'jsbi' // See https://github.com/d-mooers/swappa/blob/main/src/pairs/stableswap.ts diff --git a/src/utils/calcExpectedVeMobi.ts b/src/utils/calcExpectedVeMobi.ts index 1424d9cdb0b..760937252b1 100644 --- a/src/utils/calcExpectedVeMobi.ts +++ b/src/utils/calcExpectedVeMobi.ts @@ -1,4 +1,5 @@ -import { Fraction, JSBI, Token, TokenAmount } from '@ubeswap/sdk' +import JSBI from 'jsbi' +import { Fraction, Token, TokenAmount } from 'lib/token-utils' import { GaugeSummary } from 'state/staking/hooks' // TODO double check that this math is correct diff --git a/src/utils/currencyId.ts b/src/utils/currencyId.ts index 2de6c5dfa0a..8d85d93f3ab 100644 --- a/src/utils/currencyId.ts +++ b/src/utils/currencyId.ts @@ -1,4 +1,4 @@ -import { Token } from '@ubeswap/sdk' +import { Token } from 'lib/token-utils' export function currencyId(currency: Token): string { return currency.address diff --git a/src/utils/index.ts b/src/utils/index.ts index c014d17b6b5..979366b2f21 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,8 +3,9 @@ import { BigNumber } from '@ethersproject/bignumber' import { AddressZero } from '@ethersproject/constants' import { Contract } from '@ethersproject/contracts' import { JsonRpcProvider, JsonRpcSigner } from '@ethersproject/providers' -import { JSBI, Percent, TokenAmount } from '@ubeswap/sdk' import { Exchange, Swap } from 'generated/index' +import JSBI from 'jsbi' +import { Percent, TokenAmount } from 'lib/token-utils' import EXCHANGE from '../constants/abis/Exchange.json' import SWAP from '../constants/abis/Swap.json' diff --git a/src/utils/maxAmountSpend.ts b/src/utils/maxAmountSpend.ts index dec67173b59..c2032379152 100644 --- a/src/utils/maxAmountSpend.ts +++ b/src/utils/maxAmountSpend.ts @@ -1,4 +1,4 @@ -import { TokenAmount } from '@ubeswap/sdk' +import { TokenAmount } from 'lib/token-utils' /** * Given some token amount, return the max that can be spent of it diff --git a/src/utils/prices.ts b/src/utils/prices.ts index 019186d039c..211e48a7459 100644 --- a/src/utils/prices.ts +++ b/src/utils/prices.ts @@ -1,4 +1,5 @@ -import { JSBI, Percent, TokenAmount } from '@ubeswap/sdk' +import JSBI from 'jsbi' +import { Percent, TokenAmount } from 'lib/token-utils' import { MentoTrade } from 'state/mento/hooks' import { MobiusTrade } from 'state/swap/hooks' @@ -24,8 +25,8 @@ export function computeSlippageAdjustedAmounts( const maxInput = JSBI.add(inputRaw, JSBI.divide(JSBI.multiply(inputRaw, pct.numerator), pct.denominator)) const minOutput = JSBI.subtract(outputRaw, JSBI.divide(JSBI.multiply(outputRaw, pct.numerator), pct.denominator)) return { - [Field.INPUT]: new TokenAmount(trade?.input.currency, maxInput), - [Field.OUTPUT]: new TokenAmount(trade?.output.currency, minOutput), + [Field.INPUT]: new TokenAmount(trade?.input.token, maxInput), + [Field.OUTPUT]: new TokenAmount(trade?.output.token, minOutput), } } @@ -42,8 +43,6 @@ export function formatExecutionPrice(trade?: MobiusTrade | MentoTrade, inverted? return '' } return inverted - ? `${trade.executionPrice.invert().toSignificant(6)} ${trade.input.currency.symbol} / ${ - trade.output.currency.symbol - }` - : `${trade.executionPrice.toSignificant(6)} ${trade.output.currency.symbol} / ${trade.input.currency.symbol}` + ? `${trade.executionPrice.invert().toSignificant(6)} ${trade.input.token.symbol} / ${trade.output.token.symbol}` + : `${trade.executionPrice.toSignificant(6)} ${trade.output.token.symbol} / ${trade.input.token.symbol}` } diff --git a/src/utils/stableSwapMath.ts b/src/utils/stableSwapMath.ts index 371ff2673f3..28d1c03adb1 100644 --- a/src/utils/stableSwapMath.ts +++ b/src/utils/stableSwapMath.ts @@ -1,4 +1,5 @@ -import { BigintIsh, JSBI } from '@ubeswap/sdk' +import JSBI from 'jsbi' +import { BigintIsh } from 'lib/token-utils' import { StableSwapMathConstants, StableSwapVariable } from 'state/stablePools/reducer' const ZERO = JSBI.BigInt(0) diff --git a/src/utils/stableSwaps.ts b/src/utils/stableSwaps.ts index 1c6a27754f2..dd504502242 100644 --- a/src/utils/stableSwaps.ts +++ b/src/utils/stableSwaps.ts @@ -1,4 +1,5 @@ -import { JSBI, Token, TokenAmount } from '@ubeswap/sdk' +import JSBI from 'jsbi' +import { Token, TokenAmount } from 'lib/token-utils' import { StablePoolInfo } from '../state/stablePools/hooks' diff --git a/src/utils/tokens.ts b/src/utils/tokens.ts index 0314450fb8a..015a8b2599e 100644 --- a/src/utils/tokens.ts +++ b/src/utils/tokens.ts @@ -1,4 +1,4 @@ -import { Token } from '@ubeswap/sdk' +import { Token } from 'lib/token-utils' /** * Dedupes a list of tokens, picking the first instance of the token in a list. * @param tokens From ca93058995d8bdc7866a9b210be4a724a417cf00 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 23:49:24 -0500 Subject: [PATCH 41/72] cleanup --- src/components/earn/StablePoolCard.tsx | 17 -- src/hooks/index.ts | 22 -- src/hooks/useApproveCallback.ts | 16 +- src/hooks/useColor.ts | 2 - src/hooks/useMento.ts | 0 src/hooks/useMentoCallback.ts | 6 +- src/hooks/useSwapCallback.ts | 14 +- src/pages/App.tsx | 6 +- src/state/application/updater.ts | 1 - src/state/governance/hooks.ts | 1 + src/state/index.ts | 2 - src/state/openSum/reducer.ts | 8 +- src/state/stablePools/actions.ts | 17 -- src/state/stablePools/hooks.ts | 239 ----------------- src/state/stablePools/reducer.ts | 192 -------------- src/state/stablePools/updater.ts | 233 ---------------- src/theme/components.tsx | 10 - src/utils/StablePairMath.ts | 130 --------- src/utils/calcRate.ts | 25 ++ src/utils/currencyId.ts | 5 - src/utils/eth.ts | 8 - src/utils/listSort.ts | 12 - src/utils/stableSwapMath.ts | 350 ------------------------- src/utils/stableSwaps.ts | 48 ---- 24 files changed, 43 insertions(+), 1321 deletions(-) delete mode 100644 src/hooks/useMento.ts delete mode 100644 src/state/stablePools/actions.ts delete mode 100644 src/state/stablePools/hooks.ts delete mode 100644 src/state/stablePools/reducer.ts delete mode 100644 src/state/stablePools/updater.ts delete mode 100644 src/utils/StablePairMath.ts create mode 100644 src/utils/calcRate.ts delete mode 100644 src/utils/currencyId.ts delete mode 100644 src/utils/eth.ts delete mode 100644 src/utils/listSort.ts delete mode 100644 src/utils/stableSwapMath.ts delete mode 100644 src/utils/stableSwaps.ts diff --git a/src/components/earn/StablePoolCard.tsx b/src/components/earn/StablePoolCard.tsx index 04abeada330..418693e3069 100644 --- a/src/components/earn/StablePoolCard.tsx +++ b/src/components/earn/StablePoolCard.tsx @@ -139,23 +139,6 @@ const StyledNavLink = styled(NavLink)<{ color: string }>` textDecoration: underline, ` -export function calcApy(rewardPerYear: Fraction, totalStakedAmount: Fraction) { - const apyFraction = rewardPerYear - .multiply(JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18'))) - .divide(totalStakedAmount) - const apy = apyFraction - ? new Percent( - apyFraction.numerator, - JSBI.multiply(apyFraction.denominator, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18'))) - ) - : undefined - const dpy = - apy && !apy.equalTo('0') - ? new Percent(Math.floor(parseFloat(apy.divide('365').toFixed(10)) * 1_000_000).toFixed(0), '1000000') - : undefined - return [apyFraction, apy, dpy] -} - interface Props { poolInfo: StablePoolInfo } diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 8e7725899ce..71e6f18a5ae 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,23 +1 @@ export * from './web3' - -// export function useActiveContractKit() { -// const kit = useContractKit() -// const { -// address: account, -// network: { chainId }, -// } = kit -// const library = useProvider() -// return { -// ...kit, -// account, -// library, -// chainId, -// } -// } - -// export function useChainId(): number | undefined { -// const { -// network: { chainId }, -// } = useContractKit() -// return chainId -// } diff --git a/src/hooks/useApproveCallback.ts b/src/hooks/useApproveCallback.ts index 6f9ff2a214d..de68b7a61fa 100644 --- a/src/hooks/useApproveCallback.ts +++ b/src/hooks/useApproveCallback.ts @@ -1,13 +1,10 @@ import { MaxUint256 } from '@ethersproject/constants' import { TokenAmount } from 'lib/token-utils' import { useCallback, useMemo } from 'react' -import { MobiusTrade } from 'state/swap/hooks' import { useUserMinApprove } from 'state/user/hooks' import { useTokenAllowance } from '../data/Allowances' -import { Field } from '../state/swap/actions' import { useHasPendingApproval } from '../state/transactions/hooks' -import { computeSlippageAdjustedAmounts } from '../utils/prices' import { useTokenContract } from './useContract' import { useDoTransaction } from './useDoTransaction' import { useWeb3Context } from './web3' @@ -79,13 +76,13 @@ export function useApproveCallback( if (minApprove) { await doTransaction(tokenContract, 'approve', { args: [spender, amountToApprove.raw.toString()], - summary: `Approve ${amountToApprove.toSignificant(6)} ${amountToApprove.currency.symbol}`, + summary: `Approve ${amountToApprove.toSignificant(6)} ${amountToApprove.token.symbol}`, approval: { tokenAddress: token.address, spender: spender }, }) } else { await doTransaction(tokenContract, 'approve', { args: [spender, MaxUint256], - summary: `Approve ${amountToApprove.currency.symbol}`, + summary: `Approve ${amountToApprove.token.symbol}`, approval: { tokenAddress: token.address, spender: spender }, }) } @@ -93,12 +90,3 @@ export function useApproveCallback( return [approvalState, approve] } - -// wraps useApproveCallback in the context of a swap -export function useApproveCallbackFromTrade(trade?: MobiusTrade, allowedSlippage = 0) { - const amountToApprove = useMemo( - () => (trade ? computeSlippageAdjustedAmounts(trade, allowedSlippage)[Field.INPUT] : undefined), - [trade, allowedSlippage] - ) - return useApproveCallback(amountToApprove, trade?.pool.address) -} diff --git a/src/hooks/useColor.ts b/src/hooks/useColor.ts index 3c93a170b7f..64cda5f9def 100644 --- a/src/hooks/useColor.ts +++ b/src/hooks/useColor.ts @@ -63,7 +63,6 @@ async function getColorFromUriPath(uri: string): Promise { // `radial-gradient(91.85% 100% at 1.84% 0%, ${bgColor1} 0%, ${bgColor2} 100%) `}; export function generateGradient(tokens: Token[]) { - const prevColor = '' let colors = tokens.map((t) => useColor(t)) const numColors = colors.length + 1 const increment = 100 / numColors @@ -74,7 +73,6 @@ export function generateGradient(tokens: Token[]) { } export function generateColorPallete(tokens: Token[]) { - const prevColor = '' let colors = tokens.map((t) => useColor(t)) const increment = 100 / colors.length colors = colors.map((color, i) => `${i * increment}% { background: ${color};}`) diff --git a/src/hooks/useMento.ts b/src/hooks/useMento.ts deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/hooks/useMentoCallback.ts b/src/hooks/useMentoCallback.ts index 6539e9ddcc7..bcbc8b819db 100644 --- a/src/hooks/useMentoCallback.ts +++ b/src/hooks/useMentoCallback.ts @@ -67,7 +67,7 @@ function useSwapCallArguments( args: [ trade.input.raw.toString(), minDy.toString(), - trade.input.currency.address.toLowerCase() === CELO[CHAIN].address.toLowerCase() ? 'true' : '', + trade.input.token.address.toLowerCase() === CELO[CHAIN].address.toLowerCase() ? 'true' : '', ], value: '0', } @@ -172,8 +172,8 @@ export function useSwapCallback( gasLimit: calculateGasMargin(gasEstimate), }) .then((response: ContractTransaction) => { - const inputSymbol = trade.input.currency.symbol - const outputSymbol = trade.output.currency.symbol + const inputSymbol = trade.input.token.symbol + const outputSymbol = trade.output.token.symbol const inputAmount = trade.input.toSignificant(6) const outputAmount = trade.output.toSignificant(6) diff --git a/src/hooks/useSwapCallback.ts b/src/hooks/useSwapCallback.ts index 1beeabbc761..39057931ffe 100644 --- a/src/hooks/useSwapCallback.ts +++ b/src/hooks/useSwapCallback.ts @@ -4,6 +4,7 @@ import { SwapParameters } from '@ubeswap/sdk' import { ContractTransaction } from 'ethers' import JSBI from 'jsbi' import { useMemo } from 'react' +import { poolInfoToExchange } from 'state/mobiusPools/hooks' import isZero from 'utils/isZero' import { BIPS_BASE, INITIAL_ALLOWED_SLIPPAGE } from '../constants' @@ -57,12 +58,12 @@ function useSwapCallArguments( return useMemo(() => { if (!trade || !recipient || !provider || !connected || !deadline) return [] - const contract = getStableSwapContract(trade.pool.address, provider, connected) + const contract = getStableSwapContract(poolInfoToExchange(trade.pool).address, provider, connected) const { indexFrom = 0, indexTo = 0 } = trade || {} const outputRaw = trade.output.raw const minDy = JSBI.subtract(outputRaw, JSBI.divide(outputRaw, JSBI.divide(BIPS_BASE, JSBI.BigInt(allowedSlippage)))) const swapCallParameters: SwapParameters = { - methodName: trade.isMeta ? 'swapUnderlying' : 'swap', + methodName: 'swap', args: [ indexFrom.toString(), indexTo.toString(), @@ -134,11 +135,6 @@ export function useSwapCallback( console.debug('Call threw error', call, callError) let errorMessage: string switch (callError.reason) { - case 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT': - case 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT': - errorMessage = - 'This transaction will not succeed either due to price movement or fee on transfer. Try increasing your slippage tolerance.' - break default: errorMessage = `The transaction cannot succeed due to error: ${callError.reason}. This is probably an issue with one of the tokens you are swapping.` } @@ -173,8 +169,8 @@ export function useSwapCallback( gasLimit: gasEstimate, }) .then((response: ContractTransaction) => { - const inputSymbol = trade.input.currency.symbol - const outputSymbol = trade.output.currency.symbol + const inputSymbol = trade.input.token.symbol + const outputSymbol = trade.output.token.symbol const inputAmount = trade.input.toSignificant(6) const outputAmount = trade.output.toSignificant(6) diff --git a/src/pages/App.tsx b/src/pages/App.tsx index c0834443bd8..9a0a77079fe 100644 --- a/src/pages/App.tsx +++ b/src/pages/App.tsx @@ -45,7 +45,7 @@ const BodyWrapper = styled.div` display: flex; flex-direction: column; width: 100%; - ${({ giveSpace }) => giveSpace && `padding-top: 100px;`} + padding-top: 100px; align-items: center; flex: 1; overflow-y: auto; @@ -81,6 +81,7 @@ export default function App() { if (params.get('status') === DappKitResponseStatus.SUCCESS) { localStorage.setItem(localStorageKey, window.location.href) const mobileOS = getMobileOperatingSystem() + // TODO: test the effect of this with h if (mobileOS === Mobile.ANDROID) { window.close() } @@ -94,7 +95,7 @@ export default function App() { return ( - + {location.pathname !== '/' && ( <> @@ -132,7 +133,6 @@ export default function App() { - {/* */} {location.pathname !== '/' && } diff --git a/src/state/application/updater.ts b/src/state/application/updater.ts index 512e6b1750f..49255133bc7 100644 --- a/src/state/application/updater.ts +++ b/src/state/application/updater.ts @@ -26,7 +26,6 @@ const dedupe = (strings: string[]): string[] => { } const fetchPegPrices = async (dispatch: Dispatch) => { - // https://api.coingecko.com/api/v3/simple/price?ids=bitcoin%2Ccelo&vs_currencies=usd const pegQueries = dedupe(StablePools[CHAIN].map(({ peg }) => peg.priceQuery).filter((s) => s !== null) as string[]) const ids = pegQueries.reduce((acc, cur) => acc.concat(cur).concat('%2'), '') const resp = await axios.get( diff --git a/src/state/governance/hooks.ts b/src/state/governance/hooks.ts index f6619770698..912a6dd2ff6 100644 --- a/src/state/governance/hooks.ts +++ b/src/state/governance/hooks.ts @@ -162,6 +162,7 @@ export function useAllProposalData(): { data: ProposalData[]; loading: boolean } // get metadata from past events // early return until events are fetched + // TODO: look at this fix const formattedLogs = useFormattedProposalCreatedLogs(gov, govProposalIndexes) ?? [] return useMemo(() => { const proposalsCallData = proposals diff --git a/src/state/index.ts b/src/state/index.ts index c9f23a61949..6dd42b82295 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -11,7 +11,6 @@ import mentoPools from './mentoPools/reducer' import pools from './mobiusPools/reducer' import multicall from './multicall/reducer' import openSum from './openSum/reducer' -import stablePools from './stablePools/reducer' import staking from './staking/reducer' import swap from './swap/reducer' import transactions from './transactions/reducer' @@ -26,7 +25,6 @@ const store = configureStore({ transactions, swap, multicall, - stablePools, pools, mentoPools, mento, diff --git a/src/state/openSum/reducer.ts b/src/state/openSum/reducer.ts index de7865eb8ac..155e4998fce 100644 --- a/src/state/openSum/reducer.ts +++ b/src/state/openSum/reducer.ts @@ -1,14 +1,14 @@ import { createReducer } from '@reduxjs/toolkit' -import { NETWORK_CHAIN_ID } from 'connectors' import { ConstantSum } from 'constants/ConstantSum' import JSBI from 'jsbi' -import { WrappedTokenInfo } from 'state/lists/hooks' +import { Token } from 'lib/token-utils' +import { CHAIN } from '../../constants' import { updateBalances } from './actions' export type ConstantSumPool = { address: string - tokens: [WrappedTokenInfo, WrappedTokenInfo] + tokens: [Token, Token] balances?: JSBI[] } @@ -17,7 +17,7 @@ export interface PoolState { } const initialState: PoolState = { - pools: ConstantSum[NETWORK_CHAIN_ID] ?? [], + pools: ConstantSum[CHAIN] ?? [], } export default createReducer(initialState, (builder) => diff --git a/src/state/stablePools/actions.ts b/src/state/stablePools/actions.ts deleted file mode 100644 index e5cf344d741..00000000000 --- a/src/state/stablePools/actions.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createAction } from '@reduxjs/toolkit' - -import { ExternalRewards, GaugeOnlyInfo, PoolOnlyInfo, StableSwapConstants, StableSwapVariable } from './reducer' - -export const initPools = createAction<{ pools: StableSwapConstants }>('stablePools/initPools') - -export const updateVariableData = createAction<{ address: string; variableData: StableSwapVariable }>( - 'stablePools/updateVariableData' -) - -export const updateExternalRewards = createAction<{ pool: string; externalRewards: ExternalRewards[] }>( - 'stablePools/updateExternalRewards' -) - -export const updatePools = createAction<{ info: PoolOnlyInfo[] }>('stablePools/updatePools') - -export const updateGauges = createAction<{ info: GaugeOnlyInfo[] }>('stablePools/updateGauges') diff --git a/src/state/stablePools/hooks.ts b/src/state/stablePools/hooks.ts deleted file mode 100644 index 4315048b3a3..00000000000 --- a/src/state/stablePools/hooks.ts +++ /dev/null @@ -1,239 +0,0 @@ -// // To-Do: Implement Hooks to update Client-Side contract representation -// import { Chain, Coins } from 'constants/StablePools' -// import { useWeb3Context } from 'hooks' -// import { addressToToken } from 'hooks/Tokens' -// import { useLiquidityGaugeContract, useStableSwapContract } from 'hooks/useContract' -// import { JSBI, Percent, Token, TokenAmount } from 'lib/token-utils' -// import { useEffect, useMemo, useState } from 'react' -// import { useSelector } from 'react-redux' -// import { useSingleContractMultipleData } from 'state/multicall/hooks' -// import { tryParseAmount } from 'state/swap/hooks' -// import invariant from 'tiny-invariant' -// import { PairStableSwap } from 'utils/StablePairMath' - -// import WARNINGS from '../../constants/PoolWarnings.json' -// import { StableSwapMath } from '../../utils/stableSwapMath' -// import { AppState } from '..' -// import { StableSwapPool, WarningType } from './reducer' -// import { BigIntToJSBI } from './updater' - -// export type WarningModifications = 'require-equal-deposit' | 'none' - -// export interface StablePoolInfo { -// readonly name: string -// readonly poolAddress?: string -// readonly stakingToken?: Token -// readonly lpToken?: Token -// readonly tokens: readonly Token[] -// readonly amountDeposited?: TokenAmount -// readonly totalDeposited: TokenAmount -// readonly apr?: TokenAmount -// readonly totalStakedAmount?: TokenAmount -// readonly workingSupply?: JSBI -// readonly stakedAmount: TokenAmount -// readonly totalVolume?: TokenAmount -// readonly peggedTo: string -// readonly displayDecimals: number -// readonly virtualPrice: JSBI -// readonly priceOfStaked: TokenAmount -// readonly balances: TokenAmount[] -// readonly pegComesAfter: boolean | undefined -// readonly mobiRate: JSBI | undefined -// readonly pendingMobi: JSBI | undefined -// readonly gaugeAddress?: string -// readonly workingPercentage: Percent -// readonly totalPercentage: Percent -// readonly externalRewardRates?: TokenAmount[] -// readonly lastClaim?: Date -// readonly meta?: string -// readonly displayChain: Chain -// readonly coin: Coins -// readonly isDisabled?: boolean -// readonly weeklyVolume?: TokenAmount -// readonly poolLoading: boolean -// readonly gaugeLoading: boolean -// readonly isKilled?: boolean -// } - -// const tokenAmountScaled = (token: Token, amount: JSBI): TokenAmount => -// new TokenAmount(token, JSBI.divide(amount, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt(token.decimals)))) - -// export const getPoolInfo = (pool: StableSwapPool): StablePoolInfo | Record | undefined => { -// const external = -// pool.additionalRewardRate?.map((rate, i) => { -// const token = addressToToken(pool.additionalRewards?.[i]) -// invariant(token) -// return new TokenAmount(token, rate) -// }) ?? undefined -// return !pool.lpTotalSupply -// ? undefined -// : { -// name: pool.name, -// poolAddress: pool.address, -// lpToken: pool.lpToken, -// tokens: pool.tokens, -// amountDeposited: new TokenAmount( -// pool.lpToken, -// JSBI.add(pool.lpOwned ?? JSBI.BigInt('0'), pool.userStaked ?? JSBI.BigInt('0')) -// ), -// totalDeposited: new TokenAmount(pool.lpToken, pool.lpTotalSupply ?? JSBI.BigInt('0')), -// stakedAmount: new TokenAmount(pool.lpToken, pool.userStaked || JSBI.BigInt('0')), -// apr: new TokenAmount(pool.lpToken, JSBI.BigInt('100000000000000000')), -// peggedTo: pool.peggedTo, -// virtualPrice: pool.virtualPrice, -// priceOfStaked: tokenAmountScaled( -// pool.lpToken, -// JSBI.multiply( -// pool.virtualPrice ?? JSBI.BigInt('0'), -// JSBI.add(pool.lpOwned ?? JSBI.BigInt('0'), pool.userStaked ?? JSBI.BigInt('0')) -// ) -// ), -// workingSupply: pool.workingLiquidity, -// balances: pool.tokens.map( -// (token, i) => new TokenAmount(token, pool.balances?.[i] ?? pool.approxBalances?.[i] ?? '0') -// ), -// pegComesAfter: pool.pegComesAfter, -// mobiRate: pool.isKilled ? JSBI.BigInt('0') : pool.totalMobiRate, -// pendingMobi: pool.pendingMobi, -// gaugeAddress: pool.gaugeAddress, -// displayDecimals: pool.displayDecimals, -// totalStakedAmount: new TokenAmount(pool.lpToken, pool.totalStakedAmount ?? '0'), -// workingPercentage: new Percent(pool.effectiveBalance, pool.totalEffectiveBalance), -// totalPercentage: new Percent(pool.userStaked ?? '0', pool.totalStakedAmount ?? '1'), -// externalRewardRates: external, -// lastClaim: pool.lastClaim, -// meta: pool.metaPool, -// displayChain: pool.displayChain, -// coin: pool.coin, -// isDisabled: pool.disabled, -// isKilled: pool.isKilled, -// weeklyVolume: pool.volume ? tryParseAmount(pool.volume.week.toFixed(6), pool.lpToken) : undefined, -// totalVolume: pool.volume ? tryParseAmount(pool.volume.total?.toFixed(6), pool.lpToken) : undefined, -// poolLoading: pool.loadingPool, -// gaugeLoading: pool.loadingGauge, -// } -// } - -// export function useStablePoolInfoByName(name: string): StablePoolInfo | undefined { -// const pool = useSelector((state) => state.stablePools.pools[name.toLowerCase()]?.pool) -// return !pool ? undefined : { ...getPoolInfo(pool) } -// } - -// export function useStablePoolInfo(): readonly StablePoolInfo[] { -// const pools = usePools() -// return pools.map((pool) => getPoolInfo(pool)).filter((el) => el) -// } - -// export function useExpectedTokens(pool: StablePoolInfo, lpAmount: TokenAmount): TokenAmount[] { -// const contract = useStableSwapContract(pool.poolAddress) -// const { tokens } = pool -// const { address } = useWeb3Context() -// const [expectedOut, setExpectedOut] = useState( -// tokens.map((token) => new TokenAmount(token, JSBI.BigInt('0'))) -// ) -// useEffect(() => { -// const updateData = async () => { -// try { -// const newTokenAmounts = await contract?.calculateRemoveLiquidity(address, lpAmount.raw.toString()) -// setExpectedOut(tokens.map((token, i) => new TokenAmount(token, JSBI.BigInt(newTokenAmounts[i].toString())))) -// } catch (e) { -// console.error(e) -// setExpectedOut(tokens.map((token, i) => new TokenAmount(token, JSBI.BigInt('0')))) -// } -// } -// lpAmount && lpAmount.raw && updateData() -// }, [address, contract, lpAmount, tokens]) -// return expectedOut -// } - -// export function useExpectedLpTokens( -// pool: StablePoolInfo, -// tokens: Token[], -// input: (string | undefined)[], -// isDeposit = true -// ): [TokenAmount, TokenAmount[]] { -// const mathUtil = useMathUtil(pool.poolAddress ?? pool.address) -// const tokenAmounts = useMemo( -// () => tokens.map((t, i) => tryParseAmount(input[i], t) ?? new TokenAmount(t, '0')), -// [input] -// ) - -// return useMemo(() => { -// const allZero = tokenAmounts.reduce((accum, cur) => accum && cur.equalTo('0'), true) -// if (allZero) { -// return [new TokenAmount(pool.lpToken, '0'), tokenAmounts] -// } - -// if (!pool.totalDeposited || pool.totalDeposited.equalTo('0')) { -// const amount = -// tryParseAmount( -// tokenAmounts.reduce((accum, cur) => (parseFloat(accum) + parseFloat(cur.toExact())).toString(), '0'), -// pool.lpToken -// ) ?? new TokenAmount(pool.lpToken, '0') - -// return [amount, tokenAmounts] -// } -// const amount = -// mathUtil?.calculateTokenAmount( -// tokenAmounts.map((ta) => ta?.raw || JSBI.BigInt('0')), -// isDeposit -// ) ?? JSBI.BigInt('0') -// return [new TokenAmount(pool.lpToken, amount), tokenAmounts] -// }, [input, mathUtil, tokenAmounts]) -// } - -// export function useMathUtil(pool: StableSwapPool | string): StableSwapMath | undefined { -// const name = !pool ? '' : typeof pool == 'string' ? pool : pool.address -// const math = useSelector((state) => state.stablePools.pools[name.toLowerCase()]?.math) -// return math -// } - -// // export function usePriceOfLp(address: string, amountOfLp: TokenAmount): TokenAmount | undefined { -// // const pool = useStablePoolInfoByName(address) -// // const price = useEthBtcPrice(pool?.poolAddress ?? '') -// // return pool && price && amountOfLp -// // ? new TokenAmount( -// // amountOfLp.token, -// // JSBI.divide( -// // JSBI.multiply(amountOfLp.raw, JSBI.multiply(pool?.virtualPrice, price)), -// // JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) -// // ) -// // ) -// // : undefined -// // } - -// export function useExternalRewards({ address }: { address: string }): TokenAmount[] { -// const pool = useSelector((state) => state.stablePools.pools[address.toLowerCase()]?.pool) -// const gauge = useLiquidityGaugeContract(pool?.gaugeAddress ?? undefined) -// const { address: userAddress, connected } = useWeb3Context() -// gauge?.claimable_reward_write -// const claimableTokens = useSingleContractMultipleData( -// gauge, -// 'claimable_reward_write', -// pool?.additionalRewards?.map((token) => [connected ? userAddress : undefined, token ?? undefined]) ?? undefined -// ) -// // console.log(claimableTokens) -// const externalRewards = claimableTokens?.map((result, i) => { -// const token = addressToToken(pool.additionalRewards?.[i]) -// invariant(token) -// return new TokenAmount(token, BigIntToJSBI(result?.result?.[0] ?? '0', '0') ?? '0') -// }) -// return externalRewards -// } - -// export function useWarning( -// pool: string | undefined -// ): { warning: string; link?: string; modification?: WarningModifications } | undefined { -// const warningType = useSelector( -// (state) => state.stablePools.pools[pool?.toLowerCase() ?? '']?.pool?.warningType ?? undefined -// ) -// if (!warningType) return undefined -// return WARNINGS[warningType] as any as { warning: string; link?: string; modification?: WarningModifications } -// } - -// export function usePairUtil(pool?: StableSwapPool | string): PairStableSwap | undefined { -// const name = !pool ? '' : typeof pool == 'string' ? pool : pool.address -// return useSelector((state) => state.stablePools.pools[name.toLowerCase()]?.pair) -// } - -export {} diff --git a/src/state/stablePools/reducer.ts b/src/state/stablePools/reducer.ts deleted file mode 100644 index 028aef4bf68..00000000000 --- a/src/state/stablePools/reducer.ts +++ /dev/null @@ -1,192 +0,0 @@ -import { createReducer, current } from '@reduxjs/toolkit' -import { NETWORK_CHAIN_ID } from 'connectors' -import { Chain, Coins, STATIC_POOL_INFO } from 'constants/StablePools' -import JSBI from 'jsbi' -import { Fraction, Percent, Token } from 'lib/token-utils' -import { PairStableSwap } from 'utils/StablePairMath' -import { StableSwapMath } from 'utils/stableSwapMath' - -import { updateExternalRewards, updateGauges, updatePools } from './actions' - -const ZERO = JSBI.BigInt('0') -export enum WarningType { - POOF = 'poof', -} - -export type ExternalRewards = { - token: string - unclaimed: JSBI -} - -export type PoolOnlyInfo = { - id: string - volume: { - total: number - day: number - week: number - } - approxBalances: JSBI[] - balances: JSBI[] - amp: JSBI - virtualPrice: JSBI - aPrecise: JSBI - lpTotalSupply: JSBI - lpOwned: JSBI - loadingPool: boolean -} - -export type GaugeOnlyInfo = { - id: string - userStaked: JSBI - totalStakedAmount: JSBI - totalMobiRate: JSBI - pendingMobi: JSBI - workingLiquidity: JSBI - poolWeight: Percent - effectiveBalance: JSBI - totalEffectiveBalance: JSBI - lastUserVote: number - powerAllocated: number - futureWeight: JSBI - externalRewards?: ExternalRewards[] - gaugeAddress?: string - relativeGaugeWeight?: Fraction - lastClaim: Date -} - -export type StableSwapVariable = PoolOnlyInfo & GaugeOnlyInfo - -export type StableSwapMathConstants = { - name: string - rates: JSBI[] - lendingPrecision: JSBI - precision: JSBI - feeDenominator: JSBI - precisionMul: JSBI[] - feeIndex: number - decimals: JSBI[] - swapFee: JSBI -} - -export type StableSwapConstants = StableSwapMathConstants & { - tokens: Token[] - tokenAddresses: string[] - address: string - gaugeAddress: string - lpToken: Token - peggedTo: string - pegComesAfter: boolean | undefined - displayDecimals: number - additionalRewards?: string[] - additionalRewardRate?: string[] - lastClaim?: Date - displayChain: Chain - coin: Coins - disabled?: boolean - metaPool?: string - isKilled?: boolean - warningType?: WarningType -} - -export type StableSwapPool = StableSwapConstants & StableSwapVariable -export interface PoolState { - readonly pools: { - [address: string]: { - rehydrate?: boolean - pool: StableSwapPool | StableSwapConstants - math: StableSwapMath | undefined - pair?: PairStableSwap | undefined - } - } -} - -const initialState: PoolState = { - pools: Object.values(STATIC_POOL_INFO[NETWORK_CHAIN_ID]).reduce( - ( - accum: { - [address: string]: { - pool: StableSwapConstants - math: StableSwapMath | undefined - } - }, - cur: StableSwapConstants - ) => ({ - ...accum, - [cur.address.toLowerCase()]: { - pool: { - ...cur, - rehydrate: true, - balances: Array(cur.tokenAddresses.length).fill(ZERO), - userStaked: ZERO, - totalStakedAmount: ZERO, - totalMobiRate: ZERO, - pendingMobi: ZERO, - workingLiquidity: ZERO, - virtualPrice: ZERO, - poolWeight: new Percent('0', '1'), - effectiveBalance: ZERO, - totalEffectiveBalance: ZERO, - futureWeight: ZERO, - lpTotalSupply: ZERO, - lpOwned: ZERO, - loadingGauge: true, - loadingPool: true, - volume: { - day: 0, - week: 0, - }, - }, - math: undefined, - }, - }), - {} - ), -} - -export default createReducer(initialState, (builder) => - builder - .addCase(updateExternalRewards, (state, { payload: { pool, externalRewards } }) => { - if (!state.pools[pool].math) return - state.pools[pool].pool.externalRewards = externalRewards - }) - .addCase(updatePools, (state, { payload: { info } }) => { - const copiedState = current(state) - info.forEach((pool) => { - const cur = copiedState.pools[pool.id].pool as any as StableSwapPool - const newPool = { ...cur, ...pool } - const { balances, aPrecise, swapFee, tokens } = newPool - // console.log( - // balances?.map((el) => el.toString()) ?? ['0', '0'], - // swapFee?.toString() ?? '0', - // aPrecise?.toString() ?? '0' - // ) - const math = new StableSwapMath(newPool) - const pair = - balances && aPrecise && swapFee - ? new PairStableSwap( - balances?.map((el) => el.toString()) ?? ['0', '0'], - swapFee?.toString() ?? '0', - aPrecise?.toString() ?? '0', - tokens.map((t) => t.decimals) - ) - : undefined - - state.pools[pool.id] = { - pool: newPool, - math, - pair, - } - }) - }) - .addCase(updateGauges, (state, { payload: { info } }) => { - const copiedState = current(state) - info.forEach((gauge) => { - const cur = copiedState.pools[gauge.id].pool as any as StableSwapPool - const newPool = { ...cur, ...gauge, loadingGauge: false } - state.pools[gauge.id] = { - pool: newPool, - math: state.pools[gauge.id].math, - } - }) - }) -) diff --git a/src/state/stablePools/updater.ts b/src/state/stablePools/updater.ts deleted file mode 100644 index 996396883a1..00000000000 --- a/src/state/stablePools/updater.ts +++ /dev/null @@ -1,233 +0,0 @@ -// import { gql, useQuery } from '@apollo/client' -// import { Interface } from '@ethersproject/abi' -// import { JSBI, Percent } from 'lib/token-utils' -// import { useMemo } from 'react' -// import { useDispatch, useSelector } from 'react-redux' -// import { useBlockNumber } from 'state/application/hooks' -// import { -// useMultipleContractSingleData, -// useSingleCallResult, -// useSingleContractMultipleData, -// } from 'state/multicall/hooks' - -// import { CHAIN } from '../../constants' -// import GAUGE_V3 from '../../constants/abis/LiquidityGaugeV3.json' -// import LP from '../../constants/abis/LPToken.json' -// import SWAP from '../../constants/abis/Swap.json' -// import { STATIC_POOL_INFO } from '../../constants/StablePools' -// import { useWeb3Context } from '../../hooks' -// import { useGaugeControllerContract, useMobiContract } from '../../hooks/useContract' -// import { AppDispatch, AppState } from '../index' -// import { updateGauges, updatePools } from './actions' -// import { GaugeOnlyInfo, PoolOnlyInfo, StableSwapConstants } from './reducer' - -// const SwapInterface = new Interface(SWAP.abi) -// const lpInterface = new Interface(LP.abi) -// const gaugeInterface = new Interface(GAUGE_V3.abi) - -// export const BigIntToJSBI = (num: BigInt | undefined, fallBack = '0') => { -// return JSBI.BigInt(num?.toString() ?? fallBack) -// } - -// export function UpdateVariablePoolInfo(): null { -// const { connected, address } = useWeb3Context() -// const blockNumber = useBlockNumber() -// const dispatch = useDispatch() -// const pools: StableSwapConstants[] = useSelector((state: AppState) => -// Object.values(state.stablePools.pools).map(({ pool }) => pool) -// ) -// const poolAddresses = pools.map(({ address }) => address) -// const lpTokenAddresses = pools.map(({ lpToken: { address } }) => address) -// const lpTotalSupplies = useMultipleContractSingleData(lpTokenAddresses, lpInterface, 'totalSupply') -// const lpOwned_multiple = useMultipleContractSingleData(lpTokenAddresses, lpInterface, 'balanceOf', [ -// connected ? address : undefined, -// ]) -// const virtualPrices = useMultipleContractSingleData(poolAddresses, SwapInterface, 'getVirtualPrice') -// const balances = useMultipleContractSingleData(poolAddresses, SwapInterface, 'getBalances') -// const amplificationCoefficients = useMultipleContractSingleData(poolAddresses, SwapInterface, 'getAPrecise') -// const query = gql` -// { -// swaps { -// id -// A -// balances -// virtualPrice -// dailyVolumes(orderBy: timestamp, orderDirection: desc) { -// volume -// } -// weeklyVolumes(first: 2, orderBy: timestamp, orderDirection: desc) { -// volume -// } -// } -// } -// ` -// const { data, loading, error } = useQuery(query) -// const lpInfo: { -// [address: string]: { total: JSBI; user: JSBI; virtualPrice: JSBI; balances: JSBI[]; aPrecise: JSBI } -// } = lpTotalSupplies -// .filter((total, i) => !(total?.loading || lpOwned_multiple[i]?.loading)) -// .map((total, i) => [ -// BigIntToJSBI((total?.result?.[0] as BigInt) ?? '0'), -// BigIntToJSBI((lpOwned_multiple?.[i]?.result?.[0] as BigInt) ?? '0'), -// BigIntToJSBI((virtualPrices?.[i]?.result?.[0] as BigInt) ?? '0'), -// balances?.[i]?.result?.[0] ? balances?.[i]?.result?.[0].map((amt: BigInt): JSBI => BigIntToJSBI(amt)) : undefined, -// poolAddresses[i], -// BigIntToJSBI((amplificationCoefficients?.[i]?.result?.[0] as BigInt) ?? '50'), -// ]) -// .reduce( -// (accum, [total, user, virtualPrice, balances, address, aPrecise]) => ({ -// ...accum, -// [(address as any as string).toLowerCase()]: { total, user, balances, virtualPrice, aPrecise }, -// }), -// {} -// ) -// const inSubgraph: Set = -// data?.swaps.reduce((accum: Set, cur: any) => new Set([...accum, cur.id]), new Set()) ?? new Set() -// const poolsNotInSubgraph = poolAddresses.map((a) => a.toLowerCase()).filter((addr) => !inSubgraph.has(addr)) -// return useMemo(() => { -// if (error) console.log(error) -// if (loading) return null -// const poolInfo: PoolOnlyInfo[] = data.swaps -// .filter(({ id }) => !!lpInfo[id]) -// .map((pool) => ({ -// id: pool.id, -// volume: { -// total: pool.dailyVolumes.reduce((accum: number, el: string) => accum + parseFloat(el.volume), 0), -// day: parseFloat(pool.dailyVolumes[0]?.volume ?? '0'), -// week: parseFloat(pool.weeklyVolumes[0]?.volume ?? '0'), -// }, -// approxBalances: pool.balances.map((b: string) => JSBI.BigInt(b)), -// balances: lpInfo[pool.id].balances ? lpInfo[pool.id].balances : undefined, -// aPrecise: lpInfo[pool.id].aPrecise, -// virtualPrice: lpInfo[pool.id].virtualPrice, -// lpTotalSupply: lpInfo[pool.id].total, -// lpOwned: lpInfo[pool.id].user, -// loadingPool: !lpInfo[pool.id].total, -// })) - -// dispatch( -// updatePools({ -// info: -// poolsNotInSubgraph.length > 0 -// ? poolInfo.concat( -// poolsNotInSubgraph.map((id) => ({ -// id, -// volume: { -// total: undefined, -// day: undefined, -// week: undefined, -// }, -// balances: lpInfo[id]?.total ? lpInfo[id].balances : undefined, -// aPrecise: JSBI.BigInt(50 * 100), -// virtualPrice: lpInfo[id]?.virtualPrice, -// lpTotalSupply: lpInfo[id]?.total ?? JSBI.BigInt('1'), -// lpOwned: lpInfo[id]?.user ?? JSBI.BigInt('0'), -// loadingPool: !lpInfo[id]?.total, -// approxBalances: lpInfo[id]?.total ? lpInfo[id].balances : undefined, -// })) -// ) -// : poolInfo, -// }) -// ) -// return null -// }, [data, loading, error, dispatch, blockNumber]) -// } - -// export function BatchUpdateGauges(): null { -// const { address, connected } = useWeb3Context() -// const blockNumber = useBlockNumber() -// const dispatch = useDispatch() -// const pools: StableSwapConstants[] = STATIC_POOL_INFO[CHAIN] ?? [] -// const gaugeAddresses = pools.map(({ gaugeAddress }) => gaugeAddress) -// const gaugeController = useGaugeControllerContract() -// const mobiContract = useMobiContract() - -// const totalStakedAmount_multi = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'totalSupply') -// const lpStaked_multi = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'balanceOf', [ -// connected ? address : undefined, -// ]) -// const workingLiquidityMulti = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_supply') -// const pendingMobi_multi = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'claimable_tokens', [ -// connected ? address : undefined, -// ]) -// const mobiRate: JSBI = BigIntToJSBI(useSingleCallResult(mobiContract, 'rate')?.result?.[0] ?? '0') -// const weights = useSingleContractMultipleData( -// gaugeController, -// 'gauge_relative_weight(address)', -// gaugeAddresses.map((a) => [a ?? undefined]) -// ) -// const futureWeights = useSingleContractMultipleData( -// gaugeController, -// 'get_gauge_weight', -// gaugeAddresses.map((a) => [a ?? undefined]) -// ) - -// const lastClaims = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'last_claim') - -// const effectiveBalances = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_balances', [ -// connected ? address : undefined, -// ]) -// const totalEffectiveBalances = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_supply') -// const lastVote = useSingleContractMultipleData( -// gaugeController, -// 'last_user_vote', -// gaugeAddresses.map((a) => [connected ? address : a, a]) -// ) -// // vote_user_slopes -// const slope = useSingleContractMultipleData( -// gaugeController, -// 'vote_user_slopes', -// gaugeAddresses.map((a) => [connected ? address : a, a]) -// ) - -// useMemo(() => { -// dispatch( -// updateGauges({ -// info: pools -// .filter((_, i) => !(totalStakedAmount_multi?.[i]?.loading ?? true)) -// .map((poolInfo, i) => { -// const effectiveBalance: JSBI = BigIntToJSBI((effectiveBalances?.[i]?.result?.[0] as BigInt) ?? '0') -// const totalEffectiveBalance: JSBI = BigIntToJSBI( -// (totalEffectiveBalances?.[i]?.result?.[0] as BigInt) ?? '1' -// ) -// const lpStaked: JSBI = BigIntToJSBI((lpStaked_multi?.[i]?.result?.[0] as BigInt) ?? '0') -// const pendingMobi: JSBI = BigIntToJSBI((pendingMobi_multi?.[i]?.result?.[0] as BigInt) ?? '0') -// const weight: JSBI = BigIntToJSBI((weights?.[i]?.result?.[0] as BigInt) ?? '0') -// const futureWeight: JSBI = BigIntToJSBI((futureWeights?.[i]?.result?.[0] as BigInt) ?? '0') -// const totalStakedAmount: JSBI = BigIntToJSBI((totalStakedAmount_multi?.[i]?.result?.[0] as BigInt) ?? '0') -// const workingLiquidity: JSBI = BigIntToJSBI((workingLiquidityMulti?.[i]?.result?.[0] as BigInt) ?? '0') -// const lastUserVote: number = parseInt((lastUserVotes?.[i]?.result?.[0] ?? BigInt('0')).toString() ?? '0') -// const lastClaim: Date = new Date( -// parseInt((lastClaims?.[i]?.result?.[0] ?? BigInt('0')).toString() ?? '0') * 1000 -// ) -// const powerAllocated: number = parseInt((slopes?.[i]?.result?.[1] ?? BigInt('0')).toString() ?? '0') - -// const totalMobiRate = JSBI.divide( -// poolInfo.disabled ? JSBI.BigInt('0') : JSBI.multiply(mobiRate, weight), -// JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) -// ) - -// const collectedData: GaugeOnlyInfo = { -// id: poolInfo.address.toLowerCase(), -// poolWeight: new Percent(weight, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18'))), -// userStaked: lpStaked, -// pendingMobi, -// totalMobiRate, -// totalStakedAmount, -// workingLiquidity, -// effectiveBalance, -// totalEffectiveBalance, -// lastUserVote, -// futureWeight, -// lastClaim, -// powerAllocated: powerAllocated / 100, -// } -// return collectedData -// }), -// }) -// ) -// }, [blockNumber, dispatch]) -// return null -// } - -export {} diff --git a/src/theme/components.tsx b/src/theme/components.tsx index a8470b01a6a..f38d065b13d 100644 --- a/src/theme/components.tsx +++ b/src/theme/components.tsx @@ -200,16 +200,6 @@ export const TrashIcon = styled(Trash)` } ` -const rotateImg = keyframes` - 0% { - transform: perspective(1000px) rotateY(0deg); - } - - 100% { - transform: perspective(1000px) rotateY(360deg); - } -` - export const UbeTokenAnimated = styled.img` padding: 2rem 0 1rem 0; filter: drop-shadow(0px 2px 4px rgba(0, 0, 0, 0.15)); diff --git a/src/utils/StablePairMath.ts b/src/utils/StablePairMath.ts deleted file mode 100644 index 5b7a232b900..00000000000 --- a/src/utils/StablePairMath.ts +++ /dev/null @@ -1,130 +0,0 @@ -import BigNumber from 'bignumber.js' -import JSBI from 'jsbi' - -// See https://github.com/d-mooers/swappa/blob/main/src/pairs/stableswap.ts - -type Address = string -export class PairStableSwap { - allowRepeats = false - - private paused = false - private tokenPrecisionMultipliers: BigNumber[] = [] - private balancesWithAdjustedPrecision: BigNumber[] = [] - private balances: BigNumber[] = [] - private swapFee: BigNumber = new BigNumber(0) - private preciseA: BigNumber = new BigNumber(0) - private lpTotalSupply: BigNumber = new BigNumber(0) - - static readonly POOL_PRECISION_DECIMALS = 18 - static readonly A_PRECISION = 100 - - constructor(balances: string[], swapFee: string, preciseA: string, decimals: number[]) { - const [decimalsA, decimalsB] = decimals - this.tokenPrecisionMultipliers = [ - new BigNumber(10).pow(PairStableSwap.POOL_PRECISION_DECIMALS - decimalsA), - new BigNumber(10).pow(PairStableSwap.POOL_PRECISION_DECIMALS - decimalsB), - ] - this.balances = balances.map((n) => new BigNumber(n)) - this.balancesWithAdjustedPrecision = balances.map((b, idx) => this.tokenPrecisionMultipliers[idx].multipliedBy(b)) - this.swapFee = new BigNumber(swapFee).div(new BigNumber(10).pow(10)) - this.preciseA = new BigNumber(preciseA) - } - - public deposit( - tokenA: Address, - inputA: BigNumber, - tokenB: Address, - inputB: BigNumber, - isDeposit: boolean - ): BigNumber { - const amounts = tokenA === this.tokenA ? [inputA, inputB] : [inputB, inputA] - const d0 = this.getD(this.balancesWithAdjustedPrecision, this.preciseA) - const balances = this.balances.map((b, i) => (isDeposit ? b.plus(amounts[i]) : b.minus(amounts[i]))) - const d1 = this.getD( - balances.map((b, idx) => this.tokenPrecisionMultipliers[idx].multipliedBy(b)), - this.preciseA - ) - - return d1.minus(d0).multipliedBy(this.lpTotalSupply).dividedBy(d0) - } - - public outputAmount(tokenIndexFrom: number, tokenIndexTo: number, input: JSBI): [JSBI, JSBI] { - // See: https://github.com/mobiusAMM/mobiusV1/blob/master/contracts/SwapUtils.sol#L617 - const inputAmount = new BigNumber(input.toString()) - const x = inputAmount - .multipliedBy(this.tokenPrecisionMultipliers[tokenIndexFrom]) - .plus(this.balancesWithAdjustedPrecision[tokenIndexFrom]) - const y = this.getY(x, this.balancesWithAdjustedPrecision, this.preciseA) - const outputAmountWithFee = this.balancesWithAdjustedPrecision[tokenIndexTo].minus(y).minus(1) - const fee = outputAmountWithFee.multipliedBy(this.swapFee) - const outputAmount = outputAmountWithFee.minus(fee).div(this.tokenPrecisionMultipliers[tokenIndexTo]).integerValue() - return [JSBI.BigInt(outputAmount.toFixed(0)), JSBI.BigInt(fee.toFixed(0))] - } - - private getY = (x: BigNumber, xp: BigNumber[], a: BigNumber) => { - // See: https://github.com/mobiusAMM/mobiusV1/blob/master/contracts/SwapUtils.sol#L531 - const d = this.getD(xp, a) - const nTokens = xp.length - const nA = a.multipliedBy(nTokens) - - const s = x - const c = d - .multipliedBy(d) - .div(x.multipliedBy(nTokens)) - .integerValue() - .multipliedBy(d) - .multipliedBy(PairStableSwap.A_PRECISION) - .div(nA.multipliedBy(nTokens)) - .integerValue() - const b = s.plus(d.multipliedBy(PairStableSwap.A_PRECISION).div(nA)).integerValue() - - let yPrev - let y = d - for (let i = 0; i < 256; i++) { - yPrev = y - y = y.multipliedBy(y).plus(c).div(y.multipliedBy(2).plus(b).minus(d)).integerValue() - if (y.minus(yPrev).abs().lte(1)) { - return y - } - } - throw new Error('SwapPool approximation did not converge!') - } - - private getD(xp: BigNumber[], a: BigNumber) { - // See: https://github.com/mobiusAMM/mobiusV1/blob/master/contracts/SwapUtils.sol#L393 - const s = BigNumber.sum(...xp) - if (s.eq(0)) { - return s - } - - let prevD - let d = s - const nTokens = xp.length - const nA = a.multipliedBy(nTokens) - - for (let i = 0; i < 256; i++) { - let dP = d - xp.forEach((x) => { - dP = dP.multipliedBy(d).div(x.multipliedBy(nTokens)).integerValue() - }) - prevD = d - d = nA - .multipliedBy(s) - .div(PairStableSwap.A_PRECISION) - .plus(dP.multipliedBy(nTokens)) - .multipliedBy(d) - .div( - nA - .minus(PairStableSwap.A_PRECISION) - .multipliedBy(d) - .div(PairStableSwap.A_PRECISION) - .plus(new BigNumber(nTokens).plus(1).multipliedBy(dP)) - ) - .integerValue() - if (d.minus(prevD).abs().lte(1)) { - return d - } - } - throw new Error('SwapPool D does not converge!') - } -} diff --git a/src/utils/calcRate.ts b/src/utils/calcRate.ts new file mode 100644 index 00000000000..71d900163f3 --- /dev/null +++ b/src/utils/calcRate.ts @@ -0,0 +1,25 @@ +import JSBI from 'jsbi' +import { Fraction, Percent } from 'lib/token-utils' + +type Rates = { + apyF: Fraction + apy: Percent + dyp: Percent +} + +export function calcApy(rewardPerYear: Fraction, totalStakedAmount: Fraction): Rates { + const apyFraction = rewardPerYear + .multiply(JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18'))) + .divide(totalStakedAmount) + const apy = apyFraction + ? new Percent( + apyFraction.numerator, + JSBI.multiply(apyFraction.denominator, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18'))) + ) + : undefined + const dpy = + apy && !apy.equalTo('0') + ? new Percent(Math.floor(parseFloat(apy.divide('365').toFixed(10)) * 1_000_000).toFixed(0), '1000000') + : undefined + return { apyFraction, apy, dpy } +} diff --git a/src/utils/currencyId.ts b/src/utils/currencyId.ts deleted file mode 100644 index 8d85d93f3ab..00000000000 --- a/src/utils/currencyId.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Token } from 'lib/token-utils' - -export function currencyId(currency: Token): string { - return currency.address -} diff --git a/src/utils/eth.ts b/src/utils/eth.ts deleted file mode 100644 index 7a0547c5f55..00000000000 --- a/src/utils/eth.ts +++ /dev/null @@ -1,8 +0,0 @@ -import BN from 'bn.js' -import { fromWei } from 'web3-utils' - -import { humanFriendlyNumber } from './number' - -export const humanFriendlyWei = (wei: BN | string) => { - return humanFriendlyNumber(fromWei(wei)) -} diff --git a/src/utils/listSort.ts b/src/utils/listSort.ts deleted file mode 100644 index 7672da194dd..00000000000 --- a/src/utils/listSort.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { DEFAULT_LIST_OF_LISTS } from './../constants/lists' - -// use ordering of default list of lists to assign priority -export default function sortByListPriority(urlA: string, urlB: string) { - const first = DEFAULT_LIST_OF_LISTS.includes(urlA) ? DEFAULT_LIST_OF_LISTS.indexOf(urlA) : Number.MAX_SAFE_INTEGER - const second = DEFAULT_LIST_OF_LISTS.includes(urlB) ? DEFAULT_LIST_OF_LISTS.indexOf(urlB) : Number.MAX_SAFE_INTEGER - - // need reverse order to make sure mapping includes top priority last - if (first < second) return 1 - else if (first > second) return -1 - return 0 -} diff --git a/src/utils/stableSwapMath.ts b/src/utils/stableSwapMath.ts deleted file mode 100644 index 28d1c03adb1..00000000000 --- a/src/utils/stableSwapMath.ts +++ /dev/null @@ -1,350 +0,0 @@ -import JSBI from 'jsbi' -import { BigintIsh } from 'lib/token-utils' -import { StableSwapMathConstants, StableSwapVariable } from 'state/stablePools/reducer' - -const ZERO = JSBI.BigInt(0) -const ONE = JSBI.BigInt(1) -const TWO = JSBI.BigInt(2) -export class StableSwapMath { - public readonly RATES: JSBI[] - public readonly LENDING_PRECISION: JSBI - public readonly PRECISION: JSBI - public readonly FEE_DENOMINATOR: JSBI - public readonly PRECISION_MUL: JSBI[] - public readonly N_COINS: number - public readonly FEE_INDEX: number - public readonly DECIMALS: JSBI[] - public readonly POOL_PRECISION_DECIMALS = JSBI.BigInt('18') - public readonly tokenPrecisionMultipliers: JSBI[] - public readonly MAX_LOOP_LIMIT = 256 - public readonly A_PRECISION = JSBI.BigInt('100') - - public lpTotalSupply: JSBI - public swapFee: JSBI - public currentWithdrawFee: JSBI - public balances: JSBI[] - public amp: JSBI - public D: JSBI | undefined - public xp: JSBI[] | undefined - public aPrecise: JSBI - - constructor({ - rates, - lendingPrecision, - precision, - feeDenominator, - precisionMul, - feeIndex, - decimals, - amp, - balances, - lpTotalSupply, - swapFee, - aPrecise, - }: StableSwapMathConstants & StableSwapVariable) { - this.RATES = rates - this.LENDING_PRECISION = lendingPrecision - this.PRECISION = precision - this.FEE_DENOMINATOR = feeDenominator - this.PRECISION_MUL = precisionMul - this.N_COINS = rates.length - this.FEE_INDEX = feeIndex - this.DECIMALS = decimals - const tokenPrecisionMultipliers = decimals.map((deci) => - JSBI.exponentiate(JSBI.BigInt('10'), JSBI.subtract(this.POOL_PRECISION_DECIMALS, deci)) - ) - - this.tokenPrecisionMultipliers = tokenPrecisionMultipliers - - this.currentWithdrawFee = ZERO - this.swapFee = ONE - this.amp = ONE - this.balances = Array(this.N_COINS).fill(ZERO) - this.lpTotalSupply = ONE - this.aPrecise = aPrecise - this.updateInfo(swapFee, amp, balances, lpTotalSupply) - } - - updateInfo(swapFee: JSBI, amp: JSBI, balances: JSBI[], lpTotalSupply: JSBI) { - this.swapFee = swapFee - this.amp = amp - this.balances = balances - this.lpTotalSupply = lpTotalSupply - } - - calc_xp_mem(balances: BigintIsh[]): JSBI[] { - const xp: JSBI[] = new Array(this.N_COINS) - for (let i = 0; i < this.N_COINS; i += 1) { - xp[i] = JSBI.multiply(JSBI.BigInt(balances[i].toString()), this.tokenPrecisionMultipliers[i]) - } - this.xp = xp - return xp - } - - calc_xp(): JSBI[] { - return this.calc_xp_mem(this.balances) - } - - calc_D_xp(xp: JSBI[], amp: JSBI): JSBI { - // const S = xp.reduce((accum, cur) => JSBI.add(accum, cur)) - const N_COINS = JSBI.BigInt(this.N_COINS) - let S = ZERO - for (let i = 0; i < this.N_COINS; i += 1) { - S = JSBI.add(S, xp[i]) - } - if (JSBI.equal(S, ZERO)) return ZERO - - let Dprev = ZERO - let D = S - const na = JSBI.multiply(amp, N_COINS) - - for (let i = 0; i < 255; i++) { - // const D_P = xp.reduce((accum, cur) => JSBI.divide(JSBI.multiply(accum, D), JSBI.multiply(cur, N_COINS)), D) - let dP = D - for (let j = 0; j < this.N_COINS; j += 1) { - dP = JSBI.divide(JSBI.multiply(dP, D), JSBI.multiply(xp[j], N_COINS)) - } - Dprev = D - // const left = JSBI.multiply(JSBI.add(JSBI.multiply(Ann, S), JSBI.multiply(D_P, N_COINS)), D) - const left = JSBI.multiply( - JSBI.add(JSBI.divide(JSBI.multiply(na, S), this.A_PRECISION), JSBI.multiply(dP, N_COINS)), - D - ) - - const right = JSBI.add( - JSBI.divide(JSBI.multiply(JSBI.subtract(na, this.A_PRECISION), D), this.A_PRECISION), - JSBI.multiply(JSBI.add(N_COINS, ONE), dP) - ) - - D = JSBI.divide(left, right) - - if (JSBI.greaterThan(D, Dprev)) { - if (JSBI.lessThanOrEqual(JSBI.subtract(D, Dprev), ONE)) { - break - } - } else { - if (JSBI.lessThanOrEqual(JSBI.subtract(Dprev, D), ONE)) { - break - } - } - } - this.D = D - return D - } - - calc_D(): JSBI { - return this.calc_D_xp(this.calc_xp_mem(this.balances), JSBI.multiply(this.amp, this.A_PRECISION)) - } - - getD(xp: JSBI[], amp: JSBI): JSBI { - const N_COINS = JSBI.BigInt(this.N_COINS) - let S = ZERO - for (let i = 0; i < this.N_COINS; i += 1) { - S = JSBI.add(S, xp[i]) - } - if (JSBI.equal(S, ZERO)) return ZERO - - let Dprev = ZERO - let D = S - const na = JSBI.multiply(amp, N_COINS) - - for (let i = 0; i < 255; i++) { - let dP = D - for (let j = 0; j < this.N_COINS; j += 1) { - dP = JSBI.divide(JSBI.multiply(dP, D), JSBI.multiply(xp[j], N_COINS)) - } - Dprev = D - const left = JSBI.multiply( - JSBI.add(JSBI.divide(JSBI.multiply(na, S), this.A_PRECISION), JSBI.multiply(dP, N_COINS)), - D - ) - const right = JSBI.add( - JSBI.divide(JSBI.multiply(JSBI.subtract(na, this.A_PRECISION), D), this.A_PRECISION), - JSBI.multiply(JSBI.add(N_COINS, ONE), dP) - ) - D = JSBI.divide(left, right) - - if (JSBI.greaterThan(D, Dprev)) { - if (JSBI.lessThanOrEqual(JSBI.subtract(D, Dprev), ONE)) { - break - } - } else { - if (JSBI.lessThanOrEqual(JSBI.subtract(Dprev, D), ONE)) { - break - } - } - } - this.D = D - return D - } - - getY(indexFrom: number, indexTo: number, x: JSBI, xp: JSBI[]): JSBI { - const N_COINS = JSBI.BigInt(this.N_COINS) - const a = JSBI.multiply(this.amp, this.A_PRECISION) - const d = this.getD(xp, a) - let c = d - let s = ZERO - const na = JSBI.multiply(a, N_COINS) - - let _x = ZERO - for (let i = 0; i < this.N_COINS; i += 1) { - if (i === indexFrom) { - _x = x - } else if (i !== indexTo) { - _x = xp[i] - } else { - continue - } - s = JSBI.add(s, _x) - c = JSBI.divide(JSBI.multiply(c, d), JSBI.multiply(_x, N_COINS)) - } - c = JSBI.divide(JSBI.multiply(this.A_PRECISION, JSBI.multiply(c, d)), JSBI.multiply(na, N_COINS)) - const b = JSBI.add(s, JSBI.divide(JSBI.multiply(d, this.A_PRECISION), na)) - let y_prev = ZERO - let y = d - - for (let _i = 0; _i < 255; _i += 1) { - y_prev = y - y = JSBI.divide(JSBI.add(JSBI.multiply(y, y), c), JSBI.subtract(JSBI.add(JSBI.multiply(TWO, y), b), d)) - - if (JSBI.greaterThan(y, y_prev)) { - if (JSBI.lessThanOrEqual(JSBI.subtract(y, y_prev), ONE)) { - return y - } - } else { - if (JSBI.lessThanOrEqual(JSBI.subtract(y_prev, y), ONE)) { - return y - } - } - } - return y - } - - calculateSwap(indexFrom: number, indexTo: number, dx: JSBI, xp: JSBI[]): [JSBI, JSBI] { - const x = JSBI.add(xp[indexFrom], JSBI.multiply(this.tokenPrecisionMultipliers[indexFrom], dx)) - const y = this.getY(indexFrom, indexTo, x, xp) - let dy = JSBI.subtract(JSBI.subtract(xp[indexTo], y), ONE) - const dyFee = JSBI.divide(JSBI.multiply(dy, this.swapFee), this.FEE_DENOMINATOR) - dy = JSBI.divide(JSBI.subtract(dy, dyFee), this.tokenPrecisionMultipliers[indexTo]) - return [dy, dyFee] - } - - calculateRemoveLiquidity(amount: JSBI, lpTotalSupply: JSBI) { - const feeAdjustedAmount = JSBI.divide( - JSBI.multiply(JSBI.subtract(this.FEE_DENOMINATOR, this.currentWithdrawFee), amount), - this.FEE_DENOMINATOR - ) - const amounts = this.balances.map((bal) => JSBI.divide(JSBI.multiply(bal, feeAdjustedAmount), lpTotalSupply)) - return amounts - } - - _feePerToken(swapFee: JSBI, numTokens: JSBI): JSBI { - return JSBI.divide( - JSBI.multiply(swapFee, numTokens), - JSBI.multiply(JSBI.subtract(numTokens, JSBI.BigInt(1)), JSBI.BigInt(4)) - ) - } - - calculateWithdrawOneTokenDY(index: number, amount: JSBI): [JSBI, JSBI, JSBI] { - const xp = this.calc_xp() - const preciseA = this.aPrecise //JSBI.multiply(this.amp, this.A_PRECISION) - const d0 = this.getD(xp, preciseA) - const d1 = JSBI.subtract(d0, JSBI.divide(JSBI.multiply(amount, d0), this.lpTotalSupply)) - - const newY = this.getYD(preciseA, index, xp, d1) - const xpReduced: JSBI[] = new Array(xp.length).fill(JSBI.BigInt('0')) - const feePerToken = this._feePerToken(this.swapFee, JSBI.BigInt(xp.length)) - for (let i = 0; i < xp.length; i++) { - const xpi = xp[i] - const toSubtract = - i === index - ? JSBI.subtract(JSBI.divide(JSBI.multiply(xpi, d1), d0), newY) - : JSBI.subtract(xpi, JSBI.divide(JSBI.multiply(xpi, d1), d0)) - xpReduced[i] = JSBI.subtract(xpi, JSBI.divide(JSBI.multiply(toSubtract, feePerToken), this.FEE_DENOMINATOR)) - } - const y = this.getYD(preciseA, index, xpReduced, d1) - let dy = JSBI.subtract(xpReduced[index], y) - dy = JSBI.divide(JSBI.subtract(dy, JSBI.BigInt(1)), this.tokenPrecisionMultipliers[index]) - return [dy, newY, xp[index]] - } - - getYD(a: JSBI, index: number, xp: JSBI[], d: JSBI): JSBI { - const numTokens = xp.length - let c: JSBI = d - let s: JSBI = JSBI.BigInt(0) - const nA: JSBI = JSBI.multiply(a, JSBI.BigInt(numTokens)) - for (let i = 0; i < numTokens; i += 1) { - if (i !== index) { - s = JSBI.add(s, xp[i]) - c = JSBI.divide(JSBI.multiply(c, d), JSBI.multiply(xp[i], JSBI.BigInt(numTokens))) - } - } - c = JSBI.divide(JSBI.multiply(JSBI.multiply(c, d), this.A_PRECISION), JSBI.multiply(nA, JSBI.BigInt(numTokens))) - - const b = JSBI.add(s, JSBI.divide(JSBI.multiply(d, this.A_PRECISION), nA)) - let yPrev: JSBI - let y = d - - for (let _i = 0; _i < 255; _i += 1) { - yPrev = y - y = JSBI.divide(JSBI.add(JSBI.multiply(y, y), c), JSBI.subtract(JSBI.add(JSBI.multiply(TWO, y), b), d)) - // console.log({ y: y.toString(), yPrev: yPrev.toString() }) - if (JSBI.greaterThan(y, yPrev)) { - if (JSBI.lessThanOrEqual(JSBI.subtract(y, yPrev), ONE)) { - return y - } - } else { - if (JSBI.lessThanOrEqual(JSBI.subtract(yPrev, y), ONE)) { - return y - } - } - } - console.error('Approximation did not converge') - return y - } - - calculateWithdrawOneToken(index: number, amount: JSBI): [JSBI, JSBI] { - const [dy, newY, currentY] = this.calculateWithdrawOneTokenDY(index, amount) - const swapFee = JSBI.subtract(JSBI.divide(JSBI.subtract(currentY, newY), this.tokenPrecisionMultipliers[index]), dy) - return [dy, swapFee] - } - - calculateTokenAmount(originalAmounts: JSBI[], deposit: boolean): JSBI { - const amounts = originalAmounts.map((a) => (JSBI.equal(a, ZERO) ? JSBI.BigInt('1') : a)) - const a = this.aPrecise - const d0 = this.getD(this.calc_xp(), a) - const balances1 = this.balances.map((bal, i) => - deposit ? JSBI.add(bal, amounts[i]) : JSBI.subtract(bal, amounts[i]) - ) - const d1 = this.getD(this.calc_xp_mem(balances1), a) - const totalSupply = this.lpTotalSupply - if (deposit) { - const expected = JSBI.divide(JSBI.multiply(JSBI.subtract(d1, d0), totalSupply), d0) - return expected - } else { - return JSBI.divide( - JSBI.multiply(JSBI.divide(JSBI.multiply(JSBI.subtract(d0, d1), totalSupply), d0), this.FEE_DENOMINATOR), - this.FEE_DENOMINATOR - ) - } - } - - get_dx(i: number, j: number, dy: JSBI, xp: JSBI[]): JSBI { - const y: JSBI = JSBI.subtract( - xp[j], - JSBI.divide( - JSBI.multiply( - JSBI.divide( - JSBI.multiply(dy, this.FEE_DENOMINATOR), - JSBI.subtract(this.FEE_DENOMINATOR, JSBI.BigInt(this.FEE_INDEX.toString())) - ), - this.RATES[j] - ), - this.PRECISION - ) - ) - const x: JSBI = this.getY(j, i, y, xp) - const dx: JSBI = JSBI.divide(JSBI.multiply(JSBI.subtract(x, xp[i]), this.PRECISION), this.RATES[i]) - return dx - } -} diff --git a/src/utils/stableSwaps.ts b/src/utils/stableSwaps.ts deleted file mode 100644 index dd504502242..00000000000 --- a/src/utils/stableSwaps.ts +++ /dev/null @@ -1,48 +0,0 @@ -import JSBI from 'jsbi' -import { Token, TokenAmount } from 'lib/token-utils' - -import { StablePoolInfo } from '../state/stablePools/hooks' - -const dummyToken = new Token(1, '0x8cD0E2F11ed2E896a8307280dEEEE15B27e46BbE', 18, 'MobLP', 'Mobius cBTC/wBTC LP') -const dummyAmount = new TokenAmount(dummyToken, '0') -const WEI_SCALE = JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) - -const scaleAmount = - (toScale: JSBI) => - (ta: TokenAmount | undefined, addition = JSBI.BigInt('0')) => - toScale && ta - ? new TokenAmount(ta.token, JSBI.divide(JSBI.multiply(JSBI.add(addition, ta.raw), toScale), WEI_SCALE)) - : new TokenAmount(dummyToken, '0') - -export const getDepositValues = ( - pool: StablePoolInfo | undefined, - workingSupply?: JSBI -): { - valueOfStaked: TokenAmount - valueOfDeposited: TokenAmount - totalValueDeposited: TokenAmount - totalValueStaked: TokenAmount -} => { - if (!pool) - return { - valueOfDeposited: dummyAmount, - valueOfStaked: dummyAmount, - totalValueDeposited: dummyAmount, - totalValueStaked: dummyAmount, - } - const { totalDeposited, amountDeposited, virtualPrice, stakedAmount, totalStakedAmount } = pool - const scale = scaleAmount(virtualPrice) - - const valueOfStaked = scale(stakedAmount) - const valueOfDeposited = scale(amountDeposited) //?.add(stakedAmount)) - const totalValueStaked = workingSupply - ? scale(totalStakedAmount?.add(new TokenAmount(totalStakedAmount.token, workingSupply))) - : scale(totalStakedAmount) - const totalValueDeposited = scale(totalDeposited) - return { - valueOfStaked, - valueOfDeposited, - totalValueDeposited, - totalValueStaked, - } -} From 6265d32fda6909a488c1e01a1355b5377b779baa Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Sun, 27 Feb 2022 23:51:00 -0500 Subject: [PATCH 42/72] more cleanup --- src/state/lists/hooks.ts | 22 ---------------------- src/state/stake/hooks.ts | 37 ------------------------------------- 2 files changed, 59 deletions(-) delete mode 100644 src/state/lists/hooks.ts delete mode 100644 src/state/stake/hooks.ts diff --git a/src/state/lists/hooks.ts b/src/state/lists/hooks.ts deleted file mode 100644 index b173b4f21b6..00000000000 --- a/src/state/lists/hooks.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Tags, TokenInfo } from '@uniswap/token-lists' -import { Token } from 'lib/token-utils' - -type TagDetails = Tags[keyof Tags] -export interface TagInfo extends TagDetails { - id: string -} -/** - * Token instances created from token info. - */ -export class WrappedTokenInfo extends Token { - public readonly tokenInfo: TokenInfo - public readonly tags: TagInfo[] - constructor(tokenInfo: TokenInfo, tags: TagInfo[]) { - super(tokenInfo.chainId, tokenInfo.address, tokenInfo.decimals, tokenInfo.symbol, tokenInfo.name) - this.tokenInfo = tokenInfo - this.tags = tags - } - public get logoURI(): string | undefined { - return this.tokenInfo.logoURI - } -} diff --git a/src/state/stake/hooks.ts b/src/state/stake/hooks.ts deleted file mode 100644 index 4f8c9d9884b..00000000000 --- a/src/state/stake/hooks.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { JSBI, Token, TokenAmount } from 'lib/token-utils' - -// Hooks -import { useWeb3Context } from '../../hooks' -import { tryParseAmount } from '../swap/hooks' - -// based on typed value -export function useDerivedStakeInfo( - typedValue: string, - stakingToken: Token, - userLiquidityUnstaked: TokenAmount | undefined -): { - parsedAmount?: TokenAmount - error?: string -} { - const { connected } = useWeb3Context() - - const parsedInput: TokenAmount | undefined = tryParseAmount(typedValue, stakingToken) - - const parsedAmount = - parsedInput && userLiquidityUnstaked && JSBI.lessThanOrEqual(parsedInput.raw, userLiquidityUnstaked.raw) - ? parsedInput - : undefined - - let error: string | undefined - if (!connected) { - error = 'Connect Wallet' - } - if (!parsedAmount) { - error = error ?? 'Enter an amount' - } - - return { - parsedAmount, - error, - } -} From 9d229e647043f01c1c7827e9139f3e198cacfb51 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 28 Feb 2022 00:05:38 -0500 Subject: [PATCH 43/72] more cleanups --- src/components/NavigationTabs/index.tsx | 1 + src/pages/App.tsx | 2 -- src/pages/Burn/index.tsx | 36 ++++++++++----------- src/pages/CreateProposal/index.tsx | 2 +- src/pages/Mento/index.tsx | 2 +- src/pages/Mento/redirects.tsx | 42 ------------------------- src/pages/OpenSum/index.tsx | 11 +++---- src/pages/Swap/redirects.tsx | 42 ------------------------- 8 files changed, 23 insertions(+), 115 deletions(-) delete mode 100644 src/pages/Mento/redirects.tsx delete mode 100644 src/pages/Swap/redirects.tsx diff --git a/src/components/NavigationTabs/index.tsx b/src/components/NavigationTabs/index.tsx index 108f965f269..fb73288f728 100644 --- a/src/components/NavigationTabs/index.tsx +++ b/src/components/NavigationTabs/index.tsx @@ -51,6 +51,7 @@ const StyledArrowLeft = styled(ArrowLeft)` color: ${({ theme }) => theme.text1}; ` +// TODO: does this do anything export function SwapPoolTabs({ active }: { active: 'swap' | 'mento' | 'pool' | 'send' }) { const { t } = useTranslation() return ( diff --git a/src/pages/App.tsx b/src/pages/App.tsx index 9a0a77079fe..26b5b83cd97 100644 --- a/src/pages/App.tsx +++ b/src/pages/App.tsx @@ -23,7 +23,6 @@ import Reset from './Reset' import RiskPage from './Risk' import Staking from './Staking' import Swap from './Swap' -import { RedirectToSwap } from './Swap/redirects' import Vote from './Vote' import VotePage from './Vote/VotePage' @@ -123,7 +122,6 @@ export default function App() { - {' '} diff --git a/src/pages/Burn/index.tsx b/src/pages/Burn/index.tsx index e69c2c68979..f7589c9a9fe 100644 --- a/src/pages/Burn/index.tsx +++ b/src/pages/Burn/index.tsx @@ -1,28 +1,29 @@ import { TransactionResponse } from '@ethersproject/providers' import { ButtonConfirmed } from 'components/Button' import { AutoColumn } from 'components/Column' -import { STATIC_POOL_INFO } from 'constants/StablePools' -import { useWeb3Context } from 'hooks' +import { StablePools } from 'constants/pools' +import { useSwappableTokens } from 'hooks/Tokens' import { useFeeDistributor, usePoolProxy } from 'hooks/useContract' import React, { useState } from 'react' import { isMobile } from 'react-device-detect' -import { useStablePoolInfo } from 'state/stablePools/hooks' import { useTransactionAdder } from 'state/transactions/hooks' import styled from 'styled-components' import { TYPE } from 'theme' +import { CHAIN } from '../../constants' + const PageWrapper = styled(AutoColumn)` max-width: 640px; width: 100%; ` const blackList: Set = new Set([ - '0xcC82628f6A8dEFA1e2B0aD7ed448bef3647F7941', - '0xBe50a3013A1c94768A1ABb78c3cB79AB28fc1aCE', - '0xE919F65739c26a42616b7b8eedC6b5524d1e3aC4', - '0xcFFfE0c89a779c09Df3DF5624f54cDf7EF5fDd5D', - '0x93DB49bE12B864019dA9Cb147ba75cDC0506190e', - '0xd7Bf6946b740930c60131044bD2F08787e1DdBd4', + '0xcC82628f6A8dEFA1e2B0aD7ed448bef3647F7941'.toLowerCase(), + '0xBe50a3013A1c94768A1ABb78c3cB79AB28fc1aCE'.toLowerCase(), + '0xE919F65739c26a42616b7b8eedC6b5524d1e3aC4'.toLowerCase(), + '0xcFFfE0c89a779c09Df3DF5624f54cDf7EF5fDd5D'.toLowerCase(), + '0x93DB49bE12B864019dA9Cb147ba75cDC0506190e'.toLowerCase(), + '0xd7Bf6946b740930c60131044bD2F08787e1DdBd4'.toLowerCase(), ]) export default function BurnPage() { @@ -30,20 +31,15 @@ export default function BurnPage() { const poolProxy = usePoolProxy() const feeDistributor = useFeeDistributor() const addTransaction = useTransactionAdder() - const { chainID } = useWeb3Context() - const tokenSeen: Set = new Set() - const tokens: string[] = STATIC_POOL_INFO[chainID ?? chainID.MAINNET] - .flatMap((el) => el.tokens.map((tok) => tok.address)) - .filter((el) => { - if (tokenSeen.has(el)) return false - tokenSeen.add(el) - return !blackList.has(el) - }) - const pools = useStablePoolInfo() + const tokens = useSwappableTokens(false) + .filter((el) => !blackList.has(el.address.toLowerCase())) + .map(({ address }) => address) + + const pools = StablePools[CHAIN] const initProcess = async () => { for (let i = 0; i < pools.length; i += 20) { - const addresses = pools.slice(i, Math.min(i + 20, pools.length)).map((p) => p.poolAddress) + const addresses = pools.slice(i, Math.min(i + 20, pools.length)).map((p) => p.pool.address) await poolProxy ?.withdraw_many(addresses, { gasLimit: 10000000 }) .then((response: TransactionResponse) => { diff --git a/src/pages/CreateProposal/index.tsx b/src/pages/CreateProposal/index.tsx index b85fe1f90ee..7688bb01bde 100644 --- a/src/pages/CreateProposal/index.tsx +++ b/src/pages/CreateProposal/index.tsx @@ -49,7 +49,7 @@ const CreateProposalButton = ({ const formattedProposalThreshold = proposalThreshold ? JSBI.divide( proposalThreshold.quotient, - JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(proposalThreshold.currency.decimals)) + JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(proposalThreshold.token.decimals)) ).toLocaleString() : undefined return ( diff --git a/src/pages/Mento/index.tsx b/src/pages/Mento/index.tsx index 0b5bd4f2bf1..f7ab1bf8847 100644 --- a/src/pages/Mento/index.tsx +++ b/src/pages/Mento/index.tsx @@ -138,7 +138,7 @@ export default function Mento() { ReactGA.event({ category: 'Swap', action: 'Swap', - label: [trade?.input?.currency?.symbol, trade?.output?.currency?.symbol].join('/'), + label: [trade?.input?.token?.symbol, trade?.output?.token?.symbol].join('/'), }) }) .catch((error) => { diff --git a/src/pages/Mento/redirects.tsx b/src/pages/Mento/redirects.tsx deleted file mode 100644 index 48680c38d42..00000000000 --- a/src/pages/Mento/redirects.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { useEffect } from 'react' -import { useDispatch } from 'react-redux' -import { Redirect, RouteComponentProps } from 'react-router-dom' - -import { AppDispatch } from '../../state' -import { ApplicationModal, setOpenModal } from '../../state/application/actions' - -// Redirects to swap but only replace the pathname -export function RedirectPathToSwapOnly({ location }: RouteComponentProps) { - return -} - -// Redirects from the /swap/:outputCurrency path to the /swap?outputCurrency=:outputCurrency format -export function RedirectToSwap(props: RouteComponentProps<{ outputCurrency: string }>) { - const { - location: { search }, - match: { - params: { outputCurrency }, - }, - } = props - - return ( - 1 - ? `${search}&outputCurrency=${outputCurrency}` - : `?outputCurrency=${outputCurrency}`, - }} - /> - ) -} - -export function OpenClaimAddressModalAndRedirectToSwap(props: RouteComponentProps) { - const dispatch = useDispatch() - useEffect(() => { - dispatch(setOpenModal(ApplicationModal.ADDRESS_CLAIM)) - }, [dispatch]) - return -} diff --git a/src/pages/OpenSum/index.tsx b/src/pages/OpenSum/index.tsx index d7b8555fa62..0e9740470cd 100644 --- a/src/pages/OpenSum/index.tsx +++ b/src/pages/OpenSum/index.tsx @@ -28,7 +28,6 @@ import { CHAIN } from '../../constants' import { useWeb3Context } from '../../hooks' import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback' import { MentoTrade } from '../../state/mento/hooks' -import { useIsDarkMode } from '../../state/user/hooks' import { TYPE } from '../../theme' import AppBody from '../AppBody' @@ -40,8 +39,6 @@ const VoteCard = styled(DataCard)` // #fbcc5c export default function OpenSum() { - const isDarkMode = useIsDarkMode() - const { address, connect, connected } = useWeb3Context() const theme = useContext(ThemeContext) @@ -111,7 +108,7 @@ export default function OpenSum() { ReactGA.event({ category: 'Swap', action: 'Swap', - label: [input?.currency?.symbol, output?.currency?.symbol].join('/'), + label: [input?.token?.symbol, output?.token?.symbol].join('/'), }) ReactGA.event({ @@ -136,8 +133,8 @@ export default function OpenSum() { inputValue, inputToken?.symbol, outputToken?.symbol, - input?.currency?.symbol, - output?.currency?.symbol, + input?.token?.symbol, + output?.token?.symbol, ]) // TODO: check for endless loop @@ -342,7 +339,7 @@ export default function OpenSum() { disabled={!isValid} error={!isValid} > - + {swapInputError ? swapInputError : `${actionLabel}`} diff --git a/src/pages/Swap/redirects.tsx b/src/pages/Swap/redirects.tsx deleted file mode 100644 index 48680c38d42..00000000000 --- a/src/pages/Swap/redirects.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { useEffect } from 'react' -import { useDispatch } from 'react-redux' -import { Redirect, RouteComponentProps } from 'react-router-dom' - -import { AppDispatch } from '../../state' -import { ApplicationModal, setOpenModal } from '../../state/application/actions' - -// Redirects to swap but only replace the pathname -export function RedirectPathToSwapOnly({ location }: RouteComponentProps) { - return -} - -// Redirects from the /swap/:outputCurrency path to the /swap?outputCurrency=:outputCurrency format -export function RedirectToSwap(props: RouteComponentProps<{ outputCurrency: string }>) { - const { - location: { search }, - match: { - params: { outputCurrency }, - }, - } = props - - return ( - 1 - ? `${search}&outputCurrency=${outputCurrency}` - : `?outputCurrency=${outputCurrency}`, - }} - /> - ) -} - -export function OpenClaimAddressModalAndRedirectToSwap(props: RouteComponentProps) { - const dispatch = useDispatch() - useEffect(() => { - dispatch(setOpenModal(ApplicationModal.ADDRESS_CLAIM)) - }, [dispatch]) - return -} From dea09c67f23d4bb8bfcf6808b06c5f1c20969e83 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 28 Feb 2022 00:23:47 -0500 Subject: [PATCH 44/72] remove files --- .envrc | 4 - Deploys.csv | 2 - SNX_Addresses.txt | 4 - TestPoolInfo.txt | 91 -------------- craco.config.js | 29 ----- flake.nix | 15 --- netlify.toml | 2 - package.json | 4 - shell.nix | 7 -- src/index.tsx | 20 --- src/pages/Claim/index.tsx | 5 +- src/pages/Pool/index.tsx | 13 +- yarn.lock | 251 +++++++++++++++++--------------------- 13 files changed, 113 insertions(+), 334 deletions(-) delete mode 100644 .envrc delete mode 100644 Deploys.csv delete mode 100644 SNX_Addresses.txt delete mode 100644 TestPoolInfo.txt delete mode 100644 flake.nix delete mode 100644 netlify.toml delete mode 100644 shell.nix diff --git a/.envrc b/.envrc deleted file mode 100644 index 6b7a7d5cc07..00000000000 --- a/.envrc +++ /dev/null @@ -1,4 +0,0 @@ -watch_file flake.nix -watch_file flake.lock -mkdir -p .direnv -eval "$(nix print-dev-env --profile "$(direnv_layout_dir)/flake-profile")" diff --git a/Deploys.csv b/Deploys.csv deleted file mode 100644 index 99efafd7469..00000000000 --- a/Deploys.csv +++ /dev/null @@ -1,2 +0,0 @@ -name,address -veMOBI SNX,0x0812f6de916667C5aa820E757704c4ac69159529 \ No newline at end of file diff --git a/SNX_Addresses.txt b/SNX_Addresses.txt deleted file mode 100644 index 3fae61d8819..00000000000 --- a/SNX_Addresses.txt +++ /dev/null @@ -1,4 +0,0 @@ -USDC Optics Pool - SNX: 0xC8B86C28A0026eA72b7624FA3C912ad77F1D5fe0 -Solana Allbridge - SNX: 0xedD2c93858507A64B29a4aF0591bd2c571851829 -USDC POS - SNX: 0x3804da7A53FD810CD7f5bfcD1166eA2E0E9e9aE0 -USDC Moss - SNX: 0xd4A3debc32bdFE07b92c7D67297deCD00FC4236b \ No newline at end of file diff --git a/TestPoolInfo.txt b/TestPoolInfo.txt deleted file mode 100644 index 1ebdaead76d..00000000000 --- a/TestPoolInfo.txt +++ /dev/null @@ -1,91 +0,0 @@ -Test Pool 1 - -Transaction sent: 0x61657b0b74d62d6293ea6b84217e7dd821e0d05ba1984d3ae52235f54ee05713 - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 41 - ERC20Mock.constructor confirmed Block: 7014288 Gas used: 500215 (6.25%) - ERC20Mock deployed at: 0x2AaF20d89277BF024F463749045964D7e7d3A774 - -Transaction sent: 0x6a12d33f99f2a00f4fe40160a0126d7557ff9217e344db3643cff725e5a3f870 - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 42 - ERC20Mock.constructor confirmed Block: 7014292 Gas used: 500215 (6.25%) - ERC20Mock deployed at: 0x3551d53C9CF91E222D9579A1Ac4B44117E8Ec609 - -Transaction sent: 0x296f67cc093db17349cfaa79f94c0a724424e97c0700ef259abc4727a848f7ac - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 43 - MathUtils.constructor confirmed Block: 7014293 Gas used: 114689 (1.43%) - MathUtils deployed at: 0xa986725a7f0c6c76BB36531A29748839819da100 - -Transaction sent: 0xc4c08290c02525ca7966ef3cd6fd3dbc6db8e451b8219e1ac7a390c9444b3620 - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 44 - SwapUtils.constructor confirmed Block: 7014296 Gas used: 4067058 (50.84%) - SwapUtils deployed at: 0xF9B55CA1F693EC1e19F2dacF204642C99278C2C4 - -Transaction sent: 0x6931fbaf53a1b665892451f6c20edeabb11bb6da9b70f78b9dbcaa570ffb01ca - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 45 - Swap.constructor confirmed Block: 7014300 Gas used: 3527763 (44.10%) - Swap deployed at: 0xaAB4a154EE836fcDaa706da7BE3Cd36d116dcF84 - -Deployed at: -Swap: 0xaAB4a154EE836fcDaa706da7BE3Cd36d116dcF84 -Transaction sent: 0x413d4665d737332730daf720f4153835be5e3f5ce8c61b75a9d626e8fdb63cf1 - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 46 - ERC20Mock.approve confirmed Block: 7014302 Gas used: 43814 (0.55%) - -Transaction sent: 0x4db57f22264f9574cae052954b7cf6f1a8602bf89a1650338b0063f6d5b27acb - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 47 - ERC20Mock.approve confirmed Block: 7014303 Gas used: 43814 (0.55%) - -Transaction sent: 0x6c8cfd2f965a7d71d13224d05b018dafc49ace9553f6b50916372a7f7aaa9dd5 - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 48 - Swap.addLiquidity confirmed Block: 7014305 Gas used: 231608 (2.90%) - - -Pool 2 (3 tokens) - -Transaction sent: 0x5fa816e777e4dab3630f9658d49071196b2244311dd3acb14e7b04c66da4292e - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 58 - ERC20Mock.constructor confirmed Block: 7014406 Gas used: 500215 (6.25%) - ERC20Mock deployed at: 0x7588110A070987ea0347Cf788226c28d1476d641 - -Transaction sent: 0x97e701e26a556d459bd88fe98964a4b407eabd16d204286e6c8d6533dcc565c4 - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 59 - ERC20Mock.constructor confirmed Block: 7014407 Gas used: 500215 (6.25%) - ERC20Mock deployed at: 0x17Ec8dab839a9880D656c3cEF40cf4038657d168 - -Transaction sent: 0x3c92ba6d8af3ffe1dc8323dee12bbc128327906795f03479084c8effeb88826e - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 60 - ERC20Mock.constructor confirmed Block: 7014410 Gas used: 500215 (6.25%) - ERC20Mock deployed at: 0xCC531BfBA46cA251D3D9f3aCc37ABD5DCF3ed0B3 - -Transaction sent: 0x7ad75c4cb7a2540bdc5186db45adefcda59e23b2c27bd037de735a984f5372d1 - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 61 - MathUtils.constructor confirmed Block: 7014412 Gas used: 114689 (1.43%) - MathUtils deployed at: 0xbEA8Cf786865D8d72068284e70d92d500D32F17E - -Transaction sent: 0x3bcf4fb5bcc179db270d5acf189ce95eedfa946f6f2e64d67c21b28e972aeb1a - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 62 - SwapUtils.constructor confirmed Block: 7014413 Gas used: 4067118 (50.84%) - SwapUtils deployed at: 0x523b7553421987D008Ef70aC56ecCD9883979FAC - -Transaction sent: 0xf711eda2de779c9a659a31570768f73fe23e0c752551f0b7bde3cefc1db78083 - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 63 - Swap.constructor confirmed Block: 7014414 Gas used: 3591225 (44.89%) - Swap deployed at: 0xFB80520416685420751B2CD8E2c305aCbd5F756E - -Deployed at: -Swap: 0xFB80520416685420751B2CD8E2c305aCbd5F756E -Transaction sent: 0xda36fab594b00fc66278282340490e67d84ac518793a1cdbda82be0c935bf7f8 - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 64 - ERC20Mock.approve confirmed Block: 7014415 Gas used: 43814 (0.55%) - -Transaction sent: 0x56ce17c1c6c5cdbdcd1af73b06d479165825ca29c3dd3c9d7dd48e619b273034 - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 65 - ERC20Mock.approve confirmed Block: 7014416 Gas used: 43814 (0.55%) - -Transaction sent: 0xfd8c22ce86a20356728545e34352f6d37321efd5141cc97307a3831d42069a8f - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 66 - ERC20Mock.approve confirmed Block: 7014419 Gas used: 43814 (0.55%) - -Transaction sent: 0xf8f9ae0ba9313193779d30a95c189f1848915794db557647b959b54487ce595b - Gas price: 0.5 gwei Gas limit: 8000000 Nonce: 67 - Swap.addLiquidity confirmed Block: 7014425 Gas used: 282252 (3.53%) \ No newline at end of file diff --git a/craco.config.js b/craco.config.js index 3196f8a7f05..8d6dbae6919 100644 --- a/craco.config.js +++ b/craco.config.js @@ -1,35 +1,6 @@ -const SentryWebpackPlugin = require('@sentry/webpack-plugin') - -const now = Math.floor(new Date().getTime() / 1000) - module.exports = { webpack: { plugins: { - // add: process.env.SENTRY_AUTH_TOKEN - // ? [ - // new SentryWebpackPlugin({ - // // sentry-cli configuration - // authToken: process.env.SENTRY_AUTH_TOKEN, - // org: process.env.SENTRY_ORG, - // project: process.env.SENTRY_PROJECT, - // release: `${process.env.VERCEL_GIT_COMMIT_REF?.replace(/\//g, '--') ?? 'unknown'}-${ - // process.env.VERCEL_GIT_COMMIT_SHA ?? 'unknown' - // }`, - // // webpack specific configuration - // include: './build/', - // ignore: ['node_modules'], - // setCommits: { - // repo: `${process.env.VERCEL_GIT_REPO_OWNER}/${process.env.VERCEL_GIT_REPO_SLUG}`, - // commit: process.env.VERCEL_GIT_COMMIT_SHA, - // }, - // deploy: { - // env: process.env.VERCEL_ENV, - // url: `https://${process.env.VERCEL_URL}`, - // started: now, - // }, - // }), - // ] - // : [], }, }, eslint: { diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 69827df7b49..00000000000 --- a/flake.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ - description = "Mobius frontend interface"; - - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - flake-utils.url = "github:numtide/flake-utils"; - }; - - outputs = { self, nixpkgs, flake-utils }: - let systems = [ "x86_64-darwin" "x86_64-linux" ]; - - in flake-utils.lib.eachSystem systems (system: - let pkgs = nixpkgs.legacyPackages.${system}; - in { devShell = import ./shell.nix { inherit pkgs; }; }); -} diff --git a/netlify.toml b/netlify.toml deleted file mode 100644 index a592cf9477d..00000000000 --- a/netlify.toml +++ /dev/null @@ -1,2 +0,0 @@ -[build.environment] - NODE_OPTIONS = "--max_old_space_size=4096" \ No newline at end of file diff --git a/package.json b/package.json index b5d5b13e140..218f9781f7b 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,10 @@ "@reach/dialog": "^0.15.0", "@reach/portal": "^0.15.0", "@reduxjs/toolkit": "^1.5.1", - "@sentry/webpack-plugin": "^1.16.0", "@typechain/ethers-v5": "^7.0.1", - "@types/jest": "^26.0.23", "@types/ledgerhq__hw-transport-webusb": "^4.70.1", "@types/lodash": "^4.14.170", "@types/lodash.flatmap": "^4.5.6", - "@types/luxon": "^2.0.7", "@types/multicodec": "^2.1.0", "@types/node": "^14.14.37", "@types/react": "^17.0.11", @@ -134,7 +131,6 @@ "@ethersproject/units": "^5.3.0", "@ledgerhq/hw-transport-webusb": "^6.24.1", "@sentry/react": "^6.9.0", - "@sentry/tracing": "^6.9.0", "@types/lodash.mapvalues": "^4.6.6", "@types/react-date-range": "^1.1.8", "@types/react-vis": "^1.11.7", diff --git a/shell.nix b/shell.nix deleted file mode 100644 index 8f522c691ab..00000000000 --- a/shell.nix +++ /dev/null @@ -1,7 +0,0 @@ -{ pkgs }: -pkgs.mkShell { - buildInputs = with pkgs; [ - nodejs-14_x - (yarn.override { nodejs = nodejs-14_x; }) - ]; -} diff --git a/src/index.tsx b/src/index.tsx index c453dda7980..880c9fb1df5 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,8 +1,6 @@ import './i18n' import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client' -import * as Sentry from '@sentry/react' -import { Integrations } from '@sentry/tracing' import React, { StrictMode } from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' @@ -27,24 +25,6 @@ if (window.celo) { window.celo.autoRefreshOnNetworkChange = false } -if (process.env.REACT_APP_SENTRY_DSN) { - const sentryCfg = { - environment: `${process.env.REACT_APP_VERCEL_ENV ?? 'unknown'}`, - release: `${process.env.REACT_APP_VERCEL_GIT_COMMIT_REF?.replace(/\//g, '--') ?? 'unknown'}-${ - process.env.REACT_APP_VERCEL_GIT_COMMIT_SHA ?? 'unknown' - }`, - } - Sentry.init({ - dsn: process.env.REACT_APP_SENTRY_DSN, - integrations: [new Integrations.BrowserTracing()], - tracesSampleRate: 0.2, - ...sentryCfg, - }) - console.log(`Initializing Sentry environment at release ${sentryCfg.release} in environment ${sentryCfg.environment}`) -} else { - console.warn(`REACT_APP_SENTRY_DSN not found. Sentry will not be loaded.`) -} - const client = new ApolloClient({ uri: 'https://api.thegraph.com/subgraphs/name/d-mooers/mobius', cache: new InMemoryCache(), diff --git a/src/pages/Claim/index.tsx b/src/pages/Claim/index.tsx index 41fc1b32b84..b763736bd8b 100644 --- a/src/pages/Claim/index.tsx +++ b/src/pages/Claim/index.tsx @@ -1,4 +1,3 @@ -import { ErrorBoundary } from '@sentry/react' import React from 'react' import { useLocation } from 'react-router' import { useClaimInfo } from 'state/claim/hooks' @@ -40,9 +39,7 @@ export default function Claim() { - - - + diff --git a/src/pages/Pool/index.tsx b/src/pages/Pool/index.tsx index 742ab8393c6..fb436611e24 100644 --- a/src/pages/Pool/index.tsx +++ b/src/pages/Pool/index.tsx @@ -1,4 +1,3 @@ -import { ErrorBoundary } from '@sentry/react' import QuestionHelper from 'components/QuestionHelper' import { RowFixed } from 'components/Row' import { Chain, Coins, PRICE } from 'constants/StablePools' @@ -152,11 +151,7 @@ export default function Pool() { ) : ( sortedFilterdPools .filter((pool) => !pool.isKilled && !pool.disabled) - .map((pool) => ( - - - - )) + .map((pool) => ) )} @@ -181,11 +176,7 @@ export default function Pool() { {showDeprecated && sortedFilterdPools .filter((pool) => pool.isKilled || pool.disabled) - .map((pool) => ( - - - - ))} + .map((pool) => )} diff --git a/yarn.lock b/yarn.lock index 654865634fe..30515918e94 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2534,9 +2534,9 @@ tslib "^2.3.0" "@reduxjs/toolkit@^1.5.1": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.7.2.tgz#b428aaef92582379464f9de698dbb71957eafb02" - integrity sha512-wwr3//Ar8ZhM9bS58O+HCIaMlR4Y6SNHfuszz9hKnQuFIKvwaL3Kmjo6fpDKUOjo4Lv54Yi299ed8rofCJ/Vjw== + version "1.8.0" + resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.8.0.tgz#8ae875e481ed97e4a691aafa034f876bfd0413c4" + integrity sha512-cdfHWfcvLyhBUDicoFwG1u32JqvwKDxLxDd7zSmSoFw/RhYLOygIRtmaMjPRUUHmVmmAGAvquLLsKKU/677kSQ== dependencies: immer "^9.0.7" redux "^4.1.2" @@ -2571,100 +2571,70 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@sentry/browser@6.17.9": - version "6.17.9" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.17.9.tgz#62eac0cc3c7c788df6b4677fe9882d3974d84027" - integrity sha512-RsC8GBZmZ3YfBTaIOJ06RlFp5zG7BkUoquNJmf4YhRUZeihT9osrn8qUYGFWSV/UduwKUIlSGJA/rATWWhwPRQ== +"@sentry/browser@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.18.0.tgz#72d3e885199e0b41272ef37162dbbfa828e9c469" + integrity sha512-fQZdFs0jnBijVmhDWNIsHD0rGsIXup/1UYgMZqdBYYSBBQ7Ffpw+6nX1/vyKsCpLdgYhbi88eK/XO+QHtUJE2w== dependencies: - "@sentry/core" "6.17.9" - "@sentry/types" "6.17.9" - "@sentry/utils" "6.17.9" + "@sentry/core" "6.18.0" + "@sentry/types" "6.18.0" + "@sentry/utils" "6.18.0" tslib "^1.9.3" -"@sentry/cli@^1.72.0": - version "1.73.0" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.73.0.tgz#0d0bce913e0060ae192741c6693c57e50078c886" - integrity sha512-n4YINqmoncGUkLEpd4WuW+oD+aoUyQPhRbSBSYkbCFxPPmopn1VExCB2Vvzwj7vjXYRRGkix6keBMS0LLs3A3Q== +"@sentry/core@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.18.0.tgz#9ebfff67265cbe1af29f1cce0f712d9bd36b331f" + integrity sha512-I3iQVfMWHXR/LtevJg83aD7UAiUBLz1xAW8y3gd5lJej96UNv/4TbCmKZumYnEJMXf8EcFlg8t48W0Bl1GxhEg== dependencies: - https-proxy-agent "^5.0.0" - mkdirp "^0.5.5" - node-fetch "^2.6.7" - npmlog "^4.1.2" - progress "^2.0.3" - proxy-from-env "^1.1.0" - -"@sentry/core@6.17.9": - version "6.17.9" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.17.9.tgz#1c09f1f101207952566349a1921d46db670c8f62" - integrity sha512-14KalmTholGUtgdh9TklO+jUpyQ/D3OGkhlH1rnGQGoJgFy2eYm+s+MnUEMxFdGIUCz5kOteuNqYZxaDmFagpQ== - dependencies: - "@sentry/hub" "6.17.9" - "@sentry/minimal" "6.17.9" - "@sentry/types" "6.17.9" - "@sentry/utils" "6.17.9" + "@sentry/hub" "6.18.0" + "@sentry/minimal" "6.18.0" + "@sentry/types" "6.18.0" + "@sentry/utils" "6.18.0" tslib "^1.9.3" -"@sentry/hub@6.17.9": - version "6.17.9" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.17.9.tgz#f2c355088a49045e49feafb5356ca5d6e1e31d3c" - integrity sha512-34EdrweWDbBV9EzEFIXcO+JeoyQmKzQVJxpTKZoJA6PUwf2NrndaUdjlkDEtBEzjuLUTxhLxtOzEsYs1O6RVcg== +"@sentry/hub@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.18.0.tgz#8c425bc340b2792c5ac9c6feed2f444d9b7f5bb7" + integrity sha512-E2GrrNcidyT67ONU3btHO5vyS1bPQNdWqC09sUc1F3q/nQyvc7L2W09TKY2veaMZQtC9EU760fTG1hMmgGwPmw== dependencies: - "@sentry/types" "6.17.9" - "@sentry/utils" "6.17.9" + "@sentry/types" "6.18.0" + "@sentry/utils" "6.18.0" tslib "^1.9.3" -"@sentry/minimal@6.17.9": - version "6.17.9" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.17.9.tgz#0edca978097b3f56463ede028395d40adbf2ae84" - integrity sha512-T3PMCHcKk6lkZq6zKgANrYJJxXBXKOe+ousV1Fas1rVBMv7dtKfsa4itqQHszcW9shusPDiaQKIJ4zRLE5LKmg== +"@sentry/minimal@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.18.0.tgz#03da29b45b62b3073fbd110e423608ada17ef52c" + integrity sha512-QkkWOhX3NMycUNLj96thMQ0BclmfxE2VdDf9ZqRkvdFzxI1FVY5NEArqD4wtlrCIoYN1ioAYrvdb48/BTuGung== dependencies: - "@sentry/hub" "6.17.9" - "@sentry/types" "6.17.9" + "@sentry/hub" "6.18.0" + "@sentry/types" "6.18.0" tslib "^1.9.3" "@sentry/react@^6.9.0": - version "6.17.9" - resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.17.9.tgz#2066e7badb48c8da6da5bd07a7746137feb74021" - integrity sha512-TYu9Yl+gsNHdt763Yh35rSHJenxXqHSfWA55bYHr8hXDWu0crI/3LDuZb1RONmCM712CaQA+M5tgApA8QbHS4Q== - dependencies: - "@sentry/browser" "6.17.9" - "@sentry/minimal" "6.17.9" - "@sentry/types" "6.17.9" - "@sentry/utils" "6.17.9" - hoist-non-react-statics "^3.3.2" - tslib "^1.9.3" - -"@sentry/tracing@^6.9.0": - version "6.17.9" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.17.9.tgz#d4a6d96d88f10c9cd496e5b32f44d6e67d4c5dc7" - integrity sha512-5Rb/OS4ryNJLvz2nv6wyjwhifjy6veqaF9ffLrwFYij/WDy7m62ASBblxgeiI3fbPLX0aBRFWIJAq1vko26+AQ== + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.18.0.tgz#df76dab64decd6789b0f9e3b3ae035c3aee85b9b" + integrity sha512-jJ3g41ucDyudT5Ye6ry3mGQaHkbp14yqjbgBWKhCljWwYie0rHLCfjZ6letz6K1ey2Asvl6MLH5eoNhGEV0idg== dependencies: - "@sentry/hub" "6.17.9" - "@sentry/minimal" "6.17.9" - "@sentry/types" "6.17.9" - "@sentry/utils" "6.17.9" + "@sentry/browser" "6.18.0" + "@sentry/minimal" "6.18.0" + "@sentry/types" "6.18.0" + "@sentry/utils" "6.18.0" + hoist-non-react-statics "^3.3.2" tslib "^1.9.3" -"@sentry/types@6.17.9": - version "6.17.9" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.17.9.tgz#d579c33cde0301adaf8ff4762479ad017bf0dffa" - integrity sha512-xuulX6qUCL14ayEOh/h6FUIvZtsi1Bx34dSOaWDrjXUOJHJAM7214uiqW1GZxPJ13YuaUIubjTSfDmSQ9CBzTw== +"@sentry/types@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.18.0.tgz#89cee850d16c88621459d9f2a7f6cff9e9d3fb5f" + integrity sha512-SypDwXL1URE/XLkP4Ve+pFs41e+2OUYZ0lCimNreQQv46//pFXxP3LwU9Tc0Az4ZfxXnGiwofvt73XyBq9VpRQ== -"@sentry/utils@6.17.9": - version "6.17.9" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.17.9.tgz#425fe9af4e2d6114c2e9aaede75ccb6ddf91fbda" - integrity sha512-4eo9Z3JlJCGlGrQRbtZWL+L9NnlUXgTbfK3Lk7oO8D1ev8R5b5+iE6tZHTvU5rQRcq6zu+POT+tK5u9oxc/rnQ== +"@sentry/utils@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.18.0.tgz#99ad577020a269e43629feb6305c121065c992d1" + integrity sha512-mKegOabkAjoUHfokjI5oi3CMez5GD3xXOrBFcLVc9GFDXCgNMdYnHyEn/mmy8PikFdGHxZ3oI/16ZGU22wi5aw== dependencies: - "@sentry/types" "6.17.9" + "@sentry/types" "6.18.0" tslib "^1.9.3" -"@sentry/webpack-plugin@^1.16.0": - version "1.18.7" - resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.18.7.tgz#f48dbebb4989f3a357280f2c92a8d4b5b963f6ec" - integrity sha512-pOJLzC2unQdtrQarcicZ3aPs6hnQUjMvVmRN7s+/m7PEITvvf24hgIPdbLnn6PVQARvFA8mbbst0+eHMi44veA== - dependencies: - "@sentry/cli" "^1.72.0" - "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -3174,14 +3144,6 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^26.0.23": - version "26.0.24" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.24.tgz#943d11976b16739185913a1936e0de0c4a7d595a" - integrity sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w== - dependencies: - jest-diff "^26.0.0" - pretty-format "^26.0.0" - "@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" @@ -3222,14 +3184,9 @@ "@types/lodash" "*" "@types/lodash@*", "@types/lodash@^4.14.170", "@types/lodash@^4.14.53": - version "4.14.178" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8" - integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw== - -"@types/luxon@^2.0.7": - version "2.0.9" - resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-2.0.9.tgz#782a0edfa6d699191292c13168bd496cd66b87c6" - integrity sha512-ZuzIc7aN+i2ZDMWIiSmMdubR9EMMSTdEzF6R+FckP4p6xdnOYKqknTo/k+xXQvciSXlNGIwA4OPU5X7JIFzYdA== + version "4.14.179" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.179.tgz#490ec3288088c91295780237d2497a3aa9dfb5c5" + integrity sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w== "@types/minimatch@*": version "3.0.5" @@ -4819,9 +4776,9 @@ babel-plugin-polyfill-regenerator@^0.3.0: "@babel/helper-define-polyfill-provider" "^0.3.1" "babel-plugin-styled-components@>= 1.12.0": - version "2.0.5" - resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.5.tgz#8c402e5868c2a419eefb5466fccf154af18c52d1" - integrity sha512-A7kfST5odbf8Ev42OQbj5teEiT8DskpRoQ/iPYePLLdcTCAsodpYKqtoy4SJthpsGzQKc2vvnrtlUgdmJq6WKQ== + version "2.0.6" + resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.6.tgz#6f76c7f7224b7af7edc24a4910351948c691fc90" + integrity sha512-Sk+7o/oa2HfHv3Eh8sxoz75/fFvEdHsXV4grdeHufX0nauCmymlnN0rGhIvfpMQSJMvGutJ85gvCGea4iqmDpg== dependencies: "@babel/helper-annotate-as-pure" "^7.16.0" "@babel/helper-module-imports" "^7.16.0" @@ -5050,8 +5007,18 @@ bip32@2.0.5: typeforce "^1.11.5" wif "^2.0.6" +"bip39@git+https://github.com/bitcoinjs/bip39.git#d8ea080a18b40f301d4e2219a2991cd2417e83c2": + version "3.0.3" + resolved "git+https://github.com/bitcoinjs/bip39.git#d8ea080a18b40f301d4e2219a2991cd2417e83c2" + dependencies: + "@types/node" "11.11.6" + create-hash "^1.1.0" + pbkdf2 "^3.0.9" + randombytes "^2.0.1" + "bip39@https://github.com/bitcoinjs/bip39#d8ea080a18b40f301d4e2219a2991cd2417e83c2": version "3.0.3" + uid d8ea080a18b40f301d4e2219a2991cd2417e83c2 resolved "https://github.com/bitcoinjs/bip39#d8ea080a18b40f301d4e2219a2991cd2417e83c2" dependencies: "@types/node" "11.11.6" @@ -5073,8 +5040,21 @@ blakejs@^1.1.0: resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== +"bls12377js@git+https://github.com/celo-org/bls12377js.git#cb38a4cfb643c778619d79b20ca3e5283a2122a6": + version "0.1.0" + resolved "git+https://github.com/celo-org/bls12377js.git#cb38a4cfb643c778619d79b20ca3e5283a2122a6" + dependencies: + "@stablelib/blake2xs" "0.10.4" + "@types/node" "^12.11.7" + big-integer "^1.6.44" + chai "^4.2.0" + mocha "^6.2.2" + ts-node "^8.4.1" + typescript "^3.6.4" + "bls12377js@https://github.com/celo-org/bls12377js#cb38a4cfb643c778619d79b20ca3e5283a2122a6": version "0.1.0" + uid cb38a4cfb643c778619d79b20ca3e5283a2122a6 resolved "https://github.com/celo-org/bls12377js#cb38a4cfb643c778619d79b20ca3e5283a2122a6" dependencies: "@stablelib/blake2xs" "0.10.4" @@ -6754,7 +6734,7 @@ debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3: dependencies: ms "2.1.2" -debug@^3.1.1, debug@^3.2.6, debug@^3.2.7: +debug@^3.1.1, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -7176,9 +7156,9 @@ ejs@^2.6.1: integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== electron-to-chromium@^1.3.564, electron-to-chromium@^1.4.71: - version "1.4.72" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.72.tgz#19b871f1da8be8199b2330d694fc84fcdb72ecd9" - integrity sha512-9LkRQwjW6/wnSfevR21a3k8sOJ+XWSH7kkzs9/EUenKmuDkndP3W9y1yCZpOxufwGbX3JV8glZZSDb4o95zwXQ== + version "1.4.73" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.73.tgz#422f6f514315bcace9615903e4a9b6b9fa283137" + integrity sha512-RlCffXkE/LliqfA5m29+dVDPB2r72y2D2egMMfIy3Le8ODrxjuZNVo4NIC2yPL01N4xb4nZQLwzi6Z5tGIGLnA== elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" @@ -7473,21 +7453,21 @@ eslint-plugin-react-hooks@^4.2.0: integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA== eslint-plugin-react@^7.21.5, eslint-plugin-react@^7.24.0: - version "7.28.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.28.0.tgz#8f3ff450677571a659ce76efc6d80b6a525adbdf" - integrity sha512-IOlFIRHzWfEQQKcAD4iyYDndHwTQiCMcJVJjxempf203jnNLUnW34AXLrV33+nEXoifJE2ZEGmcjKPL8957eSw== + version "7.29.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.2.tgz#2d4da69d30d0a736efd30890dc6826f3e91f3f7c" + integrity sha512-ypEBTKOy5liFQXZWMchJ3LN0JX1uPI6n7MN7OPHKacqXAxq5gYC30TdO7wqGYQyxD1OrzpobdHC3hDmlRWDg9w== dependencies: array-includes "^3.1.4" array.prototype.flatmap "^1.2.5" doctrine "^2.1.0" estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.0.4" + minimatch "^3.1.2" object.entries "^1.1.5" object.fromentries "^2.0.5" object.hasown "^1.1.0" object.values "^1.1.5" - prop-types "^15.7.2" + prop-types "^15.8.1" resolve "^2.0.0-next.3" semver "^6.3.0" string.prototype.matchall "^4.0.6" @@ -8010,7 +7990,7 @@ events@^3.0.0, events@^3.1.0, events@^3.3.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== -eventsource@^1.0.7: +eventsource@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.0.tgz#00e8ca7c92109e94b0ddf32dac677d841028cfaf" integrity sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg== @@ -8265,7 +8245,7 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -faye-websocket@^0.11.3: +faye-websocket@^0.11.3, faye-websocket@^0.11.4: version "0.11.4" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== @@ -10212,7 +10192,7 @@ jest-config@^26.6.3: micromatch "^4.0.2" pretty-format "^26.6.2" -jest-diff@^26.0.0, jest-diff@^26.6.2: +jest-diff@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== @@ -10749,11 +10729,6 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json3@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" - integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -11587,7 +11562,7 @@ minimatch@3.0.4: dependencies: brace-expansion "^1.1.7" -minimatch@^3.0.4: +minimatch@^3.0.4, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -11873,7 +11848,7 @@ nano-json-stream-parser@^0.1.2: resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= -nanoid@^3.2.0: +nanoid@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== @@ -11965,7 +11940,7 @@ node-fetch@2.6.1: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: +node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== @@ -12112,7 +12087,7 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npmlog@^4.0.1, npmlog@^4.1.2: +npmlog@^4.0.1: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -13538,11 +13513,11 @@ postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, po source-map "^0.6.1" postcss@^8.1.0: - version "8.4.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" - integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== + version "8.4.7" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.7.tgz#f99862069ec4541de386bf57f5660a6c7a0875a8" + integrity sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A== dependencies: - nanoid "^3.2.0" + nanoid "^3.3.1" picocolors "^1.0.0" source-map-js "^1.0.2" @@ -13620,7 +13595,7 @@ pretty-error@^2.1.1: lodash "^4.17.20" renderkid "^2.0.4" -pretty-format@^26.0.0, pretty-format@^26.6.0, pretty-format@^26.6.2: +pretty-format@^26.6.0, pretty-format@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== @@ -13650,7 +13625,7 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -progress@^2.0.0, progress@^2.0.3: +progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -13691,7 +13666,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@15, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@15, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -13708,11 +13683,6 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -15421,16 +15391,15 @@ snapdragon@^0.8.1: use "^3.1.0" sockjs-client@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.2.tgz#4bc48c2da9ce4769f19dc723396b50f5c12330a3" - integrity sha512-ZzRxPBISQE7RpzlH4tKJMQbHM9pabHluk0WBaxAQ+wm/UieeBVBou0p4wVnSQGN9QmpAZygQ0cDIypWuqOFmFQ== + version "1.6.0" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.6.0.tgz#e0277b8974558edcb557eafc7d3027ef6128d865" + integrity sha512-qVHJlyfdHFht3eBFZdKEXKTlb7I4IV41xnVNo8yUKA1UHcPJwgW2SvTq9LhnjjCywSkSK7c/e4nghU0GOoMCRQ== dependencies: - debug "^3.2.6" - eventsource "^1.0.7" - faye-websocket "^0.11.3" + debug "^3.2.7" + eventsource "^1.1.0" + faye-websocket "^0.11.4" inherits "^2.0.4" - json3 "^3.3.3" - url-parse "^1.5.3" + url-parse "^1.5.10" sockjs@^0.3.21: version "0.3.24" @@ -15754,9 +15723,9 @@ string-width@^3.0.0, string-width@^3.1.0: strip-ansi "^5.1.0" string-width@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.0.tgz#5ab00980cfb29f43e736b113a120a73a0fb569d3" - integrity sha512-7x54QnN21P+XL/v8SuNKvfgsUre6PXpN7mc77N3HlZv+f1SBRGmjxtOud2Z6FZ8DmdkD/IdjCaf9XXbnqmTZGQ== + version "5.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.1.tgz#8825ca5f6b8dd5566a674e4f85001475a4b9c46e" + integrity sha512-V4jFFhDoJzUOpG491nUrDginBuZi+wKtG+omlT5hgdBLYGPNNVT/o75JWwsSqClbrYMEV9Dvm3fXjZzxyOjk2w== dependencies: eastasianwidth "^0.2.0" emoji-regex "^9.2.2" @@ -16848,7 +16817,7 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" -url-parse@^1.4.3, url-parse@^1.5.3: +url-parse@^1.4.3, url-parse@^1.5.10: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== From 45e234c43b0dbab679301fd6f952d1a85be58e1e Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 28 Feb 2022 10:46:13 -0500 Subject: [PATCH 45/72] claim cleanup --- src/components/WalletModal/index.tsx | 1 - src/components/claim/ClaimCard.tsx | 11 +- src/components/swap/ConfirmSwapModal.tsx | 4 +- .../TradeDetails/MobiusTradeDetails.tsx | 6 +- src/constants/lists.ts | 18 --- src/hooks/useStablePools.ts | 45 +++++++- src/pages/Pool/Manage.tsx | 10 +- src/pages/Pool/index.tsx | 109 ++++++++++-------- src/pages/Staking/StatsHeader.tsx | 11 +- src/pages/Staking/index.tsx | 2 +- src/state/application/hooks.ts | 2 +- src/state/claim/hooks.ts | 24 ++-- src/state/mobiusPools/hooks.ts | 34 +++++- 13 files changed, 170 insertions(+), 107 deletions(-) delete mode 100644 src/constants/lists.ts diff --git a/src/components/WalletModal/index.tsx b/src/components/WalletModal/index.tsx index 81be5996dc8..c929bab6eeb 100644 --- a/src/components/WalletModal/index.tsx +++ b/src/components/WalletModal/index.tsx @@ -24,7 +24,6 @@ export default function WalletModal({ ENSName?: string }) { const { address } = useWeb3Context() - // TODO(igm): get the errors const walletModalOpen = useModalOpen(ApplicationModal.WALLET) const closeModals = useCloseModals() diff --git a/src/components/claim/ClaimCard.tsx b/src/components/claim/ClaimCard.tsx index 8b5f714a18c..c8b9472de0f 100644 --- a/src/components/claim/ClaimCard.tsx +++ b/src/components/claim/ClaimCard.tsx @@ -4,7 +4,6 @@ import { darken } from 'polished' import React from 'react' import { VestType } from 'state/claim/reducer' import styled from 'styled-components' -import { humanFriendlyWei } from 'utils/eth' import { CHAIN } from '../../constants' import { useVestingContract } from '../../hooks/useContract' @@ -109,11 +108,11 @@ export const ClaimCard: React.FC = ({ info, type }: Props) => { const addTransaction = useTransactionAdder() async function onClaim() { - if (claimContract && unclaimedAmount) { + if (claimContract) { await claimContract?.['claim()']() .then((response: TransactionResponse) => { addTransaction(response, { - summary: `Claim ${humanFriendlyWei(unclaimedAmount.toString())} MOBI`, + summary: `Claim ${unclaimedAmount.toSignificant(3)} MOBI`, }) // setHash(response.hash) }) @@ -165,21 +164,21 @@ export const ClaimCard: React.FC = ({ info, type }: Props) => { Total allocated amount - {allocatedAmount ? humanFriendlyWei(allocatedAmount.toString()) : '--'} + {allocatedAmount.toSignificant(3)}
Claimed amount - {claimedAmount ? humanFriendlyWei(claimedAmount.toString()) : '--'} + {claimedAmount.toSignificant(3)}
Unclaimed vested amount - {unclaimedAmount ? humanFriendlyWei(unclaimedAmount.toString()) : '--'} + {unclaimedAmount.toSignificant(3)}
diff --git a/src/components/swap/ConfirmSwapModal.tsx b/src/components/swap/ConfirmSwapModal.tsx index ccfdd2668ab..705838f2380 100644 --- a/src/components/swap/ConfirmSwapModal.tsx +++ b/src/components/swap/ConfirmSwapModal.tsx @@ -86,8 +86,8 @@ export default function ConfirmSwapModal({ // text to show while loading const pendingText = `Swapping ${trade?.input?.toSignificant(6)} ${ - trade?.input?.currency?.symbol - } for ${trade?.output?.toSignificant(6)} ${trade?.output?.currency?.symbol}` + trade?.input?.token?.symbol + } for ${trade?.output?.toSignificant(6)} ${trade?.output?.token?.symbol}` const confirmationContent = useCallback( () => diff --git a/src/components/swap/routing/TradeDetails/MobiusTradeDetails.tsx b/src/components/swap/routing/TradeDetails/MobiusTradeDetails.tsx index cebcc1977d9..cfed1e2a1c1 100644 --- a/src/components/swap/routing/TradeDetails/MobiusTradeDetails.tsx +++ b/src/components/swap/routing/TradeDetails/MobiusTradeDetails.tsx @@ -34,8 +34,8 @@ export const MobiusTradeDetails: React.FC = ({ trade, allowedSlippage }: {isExactIn - ? `${slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(4)} ${trade.output.currency.symbol}` ?? '-' - : `${slippageAdjustedAmounts[Field.INPUT]?.toSignificant(4)} ${trade.input.currency.symbol}` ?? '-'} + ? `${slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(4)} ${trade.output.token.symbol}` ?? '-' + : `${slippageAdjustedAmounts[Field.INPUT]?.toSignificant(4)} ${trade.input.token.symbol}` ?? '-'} @@ -57,7 +57,7 @@ export const MobiusTradeDetails: React.FC = ({ trade, allowedSlippage }: - {realizedLPFee ? `${realizedLPFee.toSignificant(4)} ${trade.input.currency.symbol}` : '-'} + {realizedLPFee ? `${realizedLPFee.toSignificant(4)} ${trade.input.token.symbol}` : '-'} diff --git a/src/constants/lists.ts b/src/constants/lists.ts deleted file mode 100644 index 87a4c7814f6..00000000000 --- a/src/constants/lists.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @TODO add list from blockchain association - */ -export const UNSUPPORTED_LIST_URLS: string[] = [] - -const UBESWAP_LIST = 'https://raw.githubusercontent.com/Ubeswap/default-token-list/master/ubeswap.token-list.json' -const UBESWAP_EXPERIMENTAL_LIST = - 'https://raw.githubusercontent.com/Ubeswap/default-token-list/master/ubeswap-experimental.token-list.json' - -// lower index == higher priority for token import -export const DEFAULT_LIST_OF_LISTS: string[] = [ - UBESWAP_LIST, - UBESWAP_EXPERIMENTAL_LIST, - ...UNSUPPORTED_LIST_URLS, // need to load unsupported tokens as well -] - -// default lists to be 'active' aka searched across -export const DEFAULT_ACTIVE_LIST_URLS: string[] = [UBESWAP_LIST] diff --git a/src/hooks/useStablePools.ts b/src/hooks/useStablePools.ts index e7645f36de4..264956d4984 100644 --- a/src/hooks/useStablePools.ts +++ b/src/hooks/useStablePools.ts @@ -1,7 +1,50 @@ -import { StablePools } from 'constants/pools' +import { invariant } from '@apollo/client/utilities/globals' +import { IExchangeInfo, StablePools } from 'constants/pools' +import JSBI from 'jsbi' +import { calculateVirtualPrice } from 'lib/calculator' +import { Fraction, TokenAmount } from 'lib/token-utils' +import { priceStringToFraction, useTokenPrice, useTokenPrices } from 'state/application/hooks' +import { poolInfoToDisplay, usePools } from 'state/mobiusPools/hooks' import { CHAIN } from '../constants' export const useStablePools = () => { return StablePools[CHAIN] } + +export function useValueOfLp(lpAmount: TokenAmount, exchange: IExchangeInfo): Fraction | undefined { + const display = poolInfoToDisplay(exchange) + const price = useTokenPrice(display.peg.priceQuery ?? undefined) + const virtualPrice = calculateVirtualPrice(exchange) + if (!price || !virtualPrice) return undefined + return lpAmount.multiply(price).multiply(virtualPrice) +} + +export function useValueOfPool(exchange: IExchangeInfo): Fraction | undefined { + return useValueOfLp(exchange.lpTotalSupply, exchange) +} + +export function useValueOfAllPools(): Fraction { + const prices = useTokenPrices() + const pools = usePools() + return StablePools[CHAIN].reduce((acc, cur, i) => { + const price = cur.peg.priceQuery ? priceStringToFraction(prices[cur.peg.priceQuery]) : new Fraction(1) + invariant(price, 'price') + const virtualPrice = calculateVirtualPrice(pools[i]) + + return virtualPrice ? acc.add(price.multiply(virtualPrice).multiply(pools[i].lpTotalSupply)) : acc + }, new Fraction(0)) +} + +export function useValueOfAllLP(amounts: JSBI[]): Fraction { + const prices = useTokenPrices() + const pools = usePools() + invariant(amounts.length === pools.length, 'invalid amounts entry') + return StablePools[CHAIN].reduce((acc, cur, i) => { + const price = cur.peg.priceQuery ? priceStringToFraction(prices[cur.peg.priceQuery]) : new Fraction(1) + invariant(price, 'price') + const virtualPrice = calculateVirtualPrice(pools[i]) + + return virtualPrice ? acc.add(price.multiply(virtualPrice).multiply(amounts[i])) : acc + }, new Fraction(0)) +} diff --git a/src/pages/Pool/Manage.tsx b/src/pages/Pool/Manage.tsx index 2584bfd227d..30e4e568291 100644 --- a/src/pages/Pool/Manage.tsx +++ b/src/pages/Pool/Manage.tsx @@ -4,7 +4,7 @@ import Loader from 'components/Loader' import QuestionHelper from 'components/QuestionHelper' import { useMobi } from 'hooks/Tokens' import JSBI from 'jsbi' -import { Fraction, JSBI, TokenAmount } from 'lib/token-utils' +import { Fraction, TokenAmount } from 'lib/token-utils' import React, { useCallback, useState } from 'react' import { Link, RouteComponentProps } from 'react-router-dom' import { useExternalRewards, useStablePoolInfoByName } from 'state/stablePools/hooks' @@ -24,7 +24,7 @@ import { useWeb3Context } from '../../hooks' import { useColor } from '../../hooks/useColor' import usePrevious from '../../hooks/usePrevious' import { useTokenBalance } from '../../state/wallet/hooks' -import { ExternalLinkIcon, TYPE } from '../../theme' +import { TYPE } from '../../theme' const PageWrapper = styled(AutoColumn)` margin-top: 3rem; @@ -476,9 +476,3 @@ export default function Manage({ ) } - -const PairLinkIcon = styled(ExternalLinkIcon)` - svg { - stroke: ${(props) => props.theme.primary1}; - } -` diff --git a/src/pages/Pool/index.tsx b/src/pages/Pool/index.tsx index fb436611e24..76d3abbac56 100644 --- a/src/pages/Pool/index.tsx +++ b/src/pages/Pool/index.tsx @@ -1,22 +1,23 @@ import QuestionHelper from 'components/QuestionHelper' import { RowFixed } from 'components/Row' -import { Chain, Coins, PRICE } from 'constants/StablePools' -import { CUSD } from 'constants/tokens' +import { Chain, DisplayPool, IExchangeInfo, StablePools } from 'constants/pools' +import { useValueOfAllPools } from 'hooks/useStablePools' import JSBI from 'jsbi' import { TokenAmount } from 'lib/token-utils' import React from 'react' import { isMobile } from 'react-device-detect' import { useMobiPrice } from 'state/application/hooks' +import { GaugeInfo, useAllGaugesInfo, useAllUserGaugesInfo, UserGaugeInfo } from 'state/gauges/hooks' +import { useAllLpBalances, usePools } from 'state/mobiusPools/hooks' +import { useStakingInfo, useUserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { AutoColumn } from '../../components/Column' import { StablePoolCard } from '../../components/earn/StablePoolCard' import { CardNoise, CardSection, DataCard } from '../../components/earn/styled' -import Loader from '../../components/Loader' import { Row, RowBetween } from '../../components/Row' import { InfoWrapper } from '../../components/swap/styleds' import { CHAIN } from '../../constants' -import { StablePoolInfo, useStablePoolInfo } from '../../state/stablePools/hooks' import { Sel, TYPE } from '../../theme' const PageWrapper = styled(AutoColumn)` @@ -58,58 +59,76 @@ const HeaderLinks = styled(Row)` align-items: center; ` +enum SpecialChain { + Other, + All, +} + +type SelectChain = SpecialChain | Chain + const OtherChains = new Set([Chain.Avax, Chain.Polygon, Chain.Celo]) export default function Pool() { - const stablePools = useStablePoolInfo() - const [selection, setSelection] = React.useState(Chain.All) + const userGauges = useAllUserGaugesInfo() + const gauges = useAllGaugesInfo() + const stakingInfo = useStakingInfo() + const userStakingInfo = useUserStakingInfo() + const exchanges = usePools() + const lpBalances = useAllLpBalances() + + type Meta = { + display: DisplayPool + userGauge: UserGaugeInfo | null + gauge: GaugeInfo | null + lpBalance: TokenAmount + exchangeInfo: IExchangeInfo + } + + const meta: Meta[] = StablePools[CHAIN].map((el, i) => { + return { + display: el, + userGauge: userGauges[i], + gauge: gauges[i], + lpBalance: lpBalances[i], + exchangeInfo: exchanges[i], + } + }) + + const [selection, setSelection] = React.useState(SpecialChain.All) const [showDeprecated, setShowDeprecated] = React.useState(false) - const tvl = stablePools - .filter((pool) => pool && pool.virtualPrice) - .reduce((accum, poolInfo) => { - const price = - poolInfo.coin === Coins.Bitcoin - ? JSBI.BigInt(PRICE[Coins.Bitcoin]) - : poolInfo.coin === Coins.Ether - ? JSBI.BigInt(PRICE[Coins.Ether]) - : JSBI.BigInt(PRICE[Coins.USD]) - const lpPrice = JSBI.divide( - JSBI.multiply(price, poolInfo.virtualPrice), - JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) - ) - const priceDeposited = JSBI.multiply(poolInfo?.totalDeposited?.raw ?? JSBI.BigInt('0'), lpPrice) - return JSBI.add(accum, priceDeposited) - }, JSBI.BigInt('0')) - const tvlAsTokenAmount = new TokenAmount(CUSD[CHAIN], tvl) + + const tvl = useValueOfAllPools() const mobiprice = useMobiPrice() - const sortCallback = (pool1: StablePoolInfo, pool2: StablePoolInfo) => { - if (!pool1 || !pool2) return true - const isStaking1 = pool1.amountDeposited?.greaterThan(JSBI.BigInt('0')) || pool1.stakedAmount?.greaterThan('0') - const isStaking2 = pool2.amountDeposited?.greaterThan(JSBI.BigInt('0')) || pool2.stakedAmount?.greaterThan('0') - if (isStaking1 && !isStaking2) return false - return true + + const sortCallback = (pool1: Meta, pool2: Meta) => { + const isStaking1 = + pool1.lpBalance.greaterThan(0) || (pool1.userGauge && JSBI.greaterThan(pool1.userGauge.balance, JSBI.BigInt(0))) + const isStaking2 = + pool2.lpBalance.greaterThan(0) || (pool2.userGauge && JSBI.greaterThan(pool2.userGauge?.balance, JSBI.BigInt(0))) + if (isStaking1 && !isStaking2) return 1 + return -1 } - const sortedFilterdPools = stablePools - ?.sort(sortCallback) + const sortedFilterdPools = meta + .sort(sortCallback) .filter( (pool) => - selection === Chain.All || - selection === pool.displayChain || - (selection === Chain.Other && OtherChains.has(pool.displayChain)) + selection === SpecialChain.All || + selection === pool.display.chain || + (selection === SpecialChain.Other && OtherChains.has(pool.display.chain)) ) return ( - TVL: ${tvlAsTokenAmount.toFixed(0, { groupSeparator: ',' })} + TVL: ${tvl.toFixed(0, { groupSeparator: ',' })} {mobiprice && Latest MOBI Price: ${mobiprice.toFixed(3)}} - setSelection(Chain.All)} selected={selection === Chain.All}> + setSelection(SpecialChain.All)} selected={selection === SpecialChain.All}> ALL setSelection(Chain.Ethereum)} selected={selection === Chain.Ethereum}> @@ -121,7 +140,7 @@ export default function Pool() { setSelection(Chain.Terra)} selected={selection === Chain.Terra}> TERRA - setSelection(Chain.Other)} selected={selection === Chain.Other}> + setSelection(SpecialChain.Other)} selected={selection === SpecialChain.Other}> OTHER @@ -146,13 +165,11 @@ export default function Pool() { - {stablePools && stablePools?.length === 0 ? ( - - ) : ( - sortedFilterdPools - .filter((pool) => !pool.isKilled && !pool.disabled) - .map((pool) => ) - )} + {sortedFilterdPools + .filter((pool) => !pool.gauge?.isKilled) + .map((pool) => ( + + ))} @@ -175,8 +192,8 @@ export default function Pool() { {showDeprecated && sortedFilterdPools - .filter((pool) => pool.isKilled || pool.disabled) - .map((pool) => )} + .filter((pool) => pool.gauge?.isKilled) + .map((pool) => )} diff --git a/src/pages/Staking/StatsHeader.tsx b/src/pages/Staking/StatsHeader.tsx index 87fde025733..25878a1e7be 100644 --- a/src/pages/Staking/StatsHeader.tsx +++ b/src/pages/Staking/StatsHeader.tsx @@ -1,8 +1,11 @@ import Column from 'components/Column' import Loader from 'components/Loader' import { useExternalStakingRewards } from 'hooks/useExternalStakingRewards' +import { useValueOfAllLP } from 'hooks/useStablePools' +import JSBI from 'jsbi' import React from 'react' import { isMobile } from 'react-device-detect' +import { UserGaugeInfo } from 'state/gauges/hooks' import { StakingInfo, UserStakingInfo } from 'state/staking/hooks' import { useIsDarkMode } from 'state/user/hooks' import styled from 'styled-components' @@ -65,10 +68,11 @@ const StatSpan = styled.span` type PropType = { stakingInfo: StakingInfo userStakingInfo: UserStakingInfo + userGauges: (UserGaugeInfo | null)[] } -function StatsHeader({ stakingInfo, userStakingInfo }: PropType) { +function StatsHeader({ stakingInfo, userStakingInfo, userGauges }: PropType) { // TODO: fix price of deposits - // const priceOfDeposits = undefined + const priceOfDeposits = useValueOfAllLP(userGauges.map((el) => el?.balance ?? JSBI.BigInt(0))) const { avgApr } = useExternalStakingRewards() const isDarkMode = useIsDarkMode() @@ -80,8 +84,7 @@ function StatsHeader({ stakingInfo, userStakingInfo }: PropType) { }, { label: 'Your total deposits', - // value: priceOfDeposits ? '$' + priceOfDeposits?.toSignificant(4, { groupSeparator: ',' }) : undefined, - value: 'FIX', + value: '$' + priceOfDeposits?.toSignificant(4, { groupSeparator: ',' }), img: isDarkMode ? cashDark : cashLight, }, { diff --git a/src/pages/Staking/index.tsx b/src/pages/Staking/index.tsx index 12aaf7225aa..e1130095899 100644 --- a/src/pages/Staking/index.tsx +++ b/src/pages/Staking/index.tsx @@ -94,7 +94,7 @@ export default function Staking() { return ( - +
setView(View.Lock)} selected={view === View.Lock}> diff --git a/src/state/application/hooks.ts b/src/state/application/hooks.ts index aa0967ab91f..2ddc76fe703 100644 --- a/src/state/application/hooks.ts +++ b/src/state/application/hooks.ts @@ -110,7 +110,7 @@ export function useMobiPrice(): Fraction { return priceStringToFraction(prices[mobi.address.toLowerCase()]) ?? new Fraction('0') } -function priceStringToFraction(priceString: string | undefined): Fraction | undefined { +export function priceStringToFraction(priceString: string | undefined): Fraction | undefined { if (!priceString) return undefined const price = parseFloat(priceString) * 10 ** 4 const asFraction = new Fraction(price.toFixed(0), '10000') diff --git a/src/state/claim/hooks.ts b/src/state/claim/hooks.ts index 65d99369901..742a303de38 100644 --- a/src/state/claim/hooks.ts +++ b/src/state/claim/hooks.ts @@ -1,29 +1,23 @@ // To-Do: Implement Hooks to update Client-Side contract representation -import JSBI from 'jsbi' +import { useMobi } from 'hooks/Tokens' +import { TokenAmount } from 'lib/token-utils' import { useSelector } from 'react-redux' import { AppState } from '..' import { Claim, VestType } from './reducer' export interface ClaimInfo { - readonly allocatedAmount: JSBI - readonly claimedAmount: JSBI - readonly unclaimedAmount: JSBI + readonly allocatedAmount: TokenAmount + readonly claimedAmount: TokenAmount + readonly unclaimedAmount: TokenAmount } export function useClaimInfo(type = VestType.LP): ClaimInfo { const claim = useSelector((state) => state.claim[type]) - - if (claim == null) { - return { - allocatedAmount: JSBI.BigInt(0), - claimedAmount: JSBI.BigInt(0), - unclaimedAmount: JSBI.BigInt(0), - } - } + const mobi = useMobi() return { - allocatedAmount: claim.allocatedAmount, - claimedAmount: claim.claimedAmount, - unclaimedAmount: claim.unclaimedAmount, + allocatedAmount: new TokenAmount(mobi, claim.allocatedAmount), + claimedAmount: new TokenAmount(mobi, claim.claimedAmount), + unclaimedAmount: new TokenAmount(mobi, claim.unclaimedAmount), } } diff --git a/src/state/mobiusPools/hooks.ts b/src/state/mobiusPools/hooks.ts index b13403a51d7..654891b4102 100644 --- a/src/state/mobiusPools/hooks.ts +++ b/src/state/mobiusPools/hooks.ts @@ -1,5 +1,8 @@ -import { IExchange, IExchangeInfo, StablePools, Volume } from 'constants/pools' +import { DisplayPool, IExchange, IExchangeInfo, StablePools, Volume } from 'constants/pools' +import { useWeb3Context } from 'hooks' +import { TokenAmount } from 'lib/token-utils' import { useSelector } from 'react-redux' +import { useTokenBalance, useTokenBalances } from 'state/wallet/hooks' import invariant from 'tiny-invariant' import { CHAIN } from '../../constants' @@ -49,3 +52,32 @@ export function poolInfoToExchange(info: IExchangeInfo): IExchange { invariant(exchange.length === 1, 'cant find exchange') return exchange[0].pool } + +export function poolInfoToDisplay(info: IExchangeInfo): DisplayPool { + const exchange = StablePools[CHAIN].filter( + (e) => e.pool.lpToken.address.toLowerCase() === info.lpTotalSupply.token.address.toLowerCase() + ) + invariant(exchange.length === 1, 'cant find exchange') + return exchange[0] +} + +export function useLpBalance(exchange: IExchange): TokenAmount { + const { address, connected } = useWeb3Context() + const balance = useTokenBalance(address, exchange.lpToken) + return connected ? balance ?? new TokenAmount(exchange.lpToken, 0) : new TokenAmount(exchange.lpToken, 0) +} + +export function useAllLpBalances(): TokenAmount[] { + const { address, connected } = useWeb3Context() + + const balances = useTokenBalances( + address, + StablePools[CHAIN].map(({ pool }) => pool.lpToken) + ) + + return StablePools[CHAIN].map((el) => + connected + ? balances[el.pool.lpToken.address] ?? new TokenAmount(el.pool.lpToken, 0) + : new TokenAmount(el.pool.lpToken, 0) + ) +} From 2c97d7c283edd513a3da17b4cd7e374eef165a73 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 28 Feb 2022 11:36:48 -0500 Subject: [PATCH 46/72] will this ever build ' --- package.json | 2 + .../PoolSearchModal/CurrencyList.tsx | 58 - .../PoolSearchModal/CurrencySearch.tsx | 13 +- src/components/SearchModal/CurrencyList.tsx | 51 +- src/components/SearchModal/CurrencySearch.tsx | 3 +- src/components/Visx/GradientTextBox.tsx | 76 - src/components/Visx/PieChart.tsx | 210 -- src/components/VolumeChart/index.tsx | 20 +- src/components/claim/ClaimCard.tsx | 2 +- .../earn/ClaimExternalRewardsModal.tsx | 1 - src/components/earn/DepositModal.tsx | 1 - src/components/earn/StablePoolCard.tsx | 4 - src/components/earn/StakingModal.tsx | 4 +- src/components/earn/WithdrawLP.tsx | 1 - src/components/earn/WithdrawModal.tsx | 1 - src/components/earn/WithdrawTokens.tsx | 1 - src/components/swap/SwapModalHeader.tsx | 12 +- src/constants/ConstantSum.ts | 1 - src/constants/StablePools.ts | 2353 ++++++++--------- src/constants/index.ts | 2 +- src/constants/mento.ts | 6 +- src/constants/pools.ts | 27 +- src/constants/staking.ts | 24 +- src/constants/tokens.ts | 100 +- src/hooks/useColor.ts | 17 +- src/hooks/useContract.ts | 2 +- src/hooks/useExternalStakingRewards.ts | 1 - src/lib/token-utils/index.ts | 1 - src/lib/token-utils/splTokenRegistry.ts | 19 +- src/lib/token-utils/tokenAmount.ts | 12 +- src/pages/Charts/index.tsx | 6 - src/pages/CreateProposal/index.tsx | 2 +- src/pages/Pool/Manage.tsx | 2 - src/pages/Staking/Positions.tsx | 3 +- src/pages/Staking/Vote.tsx | 3 +- src/state/claim/updater.ts | 2 +- src/state/mento/reducer.test.ts | 37 - src/state/multicall/actions.test.ts | 57 - src/state/multicall/reducer.test.ts | 312 --- src/state/multicall/updater.test.ts | 168 -- src/state/swap/reducer.test.ts | 37 - src/state/transactions/updater.test.ts | 35 - src/state/user/reducer.test.ts | 34 - src/utils/chunkArray.test.ts | 32 - src/utils/parseENSAddress.test.ts | 19 - src/utils/retry.test.ts | 66 - src/utils/uriToHttp.test.ts | 28 - yarn.lock | 80 +- 48 files changed, 1351 insertions(+), 2597 deletions(-) delete mode 100644 src/components/Visx/GradientTextBox.tsx delete mode 100644 src/components/Visx/PieChart.tsx delete mode 100644 src/state/mento/reducer.test.ts delete mode 100644 src/state/multicall/actions.test.ts delete mode 100644 src/state/multicall/reducer.test.ts delete mode 100644 src/state/multicall/updater.test.ts delete mode 100644 src/state/swap/reducer.test.ts delete mode 100644 src/state/transactions/updater.test.ts delete mode 100644 src/state/user/reducer.test.ts delete mode 100644 src/utils/chunkArray.test.ts delete mode 100644 src/utils/parseENSAddress.test.ts delete mode 100644 src/utils/retry.test.ts delete mode 100644 src/utils/uriToHttp.test.ts diff --git a/package.json b/package.json index 218f9781f7b..935ba04fe20 100644 --- a/package.json +++ b/package.json @@ -131,7 +131,9 @@ "@ethersproject/units": "^5.3.0", "@ledgerhq/hw-transport-webusb": "^6.24.1", "@sentry/react": "^6.9.0", + "@types/jest": "^27.4.1", "@types/lodash.mapvalues": "^4.6.6", + "@types/luxon": "^2.0.9", "@types/react-date-range": "^1.1.8", "@types/react-vis": "^1.11.7", "@ubeswap/sdk": "^2.1.0", diff --git a/src/components/PoolSearchModal/CurrencyList.tsx b/src/components/PoolSearchModal/CurrencyList.tsx index 328f0559364..52881f1f264 100644 --- a/src/components/PoolSearchModal/CurrencyList.tsx +++ b/src/components/PoolSearchModal/CurrencyList.tsx @@ -2,66 +2,14 @@ import { Token } from 'lib/token-utils' import React, { CSSProperties, MutableRefObject, useCallback } from 'react' import { FixedSizeList } from 'react-window' import { Text } from 'rebass' -import styled from 'styled-components' -import checkedLogo from '../../assets/svg/mobius.svg' -import { WrappedTokenInfo } from '../../state/lists/hooks' import Column from '../Column' import { MenuItem } from '../SearchModal/styleds' -import { MouseoverTooltip } from '../Tooltip' function currencyKey(currency: Token): string { return currency instanceof Token ? currency.address : '' } -const Tag = styled.div` - background-color: ${({ theme }) => theme.bg3}; - color: ${({ theme }) => theme.text2}; - font-size: 14px; - border-radius: 4px; - padding: 0.25rem 0.3rem 0.25rem 0.3rem; - max-width: 6rem; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - justify-self: flex-end; - margin-right: 4px; -` - -const TagContainer = styled.div` - display: flex; - justify-content: flex-end; -` - -function TokenTags({ currency }: { currency: Token }) { - if (!(currency instanceof WrappedTokenInfo)) { - return - } - - const tags = currency.tags - if (!tags || tags.length === 0) return - - const tag = tags[0] - - return ( - - - {tag.name} - - {tags.length > 1 ? ( - `${name}: ${description}`) - .join('; \n')} - > - ... - - ) : null} - - ) -} - function CurrencyRow({ currency, onSelect, @@ -74,11 +22,6 @@ function CurrencyRow({ style: CSSProperties }) { const key = currencyKey(currency) - if (isSelected) - currency = { - ...currency, - logoURI: checkedLogo, - } as WrappedTokenInfo // only show add or remove buttons if not on selected list return ( @@ -93,7 +36,6 @@ function CurrencyRow({ {currency.symbol} - ) } diff --git a/src/components/PoolSearchModal/CurrencySearch.tsx b/src/components/PoolSearchModal/CurrencySearch.tsx index ac5a65aea31..914dbfe6d9e 100644 --- a/src/components/PoolSearchModal/CurrencySearch.tsx +++ b/src/components/PoolSearchModal/CurrencySearch.tsx @@ -7,7 +7,6 @@ import React, { useCallback, useRef } from 'react' import AutoSizer from 'react-virtualized-auto-sizer' import { FixedSizeList } from 'react-window' import { Text } from 'rebass' -import { WrappedTokenInfo } from 'state/lists/hooks' import styled from 'styled-components' import { CHAIN } from '../../constants' @@ -36,17 +35,7 @@ export function CurrencySearch({ selectedCurrency, onCurrencySelect, onDismiss } // refs for fixed size lists const fixedList = useRef() - const tokensToSelect = StablePools[CHAIN].map( - (s) => - new WrappedTokenInfo( - { - ...s.pool.lpToken, - symbol: s.name, - name: s.name, - }, - [] - ) - ) + const tokensToSelect = StablePools[CHAIN].map((s) => s.pool.lpToken) const handleCurrencySelect = useCallback( (currency: Token) => { diff --git a/src/components/SearchModal/CurrencyList.tsx b/src/components/SearchModal/CurrencyList.tsx index 4cfbfe947f6..9d1741ff775 100644 --- a/src/components/SearchModal/CurrencyList.tsx +++ b/src/components/SearchModal/CurrencyList.tsx @@ -6,14 +6,12 @@ import { Text } from 'rebass' import styled from 'styled-components' import { useWeb3Context } from '../../hooks' -import { WrappedTokenInfo } from '../../state/lists/hooks' import { useTokenBalance } from '../../state/wallet/hooks' import { TYPE } from '../../theme' import Column from '../Column' import CurrencyLogo from '../CurrencyLogo' import Loader from '../Loader' import { RowFixed } from '../Row' -import { MouseoverTooltip } from '../Tooltip' import { MenuItem } from './styleds' function currencyKey(currency: Token): string { @@ -59,33 +57,28 @@ const TagContainer = styled.div` justify-content: flex-end; ` +// TODO: Add this feature back in function TokenTags({ currency }: { currency: Token }) { - if (!(currency instanceof WrappedTokenInfo)) { - return - } - - const tags = currency.tags - if (!tags || tags.length === 0) return - - const tag = tags[0] - - return ( - - - {tag.name} - - {tags.length > 1 ? ( - `${name}: ${description}`) - .join('; \n')} - > - ... - - ) : null} - - ) + const tags = currency.info.extensions + if (!tags) return + + // return ( + // + // + // {tag.name} + // + // {tags.length > 1 ? ( + // `${name}: ${description}`) + // .join('; \n')} + // > + // ... + // + // ) : null} + // + // ) } function CurrencyRow({ @@ -123,7 +116,7 @@ function CurrencyRow({ {currency.name} - + {/* */} {balance ? : connected ? : null} diff --git a/src/components/SearchModal/CurrencySearch.tsx b/src/components/SearchModal/CurrencySearch.tsx index 515066d54a0..f4835e1622e 100644 --- a/src/components/SearchModal/CurrencySearch.tsx +++ b/src/components/SearchModal/CurrencySearch.tsx @@ -1,3 +1,4 @@ +import { CUSD } from 'constants/tokens' import { useOnClickOutside } from 'hooks/useOnClickOutside' import useTheme from 'hooks/useTheme' import useToggle from 'hooks/useToggle' @@ -148,7 +149,7 @@ export function CurrencySearch({ if (e.key === 'Enter') { const s = searchQuery.toLowerCase().trim() if (s === 'cusd') { - handleCurrencySelect(cUSD[CHAIN]) + handleCurrencySelect(CUSD[CHAIN]) } else if (filteredSortedTokens.length > 0) { if ( filteredSortedTokens[0].symbol?.toLowerCase() === searchQuery.trim().toLowerCase() || diff --git a/src/components/Visx/GradientTextBox.tsx b/src/components/Visx/GradientTextBox.tsx deleted file mode 100644 index 95a74130aa6..00000000000 --- a/src/components/Visx/GradientTextBox.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { CardNoise } from 'components/claim/styled' -import { darken } from 'polished' -import React from 'react' -// import { -// GradientDarkgreenGreen, -// GradientLightgreenGreen, -// GradientOrangeRed, -// GradientPinkBlue, -// GradientPinkRed, -// GradientPurpleOrange, -// GradientPurpleRed, -// GradientTealBlue, -// RadialGradient, -// LinearGradient, -// } from '@visx/gradient' -// import { Bar } from '@visx/shape' -import styled from 'styled-components' - -import { TYPE } from '../../theme' -import { RowBetween } from '../Row' - -const defaultMargin = { - top: 0, - left: 0, - right: 0, - bottom: 0, -} - -const colors = ['#2172e5', '#EC7391', '#BF4B96', '#00BEBF', '#6C4871', '#E2AD57'] - -const InfoBox = styled.div<{ bgEnd: string }>` - width: 25%; - height: 4rem; - display: flex; - flex-direction: row; - margin: 0.5rem; - padding: 1rem; - border-radius: 0.5rem; - overflow: hidden; - position: relative; - background: radial-gradient( - 174.47% 188.91% at 1.84% 0%, - ${({ theme }) => theme.primary1} 0%, - ${({ bgEnd }) => darken(0.3, bgEnd)} 100% - ), - #edeef2; - ${({ theme }) => theme.mediaWidth.upToMedium` - width: 45%; - `} - ${({ theme }) => theme.mediaWidth.upToSmall` - width: 95%; - `} -` - -export type GradientTextProps = { - id: string - label: string - value: string - i?: number - margin?: typeof defaultMargin -} - -export default function GradientTextBox({ label, value, id, i = 0 }: GradientTextProps) { - const bgEnd = colors[i % colors.length] - return ( - <> - - - - {label} - {value} - - - - ) -} diff --git a/src/components/Visx/PieChart.tsx b/src/components/Visx/PieChart.tsx deleted file mode 100644 index 205ca709e47..00000000000 --- a/src/components/Visx/PieChart.tsx +++ /dev/null @@ -1,210 +0,0 @@ -import { GradientDarkgreenGreen } from '@visx/gradient' -import { Group } from '@visx/group' -import { scaleOrdinal } from '@visx/scale' -import Pie, { PieArcDatum, ProvidedProps } from '@visx/shape/lib/shapes/Pie' -import React, { useState } from 'react' -import { animated, interpolate, useTransition } from 'react-spring' -import styled from 'styled-components' - -export interface PieSection { - label: string - value: number -} - -const SVG = styled.svg` - width: 100%; - height: 50rem; -` - -// color scales -const defaultMargin = { top: 20, right: 20, bottom: 20, left: 20 } - -export type PieProps = { - width: number - height: number - margin?: typeof defaultMargin - animate?: boolean - innerChartData: PieSection[] - outerChartData: PieSection[] -} - -export default function DoublePieChart({ - width, - height, - innerChartData, - outerChartData, - margin = defaultMargin, - animate = true, -}: PieProps) { - const outerLabels = outerChartData.map(({ label }) => label) - const innerLabels = innerChartData.map(({ label }) => label) - const getOuterColor = scaleOrdinal({ - domain: outerLabels, - range: [ - 'rgba(255,255,255,0.7)', - 'rgba(255,255,255,0.6)', - 'rgba(255,255,255,0.5)', - 'rgba(255,255,255,0.4)', - 'rgba(255,255,255,0.3)', - 'rgba(255,255,255,0.2)', - 'rgba(255,255,255,0.1)', - ], - }) - const getInnerColor = scaleOrdinal({ - domain: innerLabels, - range: [ - 'rgba(93,30,91,1)', - 'rgba(93,30,91,0.9)', - 'rgba(93,30,91,0.8)', - 'rgba(93,30,91,0.7)', - 'rgba(93,30,91,0.6)', - 'rgba(93,30,91,0.5)', - 'rgba(93,30,91,0.4)', - 'rgba(93,30,91,0.3)', - 'rgba(93,30,91,0.2)', - 'rgba(93,30,91,0.1)', - ], - }) - - const [selectedOuter, setSelectedOuter] = useState(null) - const [selectedInner, setSelectedInner] = useState(null) - - if (width < 10) return null - - const innerWidth = width - margin.left - margin.right - const innerHeight = height - margin.top - margin.bottom - const radius = Math.min(innerWidth, innerHeight) / 2 - const centerY = innerHeight / 2 - const centerX = innerWidth / 2 - const donutThickness = 50 - - return ( - - - - - label === selectedOuter) : outerChartData} - pieValue={(e: PieSection) => e.value} - outerRadius={radius} - innerRadius={radius - donutThickness} - cornerRadius={3} - padAngle={0.005} - > - {(pie) => ( - - {...pie} - animate={animate} - getKey={(arc) => arc.data.label} - onClickDatum={({ data: { label } }) => - animate && setSelectedOuter(selectedOuter && selectedOuter === label ? null : label) - } - getColor={(arc) => getOuterColor(arc.data.label)} - /> - )} - - label === selectedInner) : innerChartData} - pieValue={(e: PieSection) => e.value} - pieSortValues={() => -1} - outerRadius={radius - donutThickness * 1.3} - > - {(pie) => ( - - {...pie} - animate={animate} - getKey={({ data: { label } }) => label} - onClickDatum={({ data: { label } }) => - animate && setSelectedInner(selectedInner && selectedInner === label ? null : label) - } - getColor={({ data: { label } }) => getInnerColor(label)} - /> - )} - - - {animate && ( - - Click segments to update - - )} - - ) -} - -// react-spring transition definitions -type AnimatedStyles = { startAngle: number; endAngle: number; opacity: number } - -const fromLeaveTransition = ({ endAngle }: PieArcDatum) => ({ - // enter from 360° if end angle is > 180° - startAngle: endAngle > Math.PI ? 2 * Math.PI : 0, - endAngle: endAngle > Math.PI ? 2 * Math.PI : 0, - opacity: 0, -}) -const enterUpdateTransition = ({ startAngle, endAngle }: PieArcDatum) => ({ - startAngle, - endAngle, - opacity: 1, -}) - -type AnimatedPieProps = ProvidedProps & { - animate?: boolean - getKey: (d: PieArcDatum) => string - getColor: (d: PieArcDatum) => string - onClickDatum: (d: PieArcDatum) => void - delay?: number -} - -function AnimatedPie({ animate, arcs, path, getKey, getColor, onClickDatum }: AnimatedPieProps) { - const transitions = useTransition, AnimatedStyles>(arcs, { - from: animate ? fromLeaveTransition : enterUpdateTransition, - enter: enterUpdateTransition, - update: enterUpdateTransition, - leave: animate ? fromLeaveTransition : enterUpdateTransition, - keys: getKey, - }) - return transitions((props, arc, { key }) => { - const [centroidX, centroidY] = path.centroid(arc) - const hasSpaceForLabel = arc.endAngle - arc.startAngle >= 0.1 - - return ( - - - path({ - ...arc, - startAngle, - endAngle, - }) - )} - fill={getColor(arc)} - onClick={() => onClickDatum(arc)} - onTouchStart={() => onClickDatum(arc)} - /> - {hasSpaceForLabel && ( - - - {getKey(arc)} - - - )} - - ) - }) -} diff --git a/src/components/VolumeChart/index.tsx b/src/components/VolumeChart/index.tsx index 67e35b291cc..ba7e3c3fba1 100644 --- a/src/components/VolumeChart/index.tsx +++ b/src/components/VolumeChart/index.tsx @@ -14,7 +14,6 @@ import { XYPlot, YAxis, } from 'react-vis' -import { useIsDarkMode } from 'state/user/hooks' import styled from 'styled-components' import { TYPE } from 'theme' @@ -48,7 +47,6 @@ export default function VolumeChart({ data, labels, width, xLabelFormat }: Volum const [area, setArea] = useState() const [hovered, setHovered] = useState() const [hoverValue, setHoverValue] = useState() - const isDarkMode = useIsDarkMode() const theme = useTheme() return ( @@ -66,8 +64,8 @@ export default function VolumeChart({ data, labels, width, xLabelFormat }: Volum {s} ))} orientation="horizontal" - onItemMouseEnter={(item, index, event) => setHovered(index)} - onItemMouseLeave={(item, index, event) => setHovered(undefined)} + onItemMouseEnter={(_, index) => setHovered(index)} + onItemMouseLeave={() => setHovered(undefined)} /> setHoverValue({ ...point, label: labels[i] })} - // onValueMouseOut={() => setHoverValue(undefined)} + onNearestXY={(point) => setHoverValue({ ...point, label: labels[i] })} /> ))} setArea(newArea)} onDrag={(newArea) => { - newArea && + !!area && + !!newArea && + area.top && + area.bottom && + newArea.top && + newArea.bottom && + area.right && + area.left && + newArea.right && + newArea.left && setArea({ bottom: area.bottom + (newArea.top - newArea.bottom), left: area.left - (newArea.right - newArea.left), diff --git a/src/components/claim/ClaimCard.tsx b/src/components/claim/ClaimCard.tsx index c8b9472de0f..43f51351ef3 100644 --- a/src/components/claim/ClaimCard.tsx +++ b/src/components/claim/ClaimCard.tsx @@ -1,5 +1,5 @@ import { TransactionResponse } from '@ethersproject/providers' -import { VestingAddresses } from 'constants/StablePools' +import { VestingAddresses } from 'constants/tokens' import { darken } from 'polished' import React from 'react' import { VestType } from 'state/claim/reducer' diff --git a/src/components/earn/ClaimExternalRewardsModal.tsx b/src/components/earn/ClaimExternalRewardsModal.tsx index 949e945ef97..c2ca03835a5 100644 --- a/src/components/earn/ClaimExternalRewardsModal.tsx +++ b/src/components/earn/ClaimExternalRewardsModal.tsx @@ -3,7 +3,6 @@ import { useMobi } from 'hooks/Tokens' import { TokenAmount } from 'lib/token-utils' import React, { useEffect, useState } from 'react' import { useBlockNumber } from 'state/application/hooks' -import { StablePoolInfo, useExternalRewards } from 'state/stablePools/hooks' import styled from 'styled-components' import { useWeb3Context } from '../../hooks' diff --git a/src/components/earn/DepositModal.tsx b/src/components/earn/DepositModal.tsx index 11d04867b55..9ba88194c9e 100644 --- a/src/components/earn/DepositModal.tsx +++ b/src/components/earn/DepositModal.tsx @@ -11,7 +11,6 @@ import { useWeb3Context } from '../../hooks' import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback' import { useStableSwapContract } from '../../hooks/useContract' import useTransactionDeadline from '../../hooks/useTransactionDeadline' -import { StablePoolInfo, useExpectedLpTokens, useWarning } from '../../state/stablePools/hooks' import { useTransactionAdder } from '../../state/transactions/hooks' import { useTokenBalance } from '../../state/wallet/hooks' import { CloseIcon, ExternalLink, TYPE } from '../../theme' diff --git a/src/components/earn/StablePoolCard.tsx b/src/components/earn/StablePoolCard.tsx index 418693e3069..3362a810d9b 100644 --- a/src/components/earn/StablePoolCard.tsx +++ b/src/components/earn/StablePoolCard.tsx @@ -1,6 +1,5 @@ import Loader from 'components/Loader' import QuestionHelper from 'components/QuestionHelper' -import { ChainLogo, Coins } from 'constants/StablePools' import { useWeb3Context } from 'hooks' import { useMobi } from 'hooks/Tokens' import JSBI from 'jsbi' @@ -11,13 +10,10 @@ import { isMobile } from 'react-device-detect' import { useHistory } from 'react-router' import { NavLink } from 'react-router-dom' import styled from 'styled-components' -import { getDepositValues } from 'utils/stableSwaps' -import { getCUSDPrices, useCUSDPrice } from 'utils/useCUSDPrice' import { BIG_INT_SECONDS_IN_WEEK, BIG_INT_SECONDS_IN_YEAR, CHAIN } from '../../constants' import { useColor, usePoolColor } from '../../hooks/useColor' import { useTokenPrices } from '../../state/application/hooks' -import { StablePoolInfo } from '../../state/stablePools/hooks' import { theme, TYPE } from '../../theme' import { ButtonPrimary } from '../Button' import { AutoColumn } from '../Column' diff --git a/src/components/earn/StakingModal.tsx b/src/components/earn/StakingModal.tsx index c179bc21f76..58c361eeaa8 100644 --- a/src/components/earn/StakingModal.tsx +++ b/src/components/earn/StakingModal.tsx @@ -1,15 +1,13 @@ import { TransactionResponse } from '@ethersproject/providers' import Loader from 'components/Loader' import { useMobi } from 'hooks/Tokens' -import { JSBI, Token, TokenAmount } from 'lib/token-utils' +import { Token, TokenAmount } from 'lib/token-utils' import React, { useCallback, useState } from 'react' -import { StablePoolInfo } from 'state/stablePools/hooks' import styled from 'styled-components' import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback' import { useLiquidityGaugeContract } from '../../hooks/useContract' import useTransactionDeadline from '../../hooks/useTransactionDeadline' -import { useDerivedStakeInfo } from '../../state/stake/hooks' import { useTransactionAdder } from '../../state/transactions/hooks' import { CloseIcon, TYPE } from '../../theme' import { maxAmountSpend } from '../../utils/maxAmountSpend' diff --git a/src/components/earn/WithdrawLP.tsx b/src/components/earn/WithdrawLP.tsx index e581dcfe30f..6e81a3757b2 100644 --- a/src/components/earn/WithdrawLP.tsx +++ b/src/components/earn/WithdrawLP.tsx @@ -9,7 +9,6 @@ import { useWeb3Context } from '../../hooks' import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback' import { useStableSwapContract } from '../../hooks/useContract' import useTransactionDeadline from '../../hooks/useTransactionDeadline' -import { StablePoolInfo, useExpectedTokens } from '../../state/stablePools/hooks' import { tryParseAmount } from '../../state/swap/hooks' import { useTransactionAdder } from '../../state/transactions/hooks' import { TYPE } from '../../theme' diff --git a/src/components/earn/WithdrawModal.tsx b/src/components/earn/WithdrawModal.tsx index d9b06f74f2a..6a5fe7a1cd1 100644 --- a/src/components/earn/WithdrawModal.tsx +++ b/src/components/earn/WithdrawModal.tsx @@ -4,7 +4,6 @@ import React, { useState } from 'react' import styled from 'styled-components' import { useColor } from '../../hooks/useColor' -import { StablePoolInfo } from '../../state/stablePools/hooks' import { CloseIcon, StyledInternalLink, TYPE } from '../../theme' import { ButtonPrimary } from '../Button' import { AutoColumn } from '../Column' diff --git a/src/components/earn/WithdrawTokens.tsx b/src/components/earn/WithdrawTokens.tsx index a37c94cb228..11eab81ae8e 100644 --- a/src/components/earn/WithdrawTokens.tsx +++ b/src/components/earn/WithdrawTokens.tsx @@ -9,7 +9,6 @@ import { useWeb3Context } from '../../hooks' import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback' import { useStableSwapContract } from '../../hooks/useContract' import useTransactionDeadline from '../../hooks/useTransactionDeadline' -import { StablePoolInfo, useExpectedLpTokens } from '../../state/stablePools/hooks' import { tryParseAmount } from '../../state/swap/hooks' import { useTransactionAdder } from '../../state/transactions/hooks' import { useTokenBalance } from '../../state/wallet/hooks' diff --git a/src/components/swap/SwapModalHeader.tsx b/src/components/swap/SwapModalHeader.tsx index a08656ee0f2..0f066c22923 100644 --- a/src/components/swap/SwapModalHeader.tsx +++ b/src/components/swap/SwapModalHeader.tsx @@ -42,7 +42,7 @@ export default function SwapModalHeader({ - + - {trade.input.currency.symbol} + {trade.input.token.symbol} @@ -62,7 +62,7 @@ export default function SwapModalHeader({ - + - {trade.output.currency.symbol} + {trade.output.token.symbol} @@ -104,7 +104,7 @@ export default function SwapModalHeader({ {`Output is estimated. You will receive at least `} - {slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(6)} {trade.output.currency.symbol} + {slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(6)} {trade.output.token.symbol} {' or the transaction will revert.'} @@ -112,7 +112,7 @@ export default function SwapModalHeader({ {`Input is estimated. You will sell at most `} - {slippageAdjustedAmounts[Field.INPUT]?.toSignificant(6)} {trade.input.currency.symbol} + {slippageAdjustedAmounts[Field.INPUT]?.toSignificant(6)} {trade.input.token.symbol} {' or the transaction will revert.'} diff --git a/src/constants/ConstantSum.ts b/src/constants/ConstantSum.ts index 072451ebfdb..2acc7a3fd84 100644 --- a/src/constants/ConstantSum.ts +++ b/src/constants/ConstantSum.ts @@ -1,5 +1,4 @@ import { ChainId } from 'lib/token-utils' -import { WrappedTokenInfo } from 'state/lists/hooks' export type ConstantSumInfo = { address: string diff --git a/src/constants/StablePools.ts b/src/constants/StablePools.ts index 263f5da52bf..dbb6ac47ac7 100644 --- a/src/constants/StablePools.ts +++ b/src/constants/StablePools.ts @@ -1,1251 +1,1122 @@ import BigNumber from 'bignumber.js' -import JSBI from 'jsbi' -import { ChainId, Token } from 'lib/token-utils' -import { VestType } from 'state/claim/reducer' -import { WrappedTokenInfo } from 'state/lists/hooks' +import { ChainId } from 'lib/token-utils' -import celoLogo from '../assets/images/celo-chain-logo.png' -import ethLogo from '../assets/images/ethereum-chain-logo.png' -import polygonLogo from '../assets/images/polygon-chain-logo.png' -import terraLogo from '../assets/images/terra-logo.png' - -export enum Coins { - Bitcoin, - Ether, - USD, - Celo, - Eur, -} - -export enum Chain { - Celo, - Ethereum, - Polygon, - Solana, - Avax, - All, - Terra, - Other, -} - -enum WarningType { - POOF = 'poof', -} - -type StableSwapMathConstants = { - name: string - rates: JSBI[] - lendingPrecision: JSBI - precision: JSBI - feeDenominator: JSBI - precisionMul: JSBI[] - feeIndex: number - decimals: JSBI[] - swapFee: JSBI -} -type StableSwapConstants = StableSwapMathConstants & { - tokens: WrappedTokenInfo[] - tokenAddresses: string[] - address: string - gaugeAddress: string - lpToken: Token - peggedTo: string - pegComesAfter: boolean | undefined - displayDecimals: number - additionalRewards?: string[] - additionalRewardRate?: string[] - lastClaim?: Date - displayChain: Chain - coin: Coins - disabled?: boolean - metaPool?: string - isKilled?: boolean - warningType?: WarningType -} - -export const ChainLogo: { [c in Chain]: string } = { - [Chain.Celo]: celoLogo, - [Chain.Ethereum]: ethLogo, - [Chain.Polygon]: polygonLogo, - [Chain.Solana]: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_SOL.png', - [Chain.Avax]: 'https://s2.coinmarketcap.com/static/img/coins/64x64/5805.png', - [Chain.All]: '', - [Chain.Terra]: terraLogo, - [Chain.Other]: '', -} - -export const PRICE: { [c in Coins]: number } = { - [Coins.Bitcoin]: 38000, - [Coins.Ether]: 2700, - [Coins.USD]: 1, - [Coins.Celo]: 6, - [Coins.Eur]: 1.17, -} - -export const MOBIUS_MINTER_ADDRESS: { [K in ChainId]: string } = { - [ChainId.MAINNET]: '0x5F0200CA03196D5b817E2044a0Bb0D837e0A7823', - [ChainId.ALFAJORES]: '0x5c212FA1cf8b1143f2142C26161e65404034c01f', - [ChainId.BAKLAVA]: '', -} - -export const GAUGE_CONTROLLER: { [K in ChainId]: string } = { - [ChainId.MAINNET]: '0x7530E03056D3a8eD0323e61091ea2f17a1aC5C25', - [ChainId.ALFAJORES]: '0x00063Fbe0c90834EE90C6191d0D9F04eaB01A14f', - [ChainId.BAKLAVA]: '', -} - -export const GAUGE_PROXY: { [K in ChainId]: string } = { - [ChainId.MAINNET]: '0x0a3Ac12422C95F84b5bD18A6d9904d132a161C68', - [ChainId.ALFAJORES]: '', - [ChainId.BAKLAVA]: '', -} const weeklyEmissionToSeconds = (n: number) => { const yearlyEmission = new BigNumber(`${n}e+18`).dividedBy(7 * 24 * 60 * 60) return yearlyEmission.toFixed(0) } -export const STATIC_POOL_INFO: { [K in ChainId]: StableSwapConstants[] } = { - [ChainId.MAINNET]: [ - { - name: 'UST (Allbridge)', - tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - symbol: 'cUSD', - name: 'Celo Dollar', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', - decimals: 18, - symbol: 'UST', - name: 'Allbridge UST', - logoURI: 'https://raw.githubusercontent.com/kyscott18/default-token-list/master/assets/asset_UST.png', - }, - [] - ), - ], - address: '0x9F4AdBD0af281C69a582eB2E6fa2A594D4204CAe', - lpToken: new Token( - ChainId.MAINNET, - '0x9438e7281D7E3e99A9dD21e0EAd9c6a254e17ab2', - 18, - 'MobLP', - 'Mobius cUSD/aUST LP' - ), - swapFee: JSBI.multiply(JSBI.BigInt('2'), JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7'))), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: '$', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0x107F94409746E8c8E6eFF139A100D17D9ca7FdfE', - additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], - additionalRewardRate: [weeklyEmissionToSeconds(2268)], // ['14776041660000000'], //['18468900000000000'], // ['7302827380000000'] - displayChain: Chain.Terra, - coin: Coins.USD, - }, - { - name: 'USDC (Optics V2)', - tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xef4229c8c3250C675F21BCefa42f58EfbfF6002a'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - symbol: 'cUSD', - name: 'Celo Dollar', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xef4229c8c3250C675F21BCefa42f58EfbfF6002a', - decimals: 6, - symbol: 'cUSDC', - name: 'US Dollar Coin (Optics Bridge)', - logoURI: 'https://bit.ly/3CwGimW', - }, - [] - ), - ], - address: '0x9906589Ea8fd27504974b7e8201DF5bBdE986b03', - lpToken: new Token( - ChainId.MAINNET, - '0x39b6F09ef97dB406ab78D869471adb2384C494E3', - 18, - 'MobLP', - 'Mobius cUSD/cUSDC LP' - ), - swapFee: JSBI.multiply(JSBI.BigInt('2'), JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7'))), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('6')], - peggedTo: '$', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0xc96AeeaFF32129da934149F6134Aa7bf291a754E', - additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], - additionalRewardRate: [weeklyEmissionToSeconds(11088)], // ['29552083330000000'], // ['36940104160000000'], // ['7302827380000000'] - displayChain: Chain.Ethereum, - coin: Coins.USD, - }, - { - name: 'DAI (Optics V2)', - tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0x90Ca507a5D4458a4C6C6249d186b6dCb02a5BCCd'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - symbol: 'cUSD', - name: 'Celo Dollar', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x90Ca507a5D4458a4C6C6249d186b6dCb02a5BCCd', - decimals: 18, - symbol: 'DAI', - name: 'Optics DAI', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_DAI.png', - }, - [] - ), - ], - address: '0xF3f65dFe0c8c8f2986da0FEc159ABE6fd4E700B4', - lpToken: new Token( - ChainId.MAINNET, - '0x274DD2dF039f1f6131419C82173D97770e6af6B7', - 18, - 'MobLP', - 'Mobius cUSD/cDAI LP' - ), - swapFee: JSBI.multiply(JSBI.BigInt('2'), JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7'))), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: '$', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0xE1f9D952EecC07cfEFa69df9fBB0cEF260957119', - additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], - additionalRewardRate: [weeklyEmissionToSeconds(3780)], // ['14776041660000000'], //['18468900000000000'], // ['7302827380000000'] - displayChain: Chain.Ethereum, - coin: Coins.USD, - }, - { - name: 'WETH (Optics V2)', - tokenAddresses: ['0x2DEf4285787d58a2f811AF24755A8150622f4361', '0x122013fd7dF1C6F636a5bb8f03108E876548b455'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x2DEf4285787d58a2f811AF24755A8150622f4361', - decimals: 18, - symbol: 'cETH', - name: 'Wrapped Ethereum', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cETH.svg', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x122013fd7dF1C6F636a5bb8f03108E876548b455', - decimals: 18, - symbol: 'wETH', - name: 'Wrapped Ether (Optics Bridge)', - logoURI: 'https://etherscan.io/token/images/weth_28.png', - }, - [] - ), - ], - address: '0x74ef28D635c6C5800DD3Cd62d4c4f8752DaACB09', - lpToken: new Token( - ChainId.MAINNET, - '0x4fF08e2a4E7114af4B575AeF9250144f95790982', - 18, - 'MobLP', - 'Mobius cETH/wETH LP' - ), - swapFee: JSBI.multiply(JSBI.BigInt('2'), JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7'))), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: 'Ξ', - pegComesAfter: true, - displayDecimals: 2, - gaugeAddress: '0x487c30CB18AA9Ced435911E2B414e0e85D7E52bB', - displayChain: Chain.Ethereum, - coin: Coins.Ether, - additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], - additionalRewardRate: ['0'], // ['3694010416000000'], // ['7302827380000000'] - }, - { - name: 'wBTC (Optics V2)', - tokenAddresses: ['0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', '0xBAAB46E28388d2779e6E31Fd00cF0e5Ad95E327B'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', - decimals: 18, - symbol: 'cBTC', - name: 'Wrapped Bitcoin', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cBTC.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xBAAB46E28388d2779e6E31Fd00cF0e5Ad95E327B', - decimals: 8, - symbol: 'wBTC', - name: 'Wrapped Bitcoin (Optics Bridge)', - logoURI: 'https://etherscan.io/token/images/wbtc_28.png?v=1', - }, - [] - ), - ], - address: '0xaEFc4e8cF655a182E8346B24c8AbcE45616eE0d2', - lpToken: new Token( - ChainId.MAINNET, - '0x20d7274C5aF4f9DE6e8C93025e44aF3979d9Ab2b', - 18, - 'MobLP', - 'Mobius cBTC/wBTC LP' - ), - swapFee: JSBI.multiply(JSBI.BigInt('2'), JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7'))), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('8')], - peggedTo: '₿', - pegComesAfter: true, - displayDecimals: 2, - gaugeAddress: '0x127b524c74C2162Ee4BB2e42d8d2eB9050C0293E', - displayChain: Chain.Ethereum, - coin: Coins.Bitcoin, - additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], - additionalRewardRate: ['0'], // ['3694010416000000'], // ['7302827380000000'] - }, - { - name: 'pUSDC (Optics V2)', - tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0x1bfc26cE035c368503fAE319Cc2596716428ca44'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - symbol: 'cUSD', - name: 'Celo Dollar', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x1bfc26cE035c368503fAE319Cc2596716428ca44', - decimals: 6, - symbol: 'pUSDC', - name: 'USD Coin (PoS Optics)', - logoURI: 'https://bit.ly/3CwGimW', - }, - [] - ), - ], - address: '0xcCe0d62Ce14FB3e4363Eb92Db37Ff3630836c252', - lpToken: new Token( - ChainId.MAINNET, - '0x68b239b415970dD7a5234A9701cbB5BfaB544C7C', - 18, - 'MobLP', - 'Mobius cUSD/pUSDC LP' - ), - swapFee: JSBI.multiply(JSBI.BigInt('2'), JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7'))), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('6')], - peggedTo: '$', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0x0A125D473cd3b1968e728DDF7d424c928C09222A', - additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], - additionalRewardRate: [weeklyEmissionToSeconds(2520)], // ['7388020830000000'], //['11080000000000000'], // ['2190848200000000'], - displayChain: Chain.Polygon, - coin: Coins.USD, - }, - { - name: 'USDC (Optics V1)', - tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0x2A3684e9Dc20B857375EA04235F2F7edBe818FA7'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - symbol: 'cUSD', - name: 'Celo Dollar', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x2A3684e9Dc20B857375EA04235F2F7edBe818FA7', - decimals: 6, - symbol: 'cUSDCxV1', - name: 'US Dollar Coin (Optics Bridge)', - logoURI: 'https://bit.ly/3CwGimW', - }, - [] - ), - ], - address: '0xA5037661989789d0310aC2B796fa78F1B01F195D', - lpToken: new Token( - ChainId.MAINNET, - '0xd7Bf6946b740930c60131044bD2F08787e1DdBd4', - 18, - 'MobLP', - 'Mobius cUSD/cUSDC(O) LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('6')], - peggedTo: '$', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0xdAA2ab880b7f3D5697e6F85e63c28b9120AA9E07', - additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], - additionalRewardRate: ['0'], // ['7302827380000000'] - displayChain: Chain.Ethereum, - coin: Coins.USD, - isKilled: true, - }, - { - name: 'aaUSDC (Allbridge)', - tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xb70e0a782b058BFdb0d109a3599BEc1f19328E36'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - symbol: 'cUSD', - name: 'Celo Dollar', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xb70e0a782b058BFdb0d109a3599BEc1f19328E36', - decimals: 18, - symbol: 'aaUSDC', - name: 'US Dollar Coin (Avalanche Allbridge)', - logoURI: 'https://bit.ly/3CwGimW', - }, - [] - ), - ], - address: '0x0986B42F5f9C42FeEef66fC23eba9ea1164C916D', - lpToken: new Token( - ChainId.MAINNET, - '0x730e677f39C4Ca96012c394B9Da09A025E922F81', - 18, - 'MobLP', - 'Mobius cUSD/aaUSDC LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: '$', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0xF2ae5c2D2D2eD13dd324C0942163054fc4A3D4d9', - displayChain: Chain.Avax, - coin: Coins.USD, - }, - { - name: 'Poof cUSD V2', - warningType: WarningType.POOF, - tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xEadf4A7168A82D30Ba0619e64d5BCf5B30B45226'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - symbol: 'cUSD', - name: 'Celo Dollar', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xEadf4A7168A82D30Ba0619e64d5BCf5B30B45226', - decimals: 18, - symbol: 'pUSD', - name: 'Poof USD V2', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pUSD.png', - }, - [] - ), - ], - address: '0xa2F0E57d4cEAcF025E81C76f28b9Ad6E9Fbe8735', - lpToken: new Token( - ChainId.MAINNET, - '0x07e137E5605E15C93f22545868Fa70CECfCbbFFE', - 18, - 'MobLP', - 'Mobius pUSD V2 LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: '$', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0xE7195E651Cc47853f0054d85c8ADFc79D532929f', - additionalRewards: ['0x00400FcbF0816bebB94654259de7273f4A05c762'], - additionalRewardRate: ['6283068780000000'], - displayChain: Chain.Celo, - coin: Coins.USD, - }, - { - name: 'Poof CELO V2', - warningType: WarningType.POOF, - tokenAddresses: ['0x471EcE3750Da237f93B8E339c536989b8978a438', '0x301a61D01A63c8D670c2B8a43f37d12eF181F997'], - tokens: [ - new WrappedTokenInfo( - { - address: '0x471EcE3750Da237f93B8E339c536989b8978a438', - name: 'Celo', - symbol: 'CELO', - chainId: 42220, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_CELO.png', - }, - [] - ), - new WrappedTokenInfo( - { - address: '0x301a61D01A63c8D670c2B8a43f37d12eF181F997', - name: 'Poof Celo V2', - symbol: 'pCELO', - chainId: 42220, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pCELO.png', - }, - [] - ), - ], - address: '0xFc9e2C63370D8deb3521922a7B2b60f4Cff7e75a', - lpToken: new Token( - ChainId.MAINNET, - '0xAfFD8d6b5e5A0e25034DD3D075532F9CE01C305c', - 18, - 'MobLP', - 'Mobius pCelo V2 LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: 'Celo', - pegComesAfter: true, - displayDecimals: 0, - gaugeAddress: '0xD0d57a6689188F854F996BEAE0Cb1949FDB5FF86', - additionalRewards: ['0x00400FcbF0816bebB94654259de7273f4A05c762'], - additionalRewardRate: ['6283068780000000'], - displayChain: Chain.Celo, - coin: Coins.Celo, - }, - { - name: 'Poof cEUR V2', - warningType: WarningType.POOF, - tokenAddresses: ['0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73', '0xD8761DD6c7cB54febD33adD699F5E4440b62E01B'], - tokens: [ - new WrappedTokenInfo( - { - address: '0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73', - name: 'Celo Euro', - symbol: 'cEUR', - chainId: 42220, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cEUR.png', - }, - [] - ), - new WrappedTokenInfo( - { - address: '0xD8761DD6c7cB54febD33adD699F5E4440b62E01B', - name: 'Poof EUR', - symbol: 'pEUR', - chainId: 42220, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pEUR.png', - }, - [] - ), - ], - address: '0x23C95678862a229fAC088bd9705622d78130bC3e', - lpToken: new Token( - ChainId.MAINNET, - '0xec8e37876Fd9De919B58788B87A078e546149F87', - 18, - 'MobLP', - 'Mobius pEUR V2 LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: '€', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0xCAEd243de23264Bdd8297c6eECcF320846eee18A', - additionalRewards: ['0x00400FcbF0816bebB94654259de7273f4A05c762'], - additionalRewardRate: ['6283068780000000'], - // additionalRewards: [''], - // additionalRewardRate: ['730282730000000'], - displayChain: Chain.Celo, - coin: Coins.Eur, - }, - { - name: 'Poof cUSD V1', - warningType: WarningType.POOF, - tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xB4aa2986622249B1F45eb93F28Cfca2b2606d809'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - symbol: 'cUSD', - name: 'Celo Dollar', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xB4aa2986622249B1F45eb93F28Cfca2b2606d809', - decimals: 18, - symbol: 'pUSDxV1', - name: 'Poof USD V1', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pUSD.png', - }, - [] - ), - ], - address: '0x02Db089fb09Fda92e05e92aFcd41D9AAfE9C7C7C', - lpToken: new Token( - ChainId.MAINNET, - '0x18d71b8664E69D6Dd61C79247dBf12bFAaf66C10', - 18, - 'MobLP', - 'Mobius pUSD V1 LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: '$', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0x2459BDb59a3BF6Ab6C412Ac0b220e7CDA1D4ea26', - additionalRewards: ['0x00400FcbF0816bebB94654259de7273f4A05c762', '0x17700282592D6917F6A73D0bF8AcCf4D578c131e'], - additionalRewardRate: ['0', '0'], - displayChain: Chain.Celo, - coin: Coins.USD, - isKilled: true, - }, - { - name: 'asUSDC (AllBridge)', - tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xCD7D7Ff64746C1909E44Db8e95331F9316478817'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - symbol: 'cUSD', - name: 'Celo Dollar', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xCD7D7Ff64746C1909E44Db8e95331F9316478817', - decimals: 18, - symbol: 'asUSDC', - name: 'US Dollar Coin (Solana AllBridge)', - logoURI: 'https://bit.ly/3CwGimW', - }, - [] - ), - ], - address: '0x63C1914bf00A9b395A2bF89aaDa55A5615A3656e', - lpToken: new Token( - ChainId.MAINNET, - '0xAFEe90ab6A2D3B265262f94F6e437E7f6d94e26E', - 18, - 'MobLP', - 'Mobius cUSD/asUSDC LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: '$', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0x27D9Bfa5F864862BeDC23cFab7e00b6b94488CC6', - additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], - additionalRewardRate: [weeklyEmissionToSeconds(3780)], - displayChain: Chain.Solana, - coin: Coins.USD, - }, - { - name: 'pUSDC (Optics V1)', - tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xcC82628f6A8dEFA1e2B0aD7ed448bef3647F7941'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - symbol: 'cUSD', - name: 'Celo Dollar', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xcC82628f6A8dEFA1e2B0aD7ed448bef3647F7941', - decimals: 6, - symbol: 'pUSDCxV1', - name: 'USD Coin (PoS Optics)', - logoURI: 'https://bit.ly/3CwGimW', - }, - [] - ), - ], - address: '0x2080AAa167e2225e1FC9923250bA60E19a180Fb2', - lpToken: new Token( - ChainId.MAINNET, - '0xf5b454cF47Caca418D95930AA03975Ee4bf409bc', - 18, - 'MobLP', - 'Mobius cUSD/pUSDC LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('6')], - peggedTo: '$', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0x52517feb1Fc6141d5CF6718111C7Cc0FD764fA5d', - additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], - additionalRewardRate: ['0'], // ['2190848200000000'], - displayChain: Chain.Polygon, - coin: Coins.USD, - isKilled: true, - }, - { - name: 'wBTC (Optics V1)', - tokenAddresses: ['0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', '0xBe50a3013A1c94768A1ABb78c3cB79AB28fc1aCE'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', - decimals: 18, - symbol: 'cBTC', - name: 'Wrapped Bitcoin', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cBTC.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xBe50a3013A1c94768A1ABb78c3cB79AB28fc1aCE', - decimals: 8, - symbol: 'wBTCxV1', - name: 'Wrapped Bitcoin (Optics Bridge)', - logoURI: 'https://etherscan.io/token/images/wbtc_28.png?v=1', - }, - [] - ), - ], - address: '0x19260b9b573569dDB105780176547875fE9fedA3', - lpToken: new Token( - ChainId.MAINNET, - '0x8cD0E2F11ed2E896a8307280dEEEE15B27e46BbE', - 18, - 'MobLP', - 'Mobius cBTC/wBTC LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('8')], - peggedTo: '₿', - pegComesAfter: true, - displayDecimals: 2, - gaugeAddress: '0x1A8938a37093d34581B21bAd2AE7DC1c19150C05', - displayChain: Chain.Ethereum, - coin: Coins.Bitcoin, - isKilled: true, - }, - { - name: 'WETH (Optics V1)', - tokenAddresses: ['0x2DEf4285787d58a2f811AF24755A8150622f4361', '0xE919F65739c26a42616b7b8eedC6b5524d1e3aC4'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x2DEf4285787d58a2f811AF24755A8150622f4361', - decimals: 18, - symbol: 'cETH', - name: 'Wrapped Ethereum', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cETH.svg', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xE919F65739c26a42616b7b8eedC6b5524d1e3aC4', - decimals: 18, - symbol: 'wETHxV1', - name: 'Wrapped Ether (Optics Bridge)', - logoURI: 'https://etherscan.io/token/images/weth_28.png', - }, - [] - ), - ], - address: '0xE0F2cc70E52f05eDb383313393d88Df2937DA55a', - lpToken: new Token( - ChainId.MAINNET, - '0x846b784Ab5302155542c1B3952B54305F220fd84', - 18, - 'MobLP', - 'Mobius cETH/wETH LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: 'Ξ', - pegComesAfter: true, - displayDecimals: 2, - gaugeAddress: '0xD38e76E17E66b562B61c149Ca0EE53CEa1145733', - displayChain: Chain.Ethereum, - coin: Coins.Ether, - isKilled: true, - }, - { - name: 'USDT (Moss)', - tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xcFFfE0c89a779c09Df3DF5624f54cDf7EF5fDd5D'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - symbol: 'cUSD', - name: 'Celo Dollar', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xcFFfE0c89a779c09Df3DF5624f54cDf7EF5fDd5D', - decimals: 18, - symbol: 'cUSDTm', - name: 'Tether (Moss Bridge)', - logoURI: 'https://bit.ly/3AMrCyD', - }, - [] - ), - ], - address: '0xdBF27fD2a702Cc02ac7aCF0aea376db780D53247', - lpToken: new Token( - ChainId.MAINNET, - '0xC7a4c6EF4A16Dc24634Cc2A951bA5Fec4398f7e0', - 18, - 'MobLP', - 'Mobius cUSD/cUSDT LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: '$', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0xe2d6095685248F38Ae9fef1b360D772b78Ea19D1', - displayChain: Chain.Ethereum, - coin: Coins.USD, - }, - { - name: 'USDC (Moss)', - tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0x93DB49bE12B864019dA9Cb147ba75cDC0506190e'], - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - symbol: 'cUSD', - name: 'Celo Dollar', - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x93DB49bE12B864019dA9Cb147ba75cDC0506190e', - decimals: 18, - symbol: 'cUSDCm', - name: 'US Dollar Coin (Moss Bridge)', - logoURI: 'https://bit.ly/3CwGimW', - }, - [] - ), - ], - address: '0x0ff04189Ef135b6541E56f7C638489De92E9c778', - lpToken: new Token( - ChainId.MAINNET, - '0x635aec36c4b61bac5eB1C3EEe191147d006F8a21', - 18, - 'MobLP', - 'Mobius cUSD/cUSDC LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: '$', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0xd1B3C05FE24bda6F52e704daf1ACBa8c440d8573', - additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], - additionalRewardRate: ['0'], //['730282730000000'], - displayChain: Chain.Ethereum, - coin: Coins.USD, - }, - { - name: 'Poof CELO V1', - warningType: WarningType.POOF, - tokenAddresses: ['0x471EcE3750Da237f93B8E339c536989b8978a438', '0xE74AbF23E1Fdf7ACbec2F3a30a772eF77f1601E1'], - tokens: [ - new WrappedTokenInfo( - { - address: '0x471EcE3750Da237f93B8E339c536989b8978a438', - name: 'Celo', - symbol: 'CELO', - chainId: 42220, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_CELO.png', - }, - [] - ), - new WrappedTokenInfo( - { - address: '0xE74AbF23E1Fdf7ACbec2F3a30a772eF77f1601E1', - name: 'Poof Celo V1', - symbol: 'pCELOxV1', - chainId: 42220, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pCELO.png', - }, - [] - ), - ], - address: '0x413FfCc28e6cDDE7e93625Ef4742810fE9738578', - lpToken: new Token( - ChainId.MAINNET, - '0x4D6B17828d0173668e8Eb730106444556a98c0F9', - 18, - 'MobLP', - 'Mobius pCelo V1 LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: 'Celo', - pegComesAfter: true, - displayDecimals: 0, - gaugeAddress: '0x5489b2F0A1992b889F47601D71E068Fd15c63f26', - additionalRewards: ['0x00400FcbF0816bebB94654259de7273f4A05c762', '0x17700282592D6917F6A73D0bF8AcCf4D578c131e'], - additionalRewardRate: ['0', '0'], - // additionalRewards: [''], - // additionalRewardRate: ['730282730000000'], - displayChain: Chain.Celo, - coin: Coins.Celo, - isKilled: true, - }, - { - name: 'Poof cEUR V1', - warningType: WarningType.POOF, - tokenAddresses: ['0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73', '0x56072D4832642dB29225dA12d6Fd1290E4744682'], - tokens: [ - new WrappedTokenInfo( - { - address: '0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73', - name: 'Celo Euro', - symbol: 'cEUR', - chainId: 42220, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cEUR.png', - }, - [] - ), - new WrappedTokenInfo( - { - address: '0x56072D4832642dB29225dA12d6Fd1290E4744682', - name: 'Poof EUR V1', - symbol: 'pEURxV1', - chainId: 42220, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pEUR.png', - }, - [] - ), - ], - address: '0x382Ed834c6b7dBD10E4798B08889eaEd1455E820', - lpToken: new Token( - ChainId.MAINNET, - '0x2642Ab16Bfb7A8b36EE42c9CbA2289C4Ca9F33b9', - 18, - 'MobLP', - 'Mobius pEUR V1 LP' - ), - swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - lendingPrecision: JSBI.BigInt('1'), - precision: JSBI.BigInt('18'), - feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - feeIndex: 0, - decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - peggedTo: '€', - pegComesAfter: false, - displayDecimals: 0, - gaugeAddress: '0xCF34F4ec5DC9E09428A4f4a45475f6277694166c', - additionalRewards: ['0x00400FcbF0816bebB94654259de7273f4A05c762', '0x17700282592D6917F6A73D0bF8AcCf4D578c131e'], - additionalRewardRate: ['0', '0'], - // additionalRewards: [''], - // additionalRewardRate: ['730282730000000'], - displayChain: Chain.Celo, - coin: Coins.Eur, - isKilled: true, - }, - // { - // name: 'Poof cUSD V1 [DISABLED]', - // warningType: WarningType.POOF, - // tokenAddresses: ['0xB4aa2986622249B1F45eb93F28Cfca2b2606d809'], - // tokens: [ - // new WrappedTokenInfo( - // { - // chainId: ChainId.MAINNET, - // address: '0xB4aa2986622249B1F45eb93F28Cfca2b2606d809', - // decimals: 18, - // symbol: 'pUSDxV1', - // name: 'Poof USD V1', - // logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pUSD.png', - // }, - // [] - // ), - // new WrappedTokenInfo( - // { - // chainId: ChainId.MAINNET, - // address: '0xd7Bf6946b740930c60131044bD2F08787e1DdBd4', - // decimals: 18, - // symbol: 'Mob LP', - // name: 'Mobius USDC LP', - // logoURI: 'https://bit.ly/3CwGimW', - // }, - // [] - // ), - // ], - // address: '0x81B6a3d9f725AB5d706d9e552b128bC5bB0B58a1', - // lpToken: new Token( - // ChainId.MAINNET, - // '0x57f008172cF89b972db3db7dD032e66BE4AF1A8c', - // 18, - // 'MobLP', - // 'Mobius pUSD Meta LP' - // ), - // swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), - // rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], - // lendingPrecision: JSBI.BigInt('1'), - // precision: JSBI.BigInt('18'), - // feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), - // precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], - // feeIndex: 0, - // decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], - // peggedTo: '$', - // pegComesAfter: false, - // displayDecimals: 0, - // gaugeAddress: '0x1250D6dd3B51D20c14a8ECb10CC2dd713967767e', - // metaPool: 'USDC (Optics)', - // displayChain: Chain.Celo, - // coin: Coins.USD, - // disabled: true, - // isKilled: true, - // }, - ], - [ChainId.ALFAJORES]: [], - [ChainId.BAKLAVA]: [], -} +// export const STATIC_POOL_INFO: { [K in ChainId]: StableSwapConstants[] } = { +// [ChainId.MAINNET]: [ +// { +// name: 'UST (Allbridge)', +// tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', +// decimals: 18, +// symbol: 'cUSD', +// name: 'Celo Dollar', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', +// decimals: 18, +// symbol: 'UST', +// name: 'Allbridge UST', +// logoURI: 'https://raw.githubusercontent.com/kyscott18/default-token-list/master/assets/asset_UST.png', +// }, +// [] +// ), +// ], +// address: '0x9F4AdBD0af281C69a582eB2E6fa2A594D4204CAe', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x9438e7281D7E3e99A9dD21e0EAd9c6a254e17ab2', +// 18, +// 'MobLP', +// 'Mobius cUSD/aUST LP' +// ), +// swapFee: JSBI.multiply(JSBI.BigInt('2'), JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7'))), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: '$', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0x107F94409746E8c8E6eFF139A100D17D9ca7FdfE', +// additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], +// additionalRewardRate: [weeklyEmissionToSeconds(2268)], // ['14776041660000000'], //['18468900000000000'], // ['7302827380000000'] +// displayChain: Chain.Terra, +// coin: Coins.USD, +// }, +// { +// name: 'USDC (Optics V2)', +// tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xef4229c8c3250C675F21BCefa42f58EfbfF6002a'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', +// decimals: 18, +// symbol: 'cUSD', +// name: 'Celo Dollar', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xef4229c8c3250C675F21BCefa42f58EfbfF6002a', +// decimals: 6, +// symbol: 'cUSDC', +// name: 'US Dollar Coin (Optics Bridge)', +// logoURI: 'https://bit.ly/3CwGimW', +// }, +// [] +// ), +// ], +// address: '0x9906589Ea8fd27504974b7e8201DF5bBdE986b03', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x39b6F09ef97dB406ab78D869471adb2384C494E3', +// 18, +// 'MobLP', +// 'Mobius cUSD/cUSDC LP' +// ), +// swapFee: JSBI.multiply(JSBI.BigInt('2'), JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7'))), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('6')], +// peggedTo: '$', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0xc96AeeaFF32129da934149F6134Aa7bf291a754E', +// additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], +// additionalRewardRate: [weeklyEmissionToSeconds(11088)], // ['29552083330000000'], // ['36940104160000000'], // ['7302827380000000'] +// displayChain: Chain.Ethereum, +// coin: Coins.USD, +// }, +// { +// name: 'DAI (Optics V2)', +// tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0x90Ca507a5D4458a4C6C6249d186b6dCb02a5BCCd'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', +// decimals: 18, +// symbol: 'cUSD', +// name: 'Celo Dollar', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x90Ca507a5D4458a4C6C6249d186b6dCb02a5BCCd', +// decimals: 18, +// symbol: 'DAI', +// name: 'Optics DAI', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_DAI.png', +// }, +// [] +// ), +// ], +// address: '0xF3f65dFe0c8c8f2986da0FEc159ABE6fd4E700B4', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x274DD2dF039f1f6131419C82173D97770e6af6B7', +// 18, +// 'MobLP', +// 'Mobius cUSD/cDAI LP' +// ), +// swapFee: JSBI.multiply(JSBI.BigInt('2'), JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7'))), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: '$', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0xE1f9D952EecC07cfEFa69df9fBB0cEF260957119', +// additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], +// additionalRewardRate: [weeklyEmissionToSeconds(3780)], // ['14776041660000000'], //['18468900000000000'], // ['7302827380000000'] +// displayChain: Chain.Ethereum, +// coin: Coins.USD, +// }, +// { +// name: 'WETH (Optics V2)', +// tokenAddresses: ['0x2DEf4285787d58a2f811AF24755A8150622f4361', '0x122013fd7dF1C6F636a5bb8f03108E876548b455'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x2DEf4285787d58a2f811AF24755A8150622f4361', +// decimals: 18, +// symbol: 'cETH', +// name: 'Wrapped Ethereum', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cETH.svg', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x122013fd7dF1C6F636a5bb8f03108E876548b455', +// decimals: 18, +// symbol: 'wETH', +// name: 'Wrapped Ether (Optics Bridge)', +// logoURI: 'https://etherscan.io/token/images/weth_28.png', +// }, +// [] +// ), +// ], +// address: '0x74ef28D635c6C5800DD3Cd62d4c4f8752DaACB09', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x4fF08e2a4E7114af4B575AeF9250144f95790982', +// 18, +// 'MobLP', +// 'Mobius cETH/wETH LP' +// ), +// swapFee: JSBI.multiply(JSBI.BigInt('2'), JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7'))), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: 'Ξ', +// pegComesAfter: true, +// displayDecimals: 2, +// gaugeAddress: '0x487c30CB18AA9Ced435911E2B414e0e85D7E52bB', +// displayChain: Chain.Ethereum, +// coin: Coins.Ether, +// additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], +// additionalRewardRate: ['0'], // ['3694010416000000'], // ['7302827380000000'] +// }, +// { +// name: 'wBTC (Optics V2)', +// tokenAddresses: ['0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', '0xBAAB46E28388d2779e6E31Fd00cF0e5Ad95E327B'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', +// decimals: 18, +// symbol: 'cBTC', +// name: 'Wrapped Bitcoin', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cBTC.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xBAAB46E28388d2779e6E31Fd00cF0e5Ad95E327B', +// decimals: 8, +// symbol: 'wBTC', +// name: 'Wrapped Bitcoin (Optics Bridge)', +// logoURI: 'https://etherscan.io/token/images/wbtc_28.png?v=1', +// }, +// [] +// ), +// ], +// address: '0xaEFc4e8cF655a182E8346B24c8AbcE45616eE0d2', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x20d7274C5aF4f9DE6e8C93025e44aF3979d9Ab2b', +// 18, +// 'MobLP', +// 'Mobius cBTC/wBTC LP' +// ), +// swapFee: JSBI.multiply(JSBI.BigInt('2'), JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7'))), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('8')], +// peggedTo: '₿', +// pegComesAfter: true, +// displayDecimals: 2, +// gaugeAddress: '0x127b524c74C2162Ee4BB2e42d8d2eB9050C0293E', +// displayChain: Chain.Ethereum, +// coin: Coins.Bitcoin, +// additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], +// additionalRewardRate: ['0'], // ['3694010416000000'], // ['7302827380000000'] +// }, +// { +// name: 'pUSDC (Optics V2)', +// tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0x1bfc26cE035c368503fAE319Cc2596716428ca44'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', +// decimals: 18, +// symbol: 'cUSD', +// name: 'Celo Dollar', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x1bfc26cE035c368503fAE319Cc2596716428ca44', +// decimals: 6, +// symbol: 'pUSDC', +// name: 'USD Coin (PoS Optics)', +// logoURI: 'https://bit.ly/3CwGimW', +// }, +// [] +// ), +// ], +// address: '0xcCe0d62Ce14FB3e4363Eb92Db37Ff3630836c252', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x68b239b415970dD7a5234A9701cbB5BfaB544C7C', +// 18, +// 'MobLP', +// 'Mobius cUSD/pUSDC LP' +// ), +// swapFee: JSBI.multiply(JSBI.BigInt('2'), JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7'))), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('6')], +// peggedTo: '$', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0x0A125D473cd3b1968e728DDF7d424c928C09222A', +// additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], +// additionalRewardRate: [weeklyEmissionToSeconds(2520)], // ['7388020830000000'], //['11080000000000000'], // ['2190848200000000'], +// displayChain: Chain.Polygon, +// coin: Coins.USD, +// }, +// { +// name: 'USDC (Optics V1)', +// tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0x2A3684e9Dc20B857375EA04235F2F7edBe818FA7'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', +// decimals: 18, +// symbol: 'cUSD', +// name: 'Celo Dollar', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x2A3684e9Dc20B857375EA04235F2F7edBe818FA7', +// decimals: 6, +// symbol: 'cUSDCxV1', +// name: 'US Dollar Coin (Optics Bridge)', +// logoURI: 'https://bit.ly/3CwGimW', +// }, +// [] +// ), +// ], +// address: '0xA5037661989789d0310aC2B796fa78F1B01F195D', +// lpToken: new Token( +// ChainId.MAINNET, +// '0xd7Bf6946b740930c60131044bD2F08787e1DdBd4', +// 18, +// 'MobLP', +// 'Mobius cUSD/cUSDC(O) LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('6')], +// peggedTo: '$', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0xdAA2ab880b7f3D5697e6F85e63c28b9120AA9E07', +// additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], +// additionalRewardRate: ['0'], // ['7302827380000000'] +// displayChain: Chain.Ethereum, +// coin: Coins.USD, +// isKilled: true, +// }, +// { +// name: 'aaUSDC (Allbridge)', +// tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xb70e0a782b058BFdb0d109a3599BEc1f19328E36'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', +// decimals: 18, +// symbol: 'cUSD', +// name: 'Celo Dollar', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xb70e0a782b058BFdb0d109a3599BEc1f19328E36', +// decimals: 18, +// symbol: 'aaUSDC', +// name: 'US Dollar Coin (Avalanche Allbridge)', +// logoURI: 'https://bit.ly/3CwGimW', +// }, +// [] +// ), +// ], +// address: '0x0986B42F5f9C42FeEef66fC23eba9ea1164C916D', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x730e677f39C4Ca96012c394B9Da09A025E922F81', +// 18, +// 'MobLP', +// 'Mobius cUSD/aaUSDC LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: '$', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0xF2ae5c2D2D2eD13dd324C0942163054fc4A3D4d9', +// displayChain: Chain.Avax, +// coin: Coins.USD, +// }, +// { +// name: 'Poof cUSD V2', +// warningType: WarningType.POOF, +// tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xEadf4A7168A82D30Ba0619e64d5BCf5B30B45226'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', +// decimals: 18, +// symbol: 'cUSD', +// name: 'Celo Dollar', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xEadf4A7168A82D30Ba0619e64d5BCf5B30B45226', +// decimals: 18, +// symbol: 'pUSD', +// name: 'Poof USD V2', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pUSD.png', +// }, +// [] +// ), +// ], +// address: '0xa2F0E57d4cEAcF025E81C76f28b9Ad6E9Fbe8735', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x07e137E5605E15C93f22545868Fa70CECfCbbFFE', +// 18, +// 'MobLP', +// 'Mobius pUSD V2 LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: '$', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0xE7195E651Cc47853f0054d85c8ADFc79D532929f', +// additionalRewards: ['0x00400FcbF0816bebB94654259de7273f4A05c762'], +// additionalRewardRate: ['6283068780000000'], +// displayChain: Chain.Celo, +// coin: Coins.USD, +// }, +// { +// name: 'Poof CELO V2', +// warningType: WarningType.POOF, +// tokenAddresses: ['0x471EcE3750Da237f93B8E339c536989b8978a438', '0x301a61D01A63c8D670c2B8a43f37d12eF181F997'], +// tokens: [ +// new WrappedTokenInfo( +// { +// address: '0x471EcE3750Da237f93B8E339c536989b8978a438', +// name: 'Celo', +// symbol: 'CELO', +// chainId: 42220, +// decimals: 18, +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_CELO.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// address: '0x301a61D01A63c8D670c2B8a43f37d12eF181F997', +// name: 'Poof Celo V2', +// symbol: 'pCELO', +// chainId: 42220, +// decimals: 18, +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pCELO.png', +// }, +// [] +// ), +// ], +// address: '0xFc9e2C63370D8deb3521922a7B2b60f4Cff7e75a', +// lpToken: new Token( +// ChainId.MAINNET, +// '0xAfFD8d6b5e5A0e25034DD3D075532F9CE01C305c', +// 18, +// 'MobLP', +// 'Mobius pCelo V2 LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: 'Celo', +// pegComesAfter: true, +// displayDecimals: 0, +// gaugeAddress: '0xD0d57a6689188F854F996BEAE0Cb1949FDB5FF86', +// additionalRewards: ['0x00400FcbF0816bebB94654259de7273f4A05c762'], +// additionalRewardRate: ['6283068780000000'], +// displayChain: Chain.Celo, +// coin: Coins.Celo, +// }, +// { +// name: 'Poof cEUR V2', +// warningType: WarningType.POOF, +// tokenAddresses: ['0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73', '0xD8761DD6c7cB54febD33adD699F5E4440b62E01B'], +// tokens: [ +// new WrappedTokenInfo( +// { +// address: '0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73', +// name: 'Celo Euro', +// symbol: 'cEUR', +// chainId: 42220, +// decimals: 18, +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cEUR.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// address: '0xD8761DD6c7cB54febD33adD699F5E4440b62E01B', +// name: 'Poof EUR', +// symbol: 'pEUR', +// chainId: 42220, +// decimals: 18, +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pEUR.png', +// }, +// [] +// ), +// ], +// address: '0x23C95678862a229fAC088bd9705622d78130bC3e', +// lpToken: new Token( +// ChainId.MAINNET, +// '0xec8e37876Fd9De919B58788B87A078e546149F87', +// 18, +// 'MobLP', +// 'Mobius pEUR V2 LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: '€', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0xCAEd243de23264Bdd8297c6eECcF320846eee18A', +// additionalRewards: ['0x00400FcbF0816bebB94654259de7273f4A05c762'], +// additionalRewardRate: ['6283068780000000'], +// // additionalRewards: [''], +// // additionalRewardRate: ['730282730000000'], +// displayChain: Chain.Celo, +// coin: Coins.Eur, +// }, +// { +// name: 'Poof cUSD V1', +// warningType: WarningType.POOF, +// tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xB4aa2986622249B1F45eb93F28Cfca2b2606d809'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', +// decimals: 18, +// symbol: 'cUSD', +// name: 'Celo Dollar', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xB4aa2986622249B1F45eb93F28Cfca2b2606d809', +// decimals: 18, +// symbol: 'pUSDxV1', +// name: 'Poof USD V1', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pUSD.png', +// }, +// [] +// ), +// ], +// address: '0x02Db089fb09Fda92e05e92aFcd41D9AAfE9C7C7C', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x18d71b8664E69D6Dd61C79247dBf12bFAaf66C10', +// 18, +// 'MobLP', +// 'Mobius pUSD V1 LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: '$', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0x2459BDb59a3BF6Ab6C412Ac0b220e7CDA1D4ea26', +// additionalRewards: ['0x00400FcbF0816bebB94654259de7273f4A05c762', '0x17700282592D6917F6A73D0bF8AcCf4D578c131e'], +// additionalRewardRate: ['0', '0'], +// displayChain: Chain.Celo, +// coin: Coins.USD, +// isKilled: true, +// }, +// { +// name: 'asUSDC (AllBridge)', +// tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xCD7D7Ff64746C1909E44Db8e95331F9316478817'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', +// decimals: 18, +// symbol: 'cUSD', +// name: 'Celo Dollar', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xCD7D7Ff64746C1909E44Db8e95331F9316478817', +// decimals: 18, +// symbol: 'asUSDC', +// name: 'US Dollar Coin (Solana AllBridge)', +// logoURI: 'https://bit.ly/3CwGimW', +// }, +// [] +// ), +// ], +// address: '0x63C1914bf00A9b395A2bF89aaDa55A5615A3656e', +// lpToken: new Token( +// ChainId.MAINNET, +// '0xAFEe90ab6A2D3B265262f94F6e437E7f6d94e26E', +// 18, +// 'MobLP', +// 'Mobius cUSD/asUSDC LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: '$', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0x27D9Bfa5F864862BeDC23cFab7e00b6b94488CC6', +// additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], +// additionalRewardRate: [weeklyEmissionToSeconds(3780)], +// displayChain: Chain.Solana, +// coin: Coins.USD, +// }, +// { +// name: 'pUSDC (Optics V1)', +// tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xcC82628f6A8dEFA1e2B0aD7ed448bef3647F7941'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', +// decimals: 18, +// symbol: 'cUSD', +// name: 'Celo Dollar', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xcC82628f6A8dEFA1e2B0aD7ed448bef3647F7941', +// decimals: 6, +// symbol: 'pUSDCxV1', +// name: 'USD Coin (PoS Optics)', +// logoURI: 'https://bit.ly/3CwGimW', +// }, +// [] +// ), +// ], +// address: '0x2080AAa167e2225e1FC9923250bA60E19a180Fb2', +// lpToken: new Token( +// ChainId.MAINNET, +// '0xf5b454cF47Caca418D95930AA03975Ee4bf409bc', +// 18, +// 'MobLP', +// 'Mobius cUSD/pUSDC LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('6')], +// peggedTo: '$', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0x52517feb1Fc6141d5CF6718111C7Cc0FD764fA5d', +// additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], +// additionalRewardRate: ['0'], // ['2190848200000000'], +// displayChain: Chain.Polygon, +// coin: Coins.USD, +// isKilled: true, +// }, +// { +// name: 'wBTC (Optics V1)', +// tokenAddresses: ['0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', '0xBe50a3013A1c94768A1ABb78c3cB79AB28fc1aCE'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', +// decimals: 18, +// symbol: 'cBTC', +// name: 'Wrapped Bitcoin', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cBTC.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xBe50a3013A1c94768A1ABb78c3cB79AB28fc1aCE', +// decimals: 8, +// symbol: 'wBTCxV1', +// name: 'Wrapped Bitcoin (Optics Bridge)', +// logoURI: 'https://etherscan.io/token/images/wbtc_28.png?v=1', +// }, +// [] +// ), +// ], +// address: '0x19260b9b573569dDB105780176547875fE9fedA3', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x8cD0E2F11ed2E896a8307280dEEEE15B27e46BbE', +// 18, +// 'MobLP', +// 'Mobius cBTC/wBTC LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('8')], +// peggedTo: '₿', +// pegComesAfter: true, +// displayDecimals: 2, +// gaugeAddress: '0x1A8938a37093d34581B21bAd2AE7DC1c19150C05', +// displayChain: Chain.Ethereum, +// coin: Coins.Bitcoin, +// isKilled: true, +// }, +// { +// name: 'WETH (Optics V1)', +// tokenAddresses: ['0x2DEf4285787d58a2f811AF24755A8150622f4361', '0xE919F65739c26a42616b7b8eedC6b5524d1e3aC4'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x2DEf4285787d58a2f811AF24755A8150622f4361', +// decimals: 18, +// symbol: 'cETH', +// name: 'Wrapped Ethereum', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cETH.svg', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xE919F65739c26a42616b7b8eedC6b5524d1e3aC4', +// decimals: 18, +// symbol: 'wETHxV1', +// name: 'Wrapped Ether (Optics Bridge)', +// logoURI: 'https://etherscan.io/token/images/weth_28.png', +// }, +// [] +// ), +// ], +// address: '0xE0F2cc70E52f05eDb383313393d88Df2937DA55a', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x846b784Ab5302155542c1B3952B54305F220fd84', +// 18, +// 'MobLP', +// 'Mobius cETH/wETH LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: 'Ξ', +// pegComesAfter: true, +// displayDecimals: 2, +// gaugeAddress: '0xD38e76E17E66b562B61c149Ca0EE53CEa1145733', +// displayChain: Chain.Ethereum, +// coin: Coins.Ether, +// isKilled: true, +// }, +// { +// name: 'USDT (Moss)', +// tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0xcFFfE0c89a779c09Df3DF5624f54cDf7EF5fDd5D'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', +// decimals: 18, +// symbol: 'cUSD', +// name: 'Celo Dollar', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0xcFFfE0c89a779c09Df3DF5624f54cDf7EF5fDd5D', +// decimals: 18, +// symbol: 'cUSDTm', +// name: 'Tether (Moss Bridge)', +// logoURI: 'https://bit.ly/3AMrCyD', +// }, +// [] +// ), +// ], +// address: '0xdBF27fD2a702Cc02ac7aCF0aea376db780D53247', +// lpToken: new Token( +// ChainId.MAINNET, +// '0xC7a4c6EF4A16Dc24634Cc2A951bA5Fec4398f7e0', +// 18, +// 'MobLP', +// 'Mobius cUSD/cUSDT LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: '$', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0xe2d6095685248F38Ae9fef1b360D772b78Ea19D1', +// displayChain: Chain.Ethereum, +// coin: Coins.USD, +// }, +// { +// name: 'USDC (Moss)', +// tokenAddresses: ['0x765DE816845861e75A25fCA122bb6898B8B1282a', '0x93DB49bE12B864019dA9Cb147ba75cDC0506190e'], +// tokens: [ +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x765DE816845861e75A25fCA122bb6898B8B1282a', +// decimals: 18, +// symbol: 'cUSD', +// name: 'Celo Dollar', +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cUSD.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// chainId: ChainId.MAINNET, +// address: '0x93DB49bE12B864019dA9Cb147ba75cDC0506190e', +// decimals: 18, +// symbol: 'cUSDCm', +// name: 'US Dollar Coin (Moss Bridge)', +// logoURI: 'https://bit.ly/3CwGimW', +// }, +// [] +// ), +// ], +// address: '0x0ff04189Ef135b6541E56f7C638489De92E9c778', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x635aec36c4b61bac5eB1C3EEe191147d006F8a21', +// 18, +// 'MobLP', +// 'Mobius cUSD/cUSDC LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: '$', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0xd1B3C05FE24bda6F52e704daf1ACBa8c440d8573', +// additionalRewards: ['0x471EcE3750Da237f93B8E339c536989b8978a438'], +// additionalRewardRate: ['0'], //['730282730000000'], +// displayChain: Chain.Ethereum, +// coin: Coins.USD, +// }, +// { +// name: 'Poof CELO V1', +// warningType: WarningType.POOF, +// tokenAddresses: ['0x471EcE3750Da237f93B8E339c536989b8978a438', '0xE74AbF23E1Fdf7ACbec2F3a30a772eF77f1601E1'], +// tokens: [ +// new WrappedTokenInfo( +// { +// address: '0x471EcE3750Da237f93B8E339c536989b8978a438', +// name: 'Celo', +// symbol: 'CELO', +// chainId: 42220, +// decimals: 18, +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_CELO.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// address: '0xE74AbF23E1Fdf7ACbec2F3a30a772eF77f1601E1', +// name: 'Poof Celo V1', +// symbol: 'pCELOxV1', +// chainId: 42220, +// decimals: 18, +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pCELO.png', +// }, +// [] +// ), +// ], +// address: '0x413FfCc28e6cDDE7e93625Ef4742810fE9738578', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x4D6B17828d0173668e8Eb730106444556a98c0F9', +// 18, +// 'MobLP', +// 'Mobius pCelo V1 LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: 'Celo', +// pegComesAfter: true, +// displayDecimals: 0, +// gaugeAddress: '0x5489b2F0A1992b889F47601D71E068Fd15c63f26', +// additionalRewards: ['0x00400FcbF0816bebB94654259de7273f4A05c762', '0x17700282592D6917F6A73D0bF8AcCf4D578c131e'], +// additionalRewardRate: ['0', '0'], +// // additionalRewards: [''], +// // additionalRewardRate: ['730282730000000'], +// displayChain: Chain.Celo, +// coin: Coins.Celo, +// isKilled: true, +// }, +// { +// name: 'Poof cEUR V1', +// warningType: WarningType.POOF, +// tokenAddresses: ['0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73', '0x56072D4832642dB29225dA12d6Fd1290E4744682'], +// tokens: [ +// new WrappedTokenInfo( +// { +// address: '0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73', +// name: 'Celo Euro', +// symbol: 'cEUR', +// chainId: 42220, +// decimals: 18, +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cEUR.png', +// }, +// [] +// ), +// new WrappedTokenInfo( +// { +// address: '0x56072D4832642dB29225dA12d6Fd1290E4744682', +// name: 'Poof EUR V1', +// symbol: 'pEURxV1', +// chainId: 42220, +// decimals: 18, +// logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pEUR.png', +// }, +// [] +// ), +// ], +// address: '0x382Ed834c6b7dBD10E4798B08889eaEd1455E820', +// lpToken: new Token( +// ChainId.MAINNET, +// '0x2642Ab16Bfb7A8b36EE42c9CbA2289C4Ca9F33b9', +// 18, +// 'MobLP', +// 'Mobius pEUR V1 LP' +// ), +// swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// lendingPrecision: JSBI.BigInt('1'), +// precision: JSBI.BigInt('18'), +// feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// feeIndex: 0, +// decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// peggedTo: '€', +// pegComesAfter: false, +// displayDecimals: 0, +// gaugeAddress: '0xCF34F4ec5DC9E09428A4f4a45475f6277694166c', +// additionalRewards: ['0x00400FcbF0816bebB94654259de7273f4A05c762', '0x17700282592D6917F6A73D0bF8AcCf4D578c131e'], +// additionalRewardRate: ['0', '0'], +// // additionalRewards: [''], +// // additionalRewardRate: ['730282730000000'], +// displayChain: Chain.Celo, +// coin: Coins.Eur, +// isKilled: true, +// }, +// // { +// // name: 'Poof cUSD V1 [DISABLED]', +// // warningType: WarningType.POOF, +// // tokenAddresses: ['0xB4aa2986622249B1F45eb93F28Cfca2b2606d809'], +// // tokens: [ +// // new WrappedTokenInfo( +// // { +// // chainId: ChainId.MAINNET, +// // address: '0xB4aa2986622249B1F45eb93F28Cfca2b2606d809', +// // decimals: 18, +// // symbol: 'pUSDxV1', +// // name: 'Poof USD V1', +// // logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pUSD.png', +// // }, +// // [] +// // ), +// // new WrappedTokenInfo( +// // { +// // chainId: ChainId.MAINNET, +// // address: '0xd7Bf6946b740930c60131044bD2F08787e1DdBd4', +// // decimals: 18, +// // symbol: 'Mob LP', +// // name: 'Mobius USDC LP', +// // logoURI: 'https://bit.ly/3CwGimW', +// // }, +// // [] +// // ), +// // ], +// // address: '0x81B6a3d9f725AB5d706d9e552b128bC5bB0B58a1', +// // lpToken: new Token( +// // ChainId.MAINNET, +// // '0x57f008172cF89b972db3db7dD032e66BE4AF1A8c', +// // 18, +// // 'MobLP', +// // 'Mobius pUSD Meta LP' +// // ), +// // swapFee: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('7')), +// // rates: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// // lendingPrecision: JSBI.BigInt('1'), +// // precision: JSBI.BigInt('18'), +// // feeDenominator: JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('10')), +// // precisionMul: [JSBI.BigInt('1'), JSBI.BigInt('1')], +// // feeIndex: 0, +// // decimals: [JSBI.BigInt('18'), JSBI.BigInt('18')], +// // peggedTo: '$', +// // pegComesAfter: false, +// // displayDecimals: 0, +// // gaugeAddress: '0x1250D6dd3B51D20c14a8ECb10CC2dd713967767e', +// // metaPool: 'USDC (Optics)', +// // displayChain: Chain.Celo, +// // coin: Coins.USD, +// // disabled: true, +// // isKilled: true, +// // }, +// ], +// [ChainId.ALFAJORES]: [], +// [ChainId.BAKLAVA]: [], +// } //todo: replace Mainnet and Baklava Pool Addresses type AddressMap = { [K in ChainId]: string } - -export const LP_VEST_ADDRESSES: AddressMap = { - [ChainId.MAINNET]: '0x74Fc71eF736feeaCfd58aeb2543c5fe4d33aDc14', - [ChainId.ALFAJORES]: '0x9ff6d45F5900D7aCBdCb6d79fFFf22C9F63dF040', - [ChainId.BAKLAVA]: '', -} - -export const FOUNDER_VEST_ADDRESSES: AddressMap = { - [ChainId.MAINNET]: '0x34deFd314fa23821a87FCbF5393311Bc5B7608C1', - [ChainId.ALFAJORES]: '0x9ff6d45F5900D7aCBdCb6d79fFFf22C9F63dF040', - [ChainId.BAKLAVA]: '', -} - -export const INVESTOR_VEST_ADDRESSES: AddressMap = { - [ChainId.MAINNET]: '0x5498248EaB20ff314bC465268920B48eed4Cdb7C', - [ChainId.ALFAJORES]: '0x9ff6d45F5900D7aCBdCb6d79fFFf22C9F63dF040', - [ChainId.BAKLAVA]: '', -} - -export const ADVISOR_VEST_ADDRESSES: AddressMap = { - [ChainId.MAINNET]: '0x54Bf52862E1Fdf0D43D9B19Abb5ec72acA0a25A6', - [ChainId.ALFAJORES]: '0x9ff6d45F5900D7aCBdCb6d79fFFf22C9F63dF040', - [ChainId.BAKLAVA]: '', -} - -export const VestingAddresses: { [type in VestType]: AddressMap } = { - [VestType.FOUNDER]: FOUNDER_VEST_ADDRESSES, - [VestType.ADVISOR]: ADVISOR_VEST_ADDRESSES, - [VestType.INVESTOR]: INVESTOR_VEST_ADDRESSES, - [VestType.LP]: LP_VEST_ADDRESSES, -} diff --git a/src/constants/index.ts b/src/constants/index.ts index b0fe4add792..53d2c14e442 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -23,7 +23,7 @@ export const POOL_PROXY = '0x1bc2DbB8c4d04AaCF4A7fefcDB060766964B5237' // used for display in the default list when adding liquidity export const SUGGESTED_BASES: ChainTokenList = {} -export const CHAIN = ChainId.MAINNET +export const CHAIN = ChainId.Mainnet // default allowed slippage, in bips export const INITIAL_ALLOWED_SLIPPAGE = 50 diff --git a/src/constants/mento.ts b/src/constants/mento.ts index 80dcef0def9..81ddc3c192d 100644 --- a/src/constants/mento.ts +++ b/src/constants/mento.ts @@ -20,7 +20,7 @@ export interface IMentoExchangeInfo { } export const MENTO_POOL_INFO: { [K in ChainId]: IMentoExchange[] } = { - [ChainId.MAINNET]: [ + [ChainId.Mainnet]: [ { stable: StableToken.cUSD, contract: CeloContract.Exchange, @@ -34,6 +34,6 @@ export const MENTO_POOL_INFO: { [K in ChainId]: IMentoExchange[] } = { contract: CeloContract.ExchangeBRL, }, ], - [ChainId.ALFAJORES]: [], - [ChainId.BAKLAVA]: [], + [ChainId.Alfajores]: [], + [ChainId.Baklava]: [], } diff --git a/src/constants/pools.ts b/src/constants/pools.ts index 5092a63f51b..7b9ba22167b 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -1,6 +1,10 @@ import JSBI from 'jsbi' import { ChainId, Percent, Token, TokenAmount } from 'lib/token-utils' +import celoLogo from '../assets/images/celo-chain-logo.png' +import ethLogo from '../assets/images/ethereum-chain-logo.png' +import polygonLogo from '../assets/images/polygon-chain-logo.png' +import terraLogo from '../assets/images/terra-logo.png' import { CHAIN } from './' import { CELO, CETH, CUSD, UST, WETH } from './tokens' @@ -112,6 +116,15 @@ export enum Chain { Terra, } +export const ChainLogo: { [c in Chain]: string } = { + [Chain.Celo]: celoLogo, + [Chain.Ethereum]: ethLogo, + [Chain.Polygon]: polygonLogo, + [Chain.Solana]: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_SOL.png', + [Chain.Avax]: 'https://s2.coinmarketcap.com/static/img/coins/64x64/5805.png', + [Chain.Terra]: terraLogo, +} + export interface DisplayPool { name: string chain: Chain @@ -142,7 +155,7 @@ export const RECOMMENDED_FEES: Fees = { export const RECOMMENDED_AMP = JSBI.BigInt('100') export const StablePools: { [K in ChainId]: DisplayPool[] } = { - [ChainId.MAINNET]: [ + [ChainId.Mainnet]: [ { name: 'UST (Allbridge)', chain: Chain.Terra, @@ -150,13 +163,13 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { pool: { address: '0x9F4AdBD0af281C69a582eB2E6fa2A594D4204CAe', lpToken: new Token({ - chainId: ChainId.MAINNET, + chainId: ChainId.Mainnet, address: '0x9438e7281D7E3e99A9dD21e0EAd9c6a254e17ab2', decimals: 18, symbol: 'MobLP', name: 'Mobius cUSD/aUST LP', }), - tokens: [CUSD[ChainId.MAINNET], UST[ChainId.MAINNET]], + tokens: [CUSD[ChainId.Mainnet], UST[ChainId.Mainnet]], }, gauge: { address: '0x107F94409746E8c8E6eFF139A100D17D9ca7FdfE', @@ -170,13 +183,13 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { pool: { address: '0x74ef28D635c6C5800DD3Cd62d4c4f8752DaACB09', lpToken: new Token({ - chainId: ChainId.MAINNET, + chainId: ChainId.Mainnet, address: '0x4fF08e2a4E7114af4B575AeF9250144f95790982', decimals: 18, symbol: 'MobLP', name: 'Mobius cUSD/aUST LP', }), - tokens: [CETH[ChainId.MAINNET], WETH[ChainId.MAINNET]], + tokens: [CETH[ChainId.Mainnet], WETH[ChainId.Mainnet]], }, gauge: { address: '0x487c30CB18AA9Ced435911E2B414e0e85D7E52bB', @@ -184,6 +197,6 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { }, }, ], - [ChainId.ALFAJORES]: [], - [ChainId.BAKLAVA]: [], + [ChainId.Alfajores]: [], + [ChainId.Baklava]: [], } diff --git a/src/constants/staking.ts b/src/constants/staking.ts index a7bc445ef79..e5772b58769 100644 --- a/src/constants/staking.ts +++ b/src/constants/staking.ts @@ -5,7 +5,25 @@ import { CELO } from './tokens' export const ExternalRewardsToken = CELO export const ExternalStakingRewards: { [K in ChainId]: string } = { - [ChainId.MAINNET]: '0x0812f6de916667C5aa820E757704c4ac69159529', - [ChainId.ALFAJORES]: '', - [ChainId.BAKLAVA]: '', + [ChainId.Mainnet]: '0x0812f6de916667C5aa820E757704c4ac69159529', + [ChainId.Alfajores]: '', + [ChainId.Baklava]: '', +} + +export const MOBIUS_MINTER_ADDRESS: { [K in ChainId]: string } = { + [ChainId.Mainnet]: '0x5F0200CA03196D5b817E2044a0Bb0D837e0A7823', + [ChainId.Alfajores]: '0x5c212FA1cf8b1143f2142C26161e65404034c01f', + [ChainId.Baklava]: '', +} + +export const GAUGE_CONTROLLER: { [K in ChainId]: string } = { + [ChainId.Mainnet]: '0x7530E03056D3a8eD0323e61091ea2f17a1aC5C25', + [ChainId.Alfajores]: '0x00063Fbe0c90834EE90C6191d0D9F04eaB01A14f', + [ChainId.Baklava]: '', +} + +export const GAUGE_PROXY: { [K in ChainId]: string } = { + [ChainId.Mainnet]: '0x0a3Ac12422C95F84b5bD18A6d9904d132a161C68', + [ChainId.Alfajores]: '', + [ChainId.Baklava]: '', } diff --git a/src/constants/tokens.ts b/src/constants/tokens.ts index 6e6212ba2b4..a00fe5d54c7 100644 --- a/src/constants/tokens.ts +++ b/src/constants/tokens.ts @@ -1,5 +1,6 @@ import { ChainId, Token } from 'lib/token-utils' import mapValues from 'lodash/mapValues' +import { VestType } from 'state/claim/reducer' const makeTokens = ( addresses: { [net in ChainId]: string }, @@ -15,9 +16,9 @@ const makeTokens = ( export const MOBI = makeTokens( { - [ChainId.MAINNET]: '0x73a210637f6F6B7005512677Ba6B3C96bb4AA44B', - [ChainId.ALFAJORES]: '0x17a139f275102bBaB5BcbF1c4b7143F08B635EA2', - [ChainId.BAKLAVA]: '0x00Be915B9dCf56a3CBE739D9B9c202ca692409EC', + [ChainId.Mainnet]: '0x73a210637f6F6B7005512677Ba6B3C96bb4AA44B', + [ChainId.Alfajores]: '0x17a139f275102bBaB5BcbF1c4b7143F08B635EA2', + [ChainId.Baklava]: '0x00Be915B9dCf56a3CBE739D9B9c202ca692409EC', }, 18, 'MOBI', @@ -27,9 +28,9 @@ export const MOBI = makeTokens( export const CELO = makeTokens( { - [ChainId.MAINNET]: '0x471EcE3750Da237f93B8E339c536989b8978a438', - [ChainId.ALFAJORES]: '0xF194afDf50B03e69Bd7D057c1Aa9e10c9954E4C9', - [ChainId.BAKLAVA]: '0xF194afDf50B03e69Bd7D057c1Aa9e10c9954E4C9', + [ChainId.Mainnet]: '0x471EcE3750Da237f93B8E339c536989b8978a438', + [ChainId.Alfajores]: '0xF194afDf50B03e69Bd7D057c1Aa9e10c9954E4C9', + [ChainId.Baklava]: '0xF194afDf50B03e69Bd7D057c1Aa9e10c9954E4C9', }, 18, 'CELO', @@ -39,9 +40,9 @@ export const CELO = makeTokens( export const CUSD = makeTokens( { - [ChainId.MAINNET]: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - [ChainId.ALFAJORES]: '0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1', - [ChainId.BAKLAVA]: '0x62492A644A588FD904270BeD06ad52B9abfEA1aE', + [ChainId.Mainnet]: '0x765DE816845861e75A25fCA122bb6898B8B1282a', + [ChainId.Alfajores]: '0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1', + [ChainId.Baklava]: '0x62492A644A588FD904270BeD06ad52B9abfEA1aE', }, 18, 'cUSD', @@ -51,9 +52,9 @@ export const CUSD = makeTokens( export const CEUR = makeTokens( { - [ChainId.MAINNET]: '0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73', - [ChainId.ALFAJORES]: '0x10c892A6EC43a53E45D0B916B4b7D383B1b78C0F', - [ChainId.BAKLAVA]: '0xf9ecE301247aD2CE21894941830A2470f4E774ca', + [ChainId.Mainnet]: '0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73', + [ChainId.Alfajores]: '0x10c892A6EC43a53E45D0B916B4b7D383B1b78C0F', + [ChainId.Baklava]: '0xf9ecE301247aD2CE21894941830A2470f4E774ca', }, 18, 'cEUR', @@ -63,9 +64,9 @@ export const CEUR = makeTokens( export const CREAL = makeTokens( { - [ChainId.MAINNET]: '0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787', - [ChainId.ALFAJORES]: '0xE4D517785D091D3c54818832dB6094bcc2744545', - [ChainId.BAKLAVA]: '0xf9ecE301247aD2CE21894941830A2470f4E774ca', + [ChainId.Mainnet]: '0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787', + [ChainId.Alfajores]: '0xE4D517785D091D3c54818832dB6094bcc2744545', + [ChainId.Baklava]: '0xf9ecE301247aD2CE21894941830A2470f4E774ca', }, 18, 'cREAL', @@ -75,9 +76,9 @@ export const CREAL = makeTokens( export const VEMOBI = makeTokens( { - [ChainId.MAINNET]: '0xd813a846aA9D572140d7ABBB4eFaC8cD786b4c0E', - [ChainId.ALFAJORES]: '0x7d64708ecf5201cfE74364424AddB0A8FD32174f', - [ChainId.BAKLAVA]: '0xFe2434bcE62C9B4845fe0C57438f5F86fA4771A7', + [ChainId.Mainnet]: '0xd813a846aA9D572140d7ABBB4eFaC8cD786b4c0E', + [ChainId.Alfajores]: '0x7d64708ecf5201cfE74364424AddB0A8FD32174f', + [ChainId.Baklava]: '0xFe2434bcE62C9B4845fe0C57438f5F86fA4771A7', }, 18, 'veMOBI', @@ -87,9 +88,9 @@ export const VEMOBI = makeTokens( export const UST = makeTokens( { - [ChainId.MAINNET]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', - [ChainId.ALFAJORES]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', - [ChainId.BAKLAVA]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', + [ChainId.Mainnet]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', + [ChainId.Alfajores]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', + [ChainId.Baklava]: '0xEd193C4E69F591E42398eF54DEa65aa1bb02835c', }, 18, 'UST', @@ -99,9 +100,9 @@ export const UST = makeTokens( export const CETH = makeTokens( { - [ChainId.MAINNET]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', - [ChainId.ALFAJORES]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', - [ChainId.BAKLAVA]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', + [ChainId.Mainnet]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', + [ChainId.Alfajores]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', + [ChainId.Baklava]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', }, 18, 'cETH', @@ -111,9 +112,9 @@ export const CETH = makeTokens( export const WETH = makeTokens( { - [ChainId.MAINNET]: '0x122013fd7dF1C6F636a5bb8f03108E876548b455', - [ChainId.ALFAJORES]: '0x122013fd7dF1C6F636a5bb8f03108E876548b455', - [ChainId.BAKLAVA]: '0x122013fd7dF1C6F636a5bb8f03108E876548b455', + [ChainId.Mainnet]: '0x122013fd7dF1C6F636a5bb8f03108E876548b455', + [ChainId.Alfajores]: '0x122013fd7dF1C6F636a5bb8f03108E876548b455', + [ChainId.Baklava]: '0x122013fd7dF1C6F636a5bb8f03108E876548b455', }, 18, 'wETH', @@ -122,12 +123,12 @@ export const WETH = makeTokens( ) export const ExternalRewards: { [K in ChainId]: Token[] } = { - [ChainId.MAINNET]: [ + [ChainId.Mainnet]: [ new Token({ address: '0x00400FcbF0816bebB94654259de7273f4A05c762', name: 'Poof', symbol: 'POOF', - chainId: ChainId.MAINNET, + chainId: ChainId.Mainnet, decimals: 18, logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_POOF.png', }), @@ -135,7 +136,7 @@ export const ExternalRewards: { [K in ChainId]: Token[] } = { address: '0x17700282592D6917F6A73D0bF8AcCf4D578c131e', name: 'Moola', symbol: 'MOO', - chainId: ChainId.MAINNET, + chainId: ChainId.Mainnet, decimals: 18, logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_MOO.png', }), @@ -143,11 +144,44 @@ export const ExternalRewards: { [K in ChainId]: Token[] } = { address: '0x471EcE3750Da237f93B8E339c536989b8978a438', name: 'Celo', symbol: 'CELO', - chainId: ChainId.MAINNET, + chainId: ChainId.Mainnet, decimals: 18, logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_CELO.png', }), ], - [ChainId.ALFAJORES]: [], - [ChainId.BAKLAVA]: [], + [ChainId.Alfajores]: [], + [ChainId.Baklava]: [], +} + +type AddressMap = { [K in ChainId]: string } + +export const LP_VEST_ADDRESSES: AddressMap = { + [ChainId.Mainnet]: '0x74Fc71eF736feeaCfd58aeb2543c5fe4d33aDc14', + [ChainId.Alfajores]: '0x9ff6d45F5900D7aCBdCb6d79fFFf22C9F63dF040', + [ChainId.Baklava]: '', +} + +export const FOUNDER_VEST_ADDRESSES: AddressMap = { + [ChainId.Mainnet]: '0x34deFd314fa23821a87FCbF5393311Bc5B7608C1', + [ChainId.Alfajores]: '0x9ff6d45F5900D7aCBdCb6d79fFFf22C9F63dF040', + [ChainId.Baklava]: '', +} + +export const INVESTOR_VEST_ADDRESSES: AddressMap = { + [ChainId.Mainnet]: '0x5498248EaB20ff314bC465268920B48eed4Cdb7C', + [ChainId.Alfajores]: '0x9ff6d45F5900D7aCBdCb6d79fFFf22C9F63dF040', + [ChainId.Baklava]: '', +} + +export const ADVISOR_VEST_ADDRESSES: AddressMap = { + [ChainId.Mainnet]: '0x54Bf52862E1Fdf0D43D9B19Abb5ec72acA0a25A6', + [ChainId.Alfajores]: '0x9ff6d45F5900D7aCBdCb6d79fFFf22C9F63dF040', + [ChainId.Baklava]: '', +} + +export const VestingAddresses: { [type in VestType]: AddressMap } = { + [VestType.FOUNDER]: FOUNDER_VEST_ADDRESSES, + [VestType.ADVISOR]: ADVISOR_VEST_ADDRESSES, + [VestType.INVESTOR]: INVESTOR_VEST_ADDRESSES, + [VestType.LP]: LP_VEST_ADDRESSES, } diff --git a/src/hooks/useColor.ts b/src/hooks/useColor.ts index 64cda5f9def..7769522390f 100644 --- a/src/hooks/useColor.ts +++ b/src/hooks/useColor.ts @@ -1,6 +1,5 @@ -import { DisplayPool } from 'constants/pools' -import { Coins, STATIC_POOL_INFO } from 'constants/StablePools' -import { ChainId, Token } from 'lib/token-utils' +import { Coins, DisplayPool } from 'constants/pools' +import { Token } from 'lib/token-utils' import Vibrant from 'node-vibrant' import { shade } from 'polished' import { useLayoutEffect, useState } from 'react' @@ -10,19 +9,7 @@ import { hex } from 'wcag-contrast' const images: Record = {} -const stablePoolTokens = Object.values(STATIC_POOL_INFO) - .flatMap((pools) => pools) - .flatMap(({ tokens }) => tokens) - -stablePoolTokens.forEach((token) => { - images[token.address] = token.logoURI ?? '' -}) - async function getColorFromToken(token: Token): Promise { - if (token.chainId === ChainId.ALFAJORES && token.address === '0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735') { - return Promise.resolve('#FAAB14') - } - const path = images[token.address] if (!path) { return '#35D07F' diff --git a/src/hooks/useContract.ts b/src/hooks/useContract.ts index b259e515078..78e0885c8cf 100644 --- a/src/hooks/useContract.ts +++ b/src/hooks/useContract.ts @@ -1,6 +1,6 @@ import { Contract } from '@ethersproject/contracts' import { GOVERNANCE_ADDRESS } from 'constants/governance' -import { GAUGE_CONTROLLER as GAUGE_CONTROLLER_ADDRESS, MOBIUS_MINTER_ADDRESS } from 'constants/StablePools' +import { GAUGE_CONTROLLER as GAUGE_CONTROLLER_ADDRESS, MOBIUS_MINTER_ADDRESS } from 'constants/staking' import { VEMOBI } from 'constants/tokens' import { useMemo } from 'react' diff --git a/src/hooks/useExternalStakingRewards.ts b/src/hooks/useExternalStakingRewards.ts index 19c1d2cda4e..5fa1e5adab7 100644 --- a/src/hooks/useExternalStakingRewards.ts +++ b/src/hooks/useExternalStakingRewards.ts @@ -1,4 +1,3 @@ -import { calcApy } from 'components/earn/StablePoolCard' import { ExternalRewardsToken } from 'constants/staking' import JSBI from 'jsbi' import { Percent, TokenAmount } from 'lib/token-utils' diff --git a/src/lib/token-utils/index.ts b/src/lib/token-utils/index.ts index 7f55ba73836..c619a621264 100644 --- a/src/lib/token-utils/index.ts +++ b/src/lib/token-utils/index.ts @@ -6,7 +6,6 @@ export * from './tokenList' // re-export token-math types // so consumers don't need to use them -export { ChainId } from '@ubeswap/sdk' export type { BigintIsh, IFormatUint, NumberFormat } from '@ubeswap/token-math' export { Fraction, diff --git a/src/lib/token-utils/splTokenRegistry.ts b/src/lib/token-utils/splTokenRegistry.ts index 8e1fb046271..c20ee8d8eba 100644 --- a/src/lib/token-utils/splTokenRegistry.ts +++ b/src/lib/token-utils/splTokenRegistry.ts @@ -1,4 +1,3 @@ -import { ChainId } from './' /** * These types all come from the @solana/spl-token-registry package. * @@ -6,7 +5,17 @@ import { ChainId } from './' * that package, which is massive. */ -export declare enum NetworkNames { +export enum ChainId { + Mainnet = 42220, + Alfajores = 44787, + Baklava = 62320, +} +export enum TradeType { + EXACT_INPUT = 0, + EXACT_OUTPUT = 1, +} + +export enum NetworkNames { Alfajores = 'Alfajores', Baklava = 'Baklava', Mainnet = 'Mainnet', @@ -25,21 +34,21 @@ export const Alfajores: Network = { rpcUrl: 'https://alfajores-forno.celo-testnet.org', graphQl: 'https://alfajores-blockscout.celo-testnet.org/graphiql', explorer: 'https://alfajores-blockscout.celo-testnet.org', - chainId: ChainId.ALFAJORES, + chainId: ChainId.Alfajores, } export const Baklava: Network = { name: NetworkNames.Baklava, rpcUrl: 'https://baklava-forno.celo-testnet.org', graphQl: 'https://baklava-blockscout.celo-testnet.org/graphiql', explorer: 'https://baklava-blockscout.celo-testnet.org', - chainId: ChainId.BAKLAVA, + chainId: ChainId.Baklava, } export const Mainnet: Network = { name: NetworkNames.Mainnet, rpcUrl: 'https://forno.celo.org', graphQl: 'https://explorer.celo.org/graphiql', explorer: 'https://explorer.celo.org', - chainId: ChainId.MAINNET, + chainId: ChainId.Mainnet, } /** diff --git a/src/lib/token-utils/tokenAmount.ts b/src/lib/token-utils/tokenAmount.ts index a68939b7387..0d1ca2eaa6a 100644 --- a/src/lib/token-utils/tokenAmount.ts +++ b/src/lib/token-utils/tokenAmount.ts @@ -1,6 +1,5 @@ import type { BigintIsh, NumberFormat, Percent } from '@ubeswap/token-math' -import { parseBigintIsh, TokenAmount as UTokenAmount, validateU64 } from '@ubeswap/token-math' -import BN from 'bn.js' +import { TokenAmount as UTokenAmount, validateU64 } from '@ubeswap/token-math' import type { Token } from './token' @@ -50,15 +49,6 @@ export class TokenAmount extends UTokenAmount { return new TokenAmount(this.token, result.raw) } - /** - * Divides this TokenAmount by a raw integer. - * @param other - * @returns - */ - divideByInteger(other: BigintIsh): TokenAmount { - return new TokenAmount(this.token, this.toU64().div(new BN(parseBigintIsh(other).toString()))) - } - /** * Formats the token amount with units and decimal adjustment, e.g. "100.42 SOL" * @returns diff --git a/src/pages/Charts/index.tsx b/src/pages/Charts/index.tsx index b21594fe01b..90d2bd249ec 100644 --- a/src/pages/Charts/index.tsx +++ b/src/pages/Charts/index.tsx @@ -5,13 +5,11 @@ import Logo from 'components/Logo' import Row, { RowBetween, RowFixed } from 'components/Row' import Toggle from 'components/Toggle' import VolumeChart from 'components/VolumeChart' -import { ChainLogo, Coins, PRICE } from 'constants/StablePools' import useTheme from 'hooks/useTheme' import { useWindowSize } from 'hooks/useWindowSize' import React, { useState } from 'react' import { isMobile } from 'react-device-detect' import { usePools } from 'state/mobiusPools/hooks' -import { StableSwapPool } from 'state/stablePools/reducer' import styled from 'styled-components' import { Sel, TYPE } from 'theme' @@ -100,10 +98,6 @@ const timeFormat: { [g: Granularity]: (n: number) => string } = { [Granularity.Week]: (t: number) => new Date(t * 1000).toLocaleDateString(), } -function getPoolName(pools: StableSwapPool[], address: string) { - return pools.filter((p) => p.address.toLowerCase() == address)[0]?.name ?? 'Unknown' -} - export default function Charts() { const { data, loading, error } = useQuery(volumeQuery) const [granularity, setGranularity] = useState(Granularity.Week) diff --git a/src/pages/CreateProposal/index.tsx b/src/pages/CreateProposal/index.tsx index 7688bb01bde..d5b34890712 100644 --- a/src/pages/CreateProposal/index.tsx +++ b/src/pages/CreateProposal/index.tsx @@ -3,7 +3,7 @@ import { getAddress, isAddress } from '@ethersproject/address' import { ButtonError } from 'components/Button' import { BlueCard } from 'components/Card' import { AutoColumn } from 'components/Column' -import { GAUGE_CONTROLLER, GAUGE_PROXY } from 'constants/StablePools' +import { GAUGE_CONTROLLER, GAUGE_PROXY } from 'constants/staking' import { useWeb3Context } from 'hooks' import JSBI from 'jsbi' import { Token, TokenAmount } from 'lib/token-utils' diff --git a/src/pages/Pool/Manage.tsx b/src/pages/Pool/Manage.tsx index 30e4e568291..93b3b6ab175 100644 --- a/src/pages/Pool/Manage.tsx +++ b/src/pages/Pool/Manage.tsx @@ -7,10 +7,8 @@ import JSBI from 'jsbi' import { Fraction, TokenAmount } from 'lib/token-utils' import React, { useCallback, useState } from 'react' import { Link, RouteComponentProps } from 'react-router-dom' -import { useExternalRewards, useStablePoolInfoByName } from 'state/stablePools/hooks' import styled from 'styled-components' import { CountUp } from 'use-count-up' -import { getDepositValues } from 'utils/stableSwaps' import { ButtonEmpty, ButtonPrimary } from '../../components/Button' import { AutoColumn } from '../../components/Column' diff --git a/src/pages/Staking/Positions.tsx b/src/pages/Staking/Positions.tsx index 39b6922a623..0ada108cd37 100644 --- a/src/pages/Staking/Positions.tsx +++ b/src/pages/Staking/Positions.tsx @@ -2,8 +2,7 @@ import { ButtonPrimary } from 'components/Button' import { AutoColumn } from 'components/Column' import { CardNoise } from 'components/earn/styled' import { RowBetween, RowFixed } from 'components/Row' -import { DisplayPool, IGauge, StablePools } from 'constants/pools' -import { ChainLogo } from 'constants/StablePools' +import { ChainLogo, DisplayPool, IGauge, StablePools } from 'constants/pools' import { CUSD } from 'constants/tokens' import { usePoolColor } from 'hooks/useColor' import JSBI from 'jsbi' diff --git a/src/pages/Staking/Vote.tsx b/src/pages/Staking/Vote.tsx index 370d4c33ced..151ef31d649 100644 --- a/src/pages/Staking/Vote.tsx +++ b/src/pages/Staking/Vote.tsx @@ -1,7 +1,6 @@ import { AutoColumn } from 'components/Column' import { RowFixed } from 'components/Row' -import { DisplayPool, StablePools } from 'constants/pools' -import { ChainLogo } from 'constants/StablePools' +import { ChainLogo, DisplayPool, StablePools } from 'constants/pools' import { usePoolColor } from 'hooks/useColor' import { useVotePowerLeft } from 'hooks/useStaking' import React, { useState } from 'react' diff --git a/src/state/claim/updater.ts b/src/state/claim/updater.ts index 1437ca1b43d..78cdf009ddf 100644 --- a/src/state/claim/updater.ts +++ b/src/state/claim/updater.ts @@ -3,7 +3,7 @@ import { useEffect } from 'react' import { useDispatch } from 'react-redux' import { CHAIN } from '../../constants' -import { VestingAddresses } from '../../constants/StablePools' +import { VestingAddresses } from '../../constants/tokens' import { VestingEscrow } from '../../generated' import { useWeb3Context } from '../../hooks' import { useVestingContract } from '../../hooks/useContract' diff --git a/src/state/mento/reducer.test.ts b/src/state/mento/reducer.test.ts deleted file mode 100644 index 53ea44fa3e7..00000000000 --- a/src/state/mento/reducer.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { createStore, Store } from 'redux' - -import { Field, selectCurrency } from './actions' -import reducer, { SwapState } from './reducer' - -describe('swap reducer', () => { - let store: Store - - beforeEach(() => { - store = createStore(reducer, { - [Field.OUTPUT]: { currencyId: '' }, - [Field.INPUT]: { currencyId: '' }, - typedValue: '', - independentField: Field.INPUT, - recipient: null, - }) - }) - - describe('selectToken', () => { - it('changes token', () => { - store.dispatch( - selectCurrency({ - field: Field.OUTPUT, - currencyId: '0x0000', - }) - ) - - expect(store.getState()).toEqual({ - [Field.OUTPUT]: { currencyId: '0x0000' }, - [Field.INPUT]: { currencyId: '' }, - typedValue: '', - independentField: Field.INPUT, - recipient: null, - }) - }) - }) -}) diff --git a/src/state/multicall/actions.test.ts b/src/state/multicall/actions.test.ts deleted file mode 100644 index 8d2b816cbbb..00000000000 --- a/src/state/multicall/actions.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { parseCallKey, toCallKey } from './actions' - -describe('actions', () => { - describe('#parseCallKey', () => { - it('does not throw for invalid address', () => { - expect(parseCallKey('0x-0x')).toEqual({ address: '0x', callData: '0x' }) - }) - it('does not throw for invalid calldata', () => { - expect(parseCallKey('0x6b175474e89094c44da98b954eedeac495271d0f-abc')).toEqual({ - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - callData: 'abc', - }) - }) - it('throws for invalid format', () => { - expect(() => parseCallKey('abc')).toThrow('Invalid call key: abc') - }) - it('throws for uppercase calldata', () => { - expect(parseCallKey('0x6b175474e89094c44da98b954eedeac495271d0f-0xabcD')).toEqual({ - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - callData: '0xabcD', - }) - }) - it('parses pieces into address', () => { - expect(parseCallKey('0x6b175474e89094c44da98b954eedeac495271d0f-0xabcd')).toEqual({ - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - callData: '0xabcd', - }) - }) - }) - - describe('#toCallKey', () => { - it('throws for invalid address', () => { - expect(() => toCallKey({ callData: '0x', address: '0x' })).toThrow('Invalid address: 0x') - }) - it('throws for invalid calldata', () => { - expect(() => - toCallKey({ - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - callData: 'abc', - }) - ).toThrow('Invalid hex: abc') - }) - it('throws for uppercase hex', () => { - expect(() => - toCallKey({ - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - callData: '0xabcD', - }) - ).toThrow('Invalid hex: 0xabcD') - }) - it('concatenates address to data', () => { - expect(toCallKey({ address: '0x6b175474e89094c44da98b954eedeac495271d0f', callData: '0xabcd' })).toEqual( - '0x6b175474e89094c44da98b954eedeac495271d0f-0xabcd' - ) - }) - }) -}) diff --git a/src/state/multicall/reducer.test.ts b/src/state/multicall/reducer.test.ts deleted file mode 100644 index eaffd5e6a2d..00000000000 --- a/src/state/multicall/reducer.test.ts +++ /dev/null @@ -1,312 +0,0 @@ -import { createStore, Store } from '@reduxjs/toolkit' - -import { - addMulticallListeners, - errorFetchingMulticallResults, - fetchingMulticallResults, - removeMulticallListeners, - updateMulticallResults, -} from './actions' -import reducer, { MulticallState } from './reducer' - -const DAI_ADDRESS = '0x6b175474e89094c44da98b954eedeac495271d0f' - -describe('multicall reducer', () => { - let store: Store - beforeEach(() => { - store = createStore(reducer) - }) - - it('has correct initial state', () => { - expect(store.getState().callResults).toEqual({}) - expect(store.getState().callListeners).toEqual(undefined) - }) - - describe('addMulticallListeners', () => { - it('adds listeners', () => { - store.dispatch( - addMulticallListeners({ - chainId: 1, - calls: [ - { - address: DAI_ADDRESS, - callData: '0x', - }, - ], - }) - ) - expect(store.getState()).toEqual({ - callListeners: { - [1]: { - [`${DAI_ADDRESS}-0x`]: { - [1]: 1, - }, - }, - }, - callResults: {}, - }) - }) - }) - - describe('removeMulticallListeners', () => { - it('noop', () => { - store.dispatch( - removeMulticallListeners({ - calls: [ - { - address: DAI_ADDRESS, - callData: '0x', - }, - ], - chainId: 1, - }) - ) - expect(store.getState()).toEqual({ callResults: {}, callListeners: {} }) - }) - it('removes listeners', () => { - store.dispatch( - addMulticallListeners({ - chainId: 1, - calls: [ - { - address: DAI_ADDRESS, - callData: '0x', - }, - ], - }) - ) - store.dispatch( - removeMulticallListeners({ - calls: [ - { - address: DAI_ADDRESS, - callData: '0x', - }, - ], - chainId: 1, - }) - ) - expect(store.getState()).toEqual({ - callResults: {}, - callListeners: { [1]: { [`${DAI_ADDRESS}-0x`]: {} } }, - }) - }) - }) - - describe('updateMulticallResults', () => { - it('updates data if not present', () => { - store.dispatch( - updateMulticallResults({ - chainId: 1, - blockNumber: 1, - results: { - abc: '0x', - }, - }) - ) - expect(store.getState()).toEqual({ - callResults: { - [1]: { - abc: { - blockNumber: 1, - data: '0x', - }, - }, - }, - }) - }) - it('updates old data', () => { - store.dispatch( - updateMulticallResults({ - chainId: 1, - blockNumber: 1, - results: { - abc: '0x', - }, - }) - ) - store.dispatch( - updateMulticallResults({ - chainId: 1, - blockNumber: 2, - results: { - abc: '0x2', - }, - }) - ) - expect(store.getState()).toEqual({ - callResults: { - [1]: { - abc: { - blockNumber: 2, - data: '0x2', - }, - }, - }, - }) - }) - it('ignores late updates', () => { - store.dispatch( - updateMulticallResults({ - chainId: 1, - blockNumber: 2, - results: { - abc: '0x2', - }, - }) - ) - store.dispatch( - updateMulticallResults({ - chainId: 1, - blockNumber: 1, - results: { - abc: '0x1', - }, - }) - ) - expect(store.getState()).toEqual({ - callResults: { - [1]: { - abc: { - blockNumber: 2, - data: '0x2', - }, - }, - }, - }) - }) - }) - describe('fetchingMulticallResults', () => { - it('updates state to fetching', () => { - store.dispatch( - fetchingMulticallResults({ - chainId: 1, - fetchingBlockNumber: 2, - calls: [{ address: DAI_ADDRESS, callData: '0x0' }], - }) - ) - expect(store.getState()).toEqual({ - callResults: { - [1]: { - [`${DAI_ADDRESS}-0x0`]: { fetchingBlockNumber: 2 }, - }, - }, - }) - }) - - it('updates state to fetching even if already fetching older block', () => { - store.dispatch( - fetchingMulticallResults({ - chainId: 1, - fetchingBlockNumber: 2, - calls: [{ address: DAI_ADDRESS, callData: '0x0' }], - }) - ) - store.dispatch( - fetchingMulticallResults({ - chainId: 1, - fetchingBlockNumber: 3, - calls: [{ address: DAI_ADDRESS, callData: '0x0' }], - }) - ) - expect(store.getState()).toEqual({ - callResults: { - [1]: { - [`${DAI_ADDRESS}-0x0`]: { fetchingBlockNumber: 3 }, - }, - }, - }) - }) - - it('does not do update if fetching newer block', () => { - store.dispatch( - fetchingMulticallResults({ - chainId: 1, - fetchingBlockNumber: 2, - calls: [{ address: DAI_ADDRESS, callData: '0x0' }], - }) - ) - store.dispatch( - fetchingMulticallResults({ - chainId: 1, - fetchingBlockNumber: 1, - calls: [{ address: DAI_ADDRESS, callData: '0x0' }], - }) - ) - expect(store.getState()).toEqual({ - callResults: { - [1]: { - [`${DAI_ADDRESS}-0x0`]: { fetchingBlockNumber: 2 }, - }, - }, - }) - }) - }) - - describe('errorFetchingMulticallResults', () => { - it('does nothing if not fetching', () => { - store.dispatch( - errorFetchingMulticallResults({ - chainId: 1, - fetchingBlockNumber: 1, - calls: [{ address: DAI_ADDRESS, callData: '0x0' }], - }) - ) - expect(store.getState()).toEqual({ - callResults: { - [1]: {}, - }, - }) - }) - it('updates block number if we were fetching', () => { - store.dispatch( - fetchingMulticallResults({ - chainId: 1, - fetchingBlockNumber: 2, - calls: [{ address: DAI_ADDRESS, callData: '0x0' }], - }) - ) - store.dispatch( - errorFetchingMulticallResults({ - chainId: 1, - fetchingBlockNumber: 2, - calls: [{ address: DAI_ADDRESS, callData: '0x0' }], - }) - ) - expect(store.getState()).toEqual({ - callResults: { - [1]: { - [`${DAI_ADDRESS}-0x0`]: { - blockNumber: 2, - // null data indicates error - data: null, - }, - }, - }, - }) - }) - it('does nothing if not errored on latest block', () => { - store.dispatch( - fetchingMulticallResults({ - chainId: 1, - fetchingBlockNumber: 3, - calls: [{ address: DAI_ADDRESS, callData: '0x0' }], - }) - ) - store.dispatch( - errorFetchingMulticallResults({ - chainId: 1, - fetchingBlockNumber: 2, - calls: [{ address: DAI_ADDRESS, callData: '0x0' }], - }) - ) - expect(store.getState()).toEqual({ - callResults: { - [1]: { - [`${DAI_ADDRESS}-0x0`]: { fetchingBlockNumber: 3 }, - }, - }, - }) - }) - }) -}) diff --git a/src/state/multicall/updater.test.ts b/src/state/multicall/updater.test.ts deleted file mode 100644 index feaad4f36a2..00000000000 --- a/src/state/multicall/updater.test.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { activeListeningKeys, outdatedListeningKeys } from './updater' - -describe('multicall updater', () => { - describe('#activeListeningKeys', () => { - it('ignores 0, returns call key to block age key', () => { - expect( - activeListeningKeys( - { - [1]: { - ['abc']: { - 4: 2, // 2 listeners care about 4 block old data - 1: 0, // 0 listeners care about 1 block old data - }, - }, - }, - 1 - ) - ).toEqual({ - abc: 4, - }) - }) - it('applies min', () => { - expect( - activeListeningKeys( - { - [1]: { - ['abc']: { - 4: 2, // 2 listeners care about 4 block old data - 3: 1, // 1 listener cares about 3 block old data - 1: 0, // 0 listeners care about 1 block old data - }, - }, - }, - 1 - ) - ).toEqual({ - abc: 3, - }) - }) - it('works for infinity', () => { - expect( - activeListeningKeys( - { - [1]: { - ['abc']: { - 4: 2, // 2 listeners care about 4 block old data - 1: 0, // 0 listeners care about 1 block old data - }, - ['def']: { - Infinity: 2, - }, - }, - }, - 1 - ) - ).toEqual({ - abc: 4, - def: Infinity, - }) - }) - it('multiple keys', () => { - expect( - activeListeningKeys( - { - [1]: { - ['abc']: { - 4: 2, // 2 listeners care about 4 block old data - 1: 0, // 0 listeners care about 1 block old data - }, - ['def']: { - 2: 1, - 5: 2, - }, - }, - }, - 1 - ) - ).toEqual({ - abc: 4, - def: 2, - }) - }) - it('ignores negative numbers', () => { - expect( - activeListeningKeys( - { - [1]: { - ['abc']: { - 4: 2, - 1: -1, - [-3]: 4, - }, - }, - }, - 1 - ) - ).toEqual({ - abc: 4, - }) - }) - it('applies min to infinity', () => { - expect( - activeListeningKeys( - { - [1]: { - ['abc']: { - Infinity: 2, // 2 listeners care about any data - 4: 2, // 2 listeners care about 4 block old data - 1: 0, // 0 listeners care about 1 block old data - }, - }, - }, - 1 - ) - ).toEqual({ - abc: 4, - }) - }) - }) - - describe('#outdatedListeningKeys', () => { - it('returns empty if missing block number or chain id', () => { - expect(outdatedListeningKeys({}, { abc: 2 }, undefined, undefined)).toEqual([]) - expect(outdatedListeningKeys({}, { abc: 2 }, 1, undefined)).toEqual([]) - expect(outdatedListeningKeys({}, { abc: 2 }, undefined, 1)).toEqual([]) - }) - it('returns everything for no results', () => { - expect(outdatedListeningKeys({}, { abc: 2, def: 3 }, 1, 1)).toEqual(['abc', 'def']) - }) - it('returns only outdated keys', () => { - expect(outdatedListeningKeys({ [1]: { abc: { data: '0x', blockNumber: 2 } } }, { abc: 1, def: 1 }, 1, 2)).toEqual( - ['def'] - ) - }) - it('returns only keys not being fetched', () => { - expect( - outdatedListeningKeys( - { - [1]: { abc: { data: '0x', blockNumber: 2 }, def: { fetchingBlockNumber: 2 } }, - }, - { abc: 1, def: 1 }, - 1, - 2 - ) - ).toEqual([]) - }) - it('returns keys being fetched for old blocks', () => { - expect( - outdatedListeningKeys( - { [1]: { abc: { data: '0x', blockNumber: 2 }, def: { fetchingBlockNumber: 1 } } }, - { abc: 1, def: 1 }, - 1, - 2 - ) - ).toEqual(['def']) - }) - it('respects blocks per fetch', () => { - expect( - outdatedListeningKeys( - { [1]: { abc: { data: '0x', blockNumber: 2 }, def: { data: '0x', fetchingBlockNumber: 1 } } }, - { abc: 2, def: 2 }, - 1, - 3 - ) - ).toEqual(['def']) - }) - }) -}) diff --git a/src/state/swap/reducer.test.ts b/src/state/swap/reducer.test.ts deleted file mode 100644 index 53ea44fa3e7..00000000000 --- a/src/state/swap/reducer.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { createStore, Store } from 'redux' - -import { Field, selectCurrency } from './actions' -import reducer, { SwapState } from './reducer' - -describe('swap reducer', () => { - let store: Store - - beforeEach(() => { - store = createStore(reducer, { - [Field.OUTPUT]: { currencyId: '' }, - [Field.INPUT]: { currencyId: '' }, - typedValue: '', - independentField: Field.INPUT, - recipient: null, - }) - }) - - describe('selectToken', () => { - it('changes token', () => { - store.dispatch( - selectCurrency({ - field: Field.OUTPUT, - currencyId: '0x0000', - }) - ) - - expect(store.getState()).toEqual({ - [Field.OUTPUT]: { currencyId: '0x0000' }, - [Field.INPUT]: { currencyId: '' }, - typedValue: '', - independentField: Field.INPUT, - recipient: null, - }) - }) - }) -}) diff --git a/src/state/transactions/updater.test.ts b/src/state/transactions/updater.test.ts deleted file mode 100644 index 45f5d46fdc1..00000000000 --- a/src/state/transactions/updater.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { shouldCheck } from './updater' - -describe('transactions updater', () => { - describe('shouldCheck', () => { - it('returns true if no receipt and never checked', () => { - expect(shouldCheck(10, { addedTime: 100 })).toEqual(true) - }) - it('returns false if has receipt and never checked', () => { - expect(shouldCheck(10, { addedTime: 100, receipt: {} })).toEqual(false) - }) - it('returns true if has not been checked in 1 blocks', () => { - expect(shouldCheck(10, { addedTime: new Date().getTime(), lastCheckedBlockNumber: 9 })).toEqual(true) - }) - it('returns false if checked in last 3 blocks and greater than 20 minutes old', () => { - expect(shouldCheck(10, { addedTime: new Date().getTime() - 21 * 60 * 1000, lastCheckedBlockNumber: 8 })).toEqual( - false - ) - }) - it('returns true if not checked in last 5 blocks and greater than 20 minutes old', () => { - expect(shouldCheck(10, { addedTime: new Date().getTime() - 21 * 60 * 1000, lastCheckedBlockNumber: 5 })).toEqual( - true - ) - }) - it('returns false if checked in last 10 blocks and greater than 60 minutes old', () => { - expect(shouldCheck(20, { addedTime: new Date().getTime() - 61 * 60 * 1000, lastCheckedBlockNumber: 11 })).toEqual( - false - ) - }) - it('returns true if checked in last 3 blocks and greater than 20 minutes old', () => { - expect(shouldCheck(20, { addedTime: new Date().getTime() - 61 * 60 * 1000, lastCheckedBlockNumber: 10 })).toEqual( - true - ) - }) - }) -}) diff --git a/src/state/user/reducer.test.ts b/src/state/user/reducer.test.ts deleted file mode 100644 index 2e4aaf5c5b1..00000000000 --- a/src/state/user/reducer.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { createStore, Store } from 'redux' - -import { DEFAULT_DEADLINE_FROM_NOW, INITIAL_ALLOWED_SLIPPAGE } from '../../constants' -import { updateVersion } from '../global/actions' -import reducer, { initialState, UserState } from './reducer' - -describe('swap reducer', () => { - let store: Store - - beforeEach(() => { - store = createStore(reducer, initialState) - }) - - describe('updateVersion', () => { - it('has no timestamp originally', () => { - expect(store.getState().lastUpdateVersionTimestamp).toBeUndefined() - }) - it('sets the lastUpdateVersionTimestamp', () => { - const time = new Date().getTime() - store.dispatch(updateVersion()) - expect(store.getState().lastUpdateVersionTimestamp).toBeGreaterThanOrEqual(time) - }) - it('sets allowed slippage and deadline', () => { - store = createStore(reducer, { - ...initialState, - userDeadline: undefined, - userSlippageTolerance: undefined, - } as any) - store.dispatch(updateVersion()) - expect(store.getState().userDeadline).toEqual(DEFAULT_DEADLINE_FROM_NOW) - expect(store.getState().userSlippageTolerance).toEqual(INITIAL_ALLOWED_SLIPPAGE) - }) - }) -}) diff --git a/src/utils/chunkArray.test.ts b/src/utils/chunkArray.test.ts deleted file mode 100644 index 34b9bc5698b..00000000000 --- a/src/utils/chunkArray.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import chunkArray from './chunkArray' - -describe('#chunkArray', () => { - it('size 1', () => { - expect(chunkArray([1, 2, 3], 1)).toEqual([[1], [2], [3]]) - }) - it('size 0 throws', () => { - expect(() => chunkArray([1, 2, 3], 0)).toThrow('maxChunkSize must be gte 1') - }) - it('size gte items', () => { - expect(chunkArray([1, 2, 3], 3)).toEqual([[1, 2, 3]]) - expect(chunkArray([1, 2, 3], 4)).toEqual([[1, 2, 3]]) - }) - it('size exact half', () => { - expect(chunkArray([1, 2, 3, 4], 2)).toEqual([ - [1, 2], - [3, 4], - ]) - }) - it('evenly distributes', () => { - const chunked = chunkArray([...Array(100).keys()], 40) - - expect(chunked).toEqual([ - [...Array(34).keys()], - [...Array(34).keys()].map((i) => i + 34), - [...Array(32).keys()].map((i) => i + 68), - ]) - - expect(chunked[0][0]).toEqual(0) - expect(chunked[2][31]).toEqual(99) - }) -}) diff --git a/src/utils/parseENSAddress.test.ts b/src/utils/parseENSAddress.test.ts deleted file mode 100644 index 975449b6017..00000000000 --- a/src/utils/parseENSAddress.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { parseENSAddress } from './parseENSAddress' - -describe('parseENSAddress', () => { - it('test cases', () => { - expect(parseENSAddress('hello.eth')).toEqual({ ensName: 'hello.eth', ensPath: undefined }) - expect(parseENSAddress('hello.eth/')).toEqual({ ensName: 'hello.eth', ensPath: '/' }) - expect(parseENSAddress('hello.world.eth/')).toEqual({ ensName: 'hello.world.eth', ensPath: '/' }) - expect(parseENSAddress('hello.world.eth/abcdef')).toEqual({ ensName: 'hello.world.eth', ensPath: '/abcdef' }) - expect(parseENSAddress('abso.lutely')).toEqual(undefined) - expect(parseENSAddress('abso.lutely.eth')).toEqual({ ensName: 'abso.lutely.eth', ensPath: undefined }) - expect(parseENSAddress('eth')).toEqual(undefined) - expect(parseENSAddress('eth/hello-world')).toEqual(undefined) - expect(parseENSAddress('hello-world.eth')).toEqual({ ensName: 'hello-world.eth', ensPath: undefined }) - expect(parseENSAddress('-prefix-dash.eth')).toEqual(undefined) - expect(parseENSAddress('suffix-dash-.eth')).toEqual(undefined) - expect(parseENSAddress('it.eth')).toEqual({ ensName: 'it.eth', ensPath: undefined }) - expect(parseENSAddress('only-single--dash.eth')).toEqual(undefined) - }) -}) diff --git a/src/utils/retry.test.ts b/src/utils/retry.test.ts deleted file mode 100644 index fe1952ac320..00000000000 --- a/src/utils/retry.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { retry, RetryableError } from './retry' - -describe('retry', () => { - function makeFn(fails: number, result: T, retryable = true): () => Promise { - return async () => { - if (fails > 0) { - fails-- - throw retryable ? new RetryableError('failure') : new Error('bad failure') - } - return result - } - } - - it('fails for non-retryable error', async () => { - await expect(retry(makeFn(1, 'abc', false), { n: 3, maxWait: 0, minWait: 0 }).promise).rejects.toThrow( - 'bad failure' - ) - }) - - it('works after one fail', async () => { - await expect(retry(makeFn(1, 'abc'), { n: 3, maxWait: 0, minWait: 0 }).promise).resolves.toEqual('abc') - }) - - it('works after two fails', async () => { - await expect(retry(makeFn(2, 'abc'), { n: 3, maxWait: 0, minWait: 0 }).promise).resolves.toEqual('abc') - }) - - it('throws if too many fails', async () => { - await expect(retry(makeFn(4, 'abc'), { n: 3, maxWait: 0, minWait: 0 }).promise).rejects.toThrow('failure') - }) - - it('cancel causes promise to reject', async () => { - const { promise, cancel } = retry(makeFn(2, 'abc'), { n: 3, minWait: 100, maxWait: 100 }) - cancel() - await expect(promise).rejects.toThrow('Cancelled') - }) - - it('cancel no-op after complete', async () => { - const { promise, cancel } = retry(makeFn(0, 'abc'), { n: 3, minWait: 100, maxWait: 100 }) - // defer - setTimeout(cancel, 0) - await expect(promise).resolves.toEqual('abc') - }) - - async function checkTime(fn: () => Promise, min: number, max: number) { - const time = new Date().getTime() - await fn() - const diff = new Date().getTime() - time - expect(diff).toBeGreaterThanOrEqual(min) - expect(diff).toBeLessThanOrEqual(max) - } - - it('waits random amount of time between min and max', async () => { - const promises = [] - for (let i = 0; i < 10; i++) { - promises.push( - checkTime( - () => expect(retry(makeFn(4, 'abc'), { n: 3, maxWait: 100, minWait: 50 }).promise).rejects.toThrow('failure'), - 150, - 400 - ) - ) - } - await Promise.all(promises) - }) -}) diff --git a/src/utils/uriToHttp.test.ts b/src/utils/uriToHttp.test.ts deleted file mode 100644 index 8393a7bcf93..00000000000 --- a/src/utils/uriToHttp.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import uriToHttp from './uriToHttp' - -describe('uriToHttp', () => { - it('returns .eth.link for ens names', () => { - expect(uriToHttp('t2crtokens.eth')).toEqual([]) - }) - it('returns https first for http', () => { - expect(uriToHttp('http://test.com')).toEqual(['https://test.com', 'http://test.com']) - }) - it('returns https for https', () => { - expect(uriToHttp('https://test.com')).toEqual(['https://test.com']) - }) - it('returns ipfs gateways for ipfs:// urls', () => { - expect(uriToHttp('ipfs://QmV8AfDE8GFSGQvt3vck8EwAzsPuNTmtP8VcQJE3qxRPaZ')).toEqual([ - 'https://cloudflare-ipfs.com/ipfs/QmV8AfDE8GFSGQvt3vck8EwAzsPuNTmtP8VcQJE3qxRPaZ/', - 'https://ipfs.io/ipfs/QmV8AfDE8GFSGQvt3vck8EwAzsPuNTmtP8VcQJE3qxRPaZ/', - ]) - }) - it('returns ipns gateways for ipns:// urls', () => { - expect(uriToHttp('ipns://app.ubeswap.org')).toEqual([ - 'https://cloudflare-ipfs.com/ipns/app.ubeswap.org/', - 'https://ipfs.io/ipns/app.ubeswap.org/', - ]) - }) - it('returns empty array for invalid scheme', () => { - expect(uriToHttp('blah:test')).toEqual([]) - }) -}) diff --git a/yarn.lock b/yarn.lock index 30515918e94..e743471380f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3144,6 +3144,14 @@ dependencies: "@types/istanbul-lib-report" "*" +"@types/jest@^27.4.1": + version "27.4.1" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d" + integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw== + dependencies: + jest-matcher-utils "^27.0.0" + pretty-format "^27.0.0" + "@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" @@ -3188,6 +3196,11 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.179.tgz#490ec3288088c91295780237d2497a3aa9dfb5c5" integrity sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w== +"@types/luxon@^2.0.9": + version "2.0.9" + resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-2.0.9.tgz#782a0edfa6d699191292c13168bd496cd66b87c6" + integrity sha512-ZuzIc7aN+i2ZDMWIiSmMdubR9EMMSTdEzF6R+FckP4p6xdnOYKqknTo/k+xXQvciSXlNGIwA4OPU5X7JIFzYdA== + "@types/minimatch@*": version "3.0.5" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" @@ -4315,6 +4328,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + ansi-styles@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.1.0.tgz#87313c102b8118abd57371afab34618bf7350ed3" @@ -5007,18 +5025,8 @@ bip32@2.0.5: typeforce "^1.11.5" wif "^2.0.6" -"bip39@git+https://github.com/bitcoinjs/bip39.git#d8ea080a18b40f301d4e2219a2991cd2417e83c2": - version "3.0.3" - resolved "git+https://github.com/bitcoinjs/bip39.git#d8ea080a18b40f301d4e2219a2991cd2417e83c2" - dependencies: - "@types/node" "11.11.6" - create-hash "^1.1.0" - pbkdf2 "^3.0.9" - randombytes "^2.0.1" - "bip39@https://github.com/bitcoinjs/bip39#d8ea080a18b40f301d4e2219a2991cd2417e83c2": version "3.0.3" - uid d8ea080a18b40f301d4e2219a2991cd2417e83c2 resolved "https://github.com/bitcoinjs/bip39#d8ea080a18b40f301d4e2219a2991cd2417e83c2" dependencies: "@types/node" "11.11.6" @@ -5040,21 +5048,8 @@ blakejs@^1.1.0: resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== -"bls12377js@git+https://github.com/celo-org/bls12377js.git#cb38a4cfb643c778619d79b20ca3e5283a2122a6": - version "0.1.0" - resolved "git+https://github.com/celo-org/bls12377js.git#cb38a4cfb643c778619d79b20ca3e5283a2122a6" - dependencies: - "@stablelib/blake2xs" "0.10.4" - "@types/node" "^12.11.7" - big-integer "^1.6.44" - chai "^4.2.0" - mocha "^6.2.2" - ts-node "^8.4.1" - typescript "^3.6.4" - "bls12377js@https://github.com/celo-org/bls12377js#cb38a4cfb643c778619d79b20ca3e5283a2122a6": version "0.1.0" - uid cb38a4cfb643c778619d79b20ca3e5283a2122a6 resolved "https://github.com/celo-org/bls12377js#cb38a4cfb643c778619d79b20ca3e5283a2122a6" dependencies: "@stablelib/blake2xs" "0.10.4" @@ -6947,6 +6942,11 @@ diff-sequences@^26.6.2: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== +diff-sequences@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" + integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== + diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -10202,6 +10202,16 @@ jest-diff@^26.6.2: jest-get-type "^26.3.0" pretty-format "^26.6.2" +jest-diff@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" + integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + jest-docblock@^26.0.0: version "26.0.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" @@ -10250,6 +10260,11 @@ jest-get-type@^26.3.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== +jest-get-type@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" + integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== + jest-haste-map@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" @@ -10313,6 +10328,16 @@ jest-matcher-utils@^26.6.0, jest-matcher-utils@^26.6.2: jest-get-type "^26.3.0" pretty-format "^26.6.2" +jest-matcher-utils@^27.0.0: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" + integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== + dependencies: + chalk "^4.0.0" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + jest-message-util@^26.6.0, jest-message-util@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" @@ -13605,6 +13630,15 @@ pretty-format@^26.6.0, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" +pretty-format@^27.0.0, pretty-format@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + printj@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/printj/-/printj-1.3.1.tgz#9af6b1d55647a1587ac44f4c1654a4b95b8e12cb" From 5828a1a37c2a93c0a16bfdb33480a6147a7b6656 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 28 Feb 2022 18:50:13 -0500 Subject: [PATCH 47/72] stable pool card --- src/components/earn/StablePoolCard.tsx | 369 +++++++++++-------------- src/hooks/useStablePools.ts | 20 +- src/pages/Pool/index.tsx | 23 +- src/utils/calcRate.ts | 30 +- 4 files changed, 197 insertions(+), 245 deletions(-) diff --git a/src/components/earn/StablePoolCard.tsx b/src/components/earn/StablePoolCard.tsx index 3362a810d9b..9a2d8b5fbc5 100644 --- a/src/components/earn/StablePoolCard.tsx +++ b/src/components/earn/StablePoolCard.tsx @@ -1,19 +1,23 @@ -import Loader from 'components/Loader' import QuestionHelper from 'components/QuestionHelper' +import { ChainLogo, Coins } from 'constants/pools' import { useWeb3Context } from 'hooks' -import { useMobi } from 'hooks/Tokens' +import { useValueOfExternalRewards } from 'hooks/useStablePools' import JSBI from 'jsbi' -import { Fraction, Percent, Price, TokenAmount } from 'lib/token-utils' +import { calculateEstimatedWithdrawAmount, calculateVirtualPrice } from 'lib/calculator' +import { Fraction, TokenAmount } from 'lib/token-utils' +import { Meta } from 'pages/Pool' import { darken } from 'polished' import React, { useState } from 'react' import { isMobile } from 'react-device-detect' import { useHistory } from 'react-router' import { NavLink } from 'react-router-dom' +import { useMobiPrice, useTokenPrice } from 'state/application/hooks' +import { StakingInfo, UserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' +import { calcRates } from 'utils/calcRate' -import { BIG_INT_SECONDS_IN_WEEK, BIG_INT_SECONDS_IN_YEAR, CHAIN } from '../../constants' -import { useColor, usePoolColor } from '../../hooks/useColor' -import { useTokenPrices } from '../../state/application/hooks' +import { BIG_INT_SECONDS_IN_WEEK, BIG_INT_SECONDS_IN_YEAR } from '../../constants' +import { usePoolColor } from '../../hooks/useColor' import { theme, TYPE } from '../../theme' import { ButtonPrimary } from '../Button' import { AutoColumn } from '../Column' @@ -136,130 +140,109 @@ const StyledNavLink = styled(NavLink)<{ color: string }>` ` interface Props { - poolInfo: StablePoolInfo + meta: Meta + stakingInfo: StakingInfo + userStakingInfo: UserStakingInfo } -export const StablePoolCard: React.FC = ({ poolInfo }: Props) => { +export const StablePoolCard: React.FC = ({ meta, stakingInfo, userStakingInfo }: Props) => { const { connect, connected } = useWeb3Context() - const { - tokens, - peggedTo, - balances, - totalDeposited, - stakedAmount, - workingSupply, - pegComesAfter, - feesGenerated, - mobiRate, - displayDecimals, - totalStakedAmount: totalStakedLPs, - coin, - } = poolInfo + const history = useHistory() const [openDeposit, setOpenDeposit] = useState(false) const [openWithdraw, setOpenWithdraw] = useState(false) const [openManage, setOpenManage] = useState(false) - const tokenPrices = getCUSDPrices(useTokenPrices()) - const history = useHistory() - const mobi = useMobi() - const priceOfMobi = useCUSDPrice(mobi) ?? new Price(mobi, cUSD[CHAIN], '100', '1') - const userLP = poolInfo.amountDeposited - const { totalValueDeposited, valueOfDeposited } = getDepositValues(poolInfo, workingSupply) - const coinPrice = tokens.reduce( - (accum: Fraction | undefined, { address }) => accum ?? tokenPrices[address.toLowerCase()], - undefined - ) + const mobiPrice = useMobiPrice() - const totalStakedAmount = totalValueDeposited - ? totalValueDeposited.multiply(new Fraction(coinPrice?.numerator ?? '1', coinPrice?.denominator ?? '1')) - : new Fraction(JSBI.BigInt(0)) - const totalMobiRate = new TokenAmount(mobi, mobiRate ?? JSBI.BigInt('0')) - - const rewardPerYear = priceOfMobi.raw.multiply(totalMobiRate.multiply(BIG_INT_SECONDS_IN_YEAR)) - let rewardPerYearExternal = new Fraction('0', '1') - for (let i = 0; i < 8; i++) { - const rate = poolInfo.externalRewardRates?.[i] ?? totalMobiRate - const priceOfToken = - tokenPrices[rate.token.address.toLowerCase()] ?? tokenPrices['0x00be915b9dcf56a3cbe739d9b9c202ca692409ec'] - if (poolInfo.externalRewardRates && i < poolInfo.externalRewardRates.length) { - rewardPerYearExternal = rewardPerYearExternal.add( - priceOfToken?.multiply(rate.multiply(BIG_INT_SECONDS_IN_YEAR)) ?? '0' - ) - } - } - const [apyFraction, apy, dpy] = - mobiRate && totalStakedAmount && !totalStakedAmount.equalTo(JSBI.BigInt(0)) - ? calcApy(rewardPerYear.add(rewardPerYearExternal), totalStakedAmount) - : [undefined, undefined, undefined] - - const [boostedApyFraction, boostedApy, boostedDpy] = - mobiRate && totalStakedAmount && !totalStakedAmount.equalTo(JSBI.BigInt(0)) - ? calcApy( - rewardPerYear.multiply(new Fraction(JSBI.BigInt(5), JSBI.BigInt(2))).add(rewardPerYearExternal), - totalStakedAmount - ) - : [new Fraction('0', '1'), new Fraction('0', '1'), new Fraction('0', '1')] - - let weeklyAPY: React.ReactNode | undefined = <>🤯 - try { - weeklyAPY = apy - ? new Percent( - Math.floor(parseFloat(apy.divide('52').add('1').toFixed(10)) ** 52 * 1_000_000 - 1_000_000).toFixed(0), - '1000000' - ).toFixed(0, { groupSeparator: ',' }) - : undefined - } catch (e) { - console.error('Weekly apy overflow', e) - } - let userBalances: TokenAmount[] = [] - if (totalDeposited.greaterThan('0')) { - userBalances = balances.map((amount) => { - const fraction = new Fraction(userLP ? userLP.raw : JSBI.BigInt(0), totalDeposited.raw) - const ratio = fraction.multiply(amount.raw) - return new TokenAmount(amount.currency, JSBI.divide(ratio.numerator, ratio.denominator)) - }) - } - // get the color of the token - const backgroundColorStart = useColor(tokens[0]) - let backgroundColorEnd = useColor(tokens[tokens.length - 1]) - const poolColor = usePoolColor(poolInfo) - const backgroundGradient = null //generateGradient(tokens.slice()) + const virtualPrice = calculateVirtualPrice(meta.exchangeInfo) + + const totalDeposited = + virtualPrice?.multiply(meta.exchangeInfo.lpTotalSupply) ?? new TokenAmount(meta.display.pool.lpToken, 0) + + const userDeposited = + virtualPrice?.multiply(meta.lpBalance.asFraction.add(meta.userGauge?.balance ?? JSBI.BigInt(0))) ?? + new TokenAmount(meta.display.pool.lpToken, 0) - if (!backgroundColorEnd || backgroundColorEnd === backgroundColorStart) backgroundColorEnd = '#212429' + const pegPrice = useTokenPrice(meta.display.peg.priceQuery ?? undefined) - // get the USD value of staked WETH - // const apyFraction = poolInfo.apr || undefined - // const apy = apyFraction ? new Percent(apyFraction.numerator, apyFraction.denominator) : undefined - const isStaking = valueOfDeposited.greaterThan(JSBI.BigInt('0')) || poolInfo.stakedAmount.greaterThan('0') + const totalDepositedValue = pegPrice ? totalDeposited.multiply(pegPrice) : new Fraction(0) - const formatNumber = (num: string) => { - return num.replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,') + const mobiRate = meta.gauge?.weight.multiply(stakingInfo.mobiRate).asFraction ?? new Fraction(0) + const mobiRateValue = mobiPrice.multiply(mobiRate).multiply(BIG_INT_SECONDS_IN_YEAR) + + // const totalStakedAmount = totalValueDeposited + // ? totalValueDeposited.multiply(new Fraction(coinPrice?.numerator ?? '1', coinPrice?.denominator ?? '1')) + // : new Fraction(JSBI.BigInt(0)) + // const totalMobiRate = new TokenAmount(mobi, mobiRate ?? JSBI.BigInt('0')) + + // const rewardPerYear = priceOfMobi.raw.multiply(totalMobiRate.multiply(BIG_INT_SECONDS_IN_YEAR)) + const externalRewardValue = useValueOfExternalRewards(meta.display.gauge).multiply(BIG_INT_SECONDS_IN_YEAR) + // let rewardPerYearExternal = new Fraction('0', '1') + // for (let i = 0; i < 8; i++) { + // const rate = poolInfo.externalRewardRates?.[i] ?? totalMobiRate + // const priceOfToken = + // tokenPrices[rate.token.address.toLowerCase()] ?? tokenPrices['0x00be915b9dcf56a3cbe739d9b9c202ca692409ec'] + // if (poolInfo.externalRewardRates && i < poolInfo.externalRewardRates.length) { + // rewardPerYearExternal = rewardPerYearExternal.add( + // priceOfToken?.multiply(rate.multiply(BIG_INT_SECONDS_IN_YEAR)) ?? '0' + // ) + // } + // } + + // TODO: investigate if this is the right method + const { apr, dpr, apy } = calcRates(mobiRateValue.add(externalRewardValue), totalDepositedValue) + const { apr: boostedApr } = calcRates(mobiRateValue.add(externalRewardValue), totalDepositedValue) + + // const [boostedApyFraction, boostedApy, boostedDpy] = + // mobiRate && totalStakedAmount && !totalStakedAmount.equalTo(JSBI.BigInt(0)) + // ? calcApy( + // rewardPerYear.multiply(new Fraction(JSBI.BigInt(5), JSBI.BigInt(2))).add(rewardPerYearExternal), + // totalStakedAmount + // ) + // : [new Fraction('0', '1'), new Fraction('0', '1'), new Fraction('0', '1')] + + // let weeklyAPY: React.ReactNode | undefined = <>🤯 + // try { + // weeklyAPY = apy + // ? new Percent( + // Math.floor(parseFloat(apy.divide('52').add('1').toFixed(10)) ** 52 * 1_000_000 - 1_000_000).toFixed(0), + // '1000000' + // ).toFixed(0, { groupSeparator: ',' }) + // : undefined + // } catch (e) { + // console.error('Weekly apy overflow', e) + // } + const balances = calculateEstimatedWithdrawAmount({ poolTokenAmount: meta.lpBalance, ...meta.exchangeInfo }) + const userBalances = calculateEstimatedWithdrawAmount({ + poolTokenAmount: meta.exchangeInfo.lpTotalSupply, + ...meta.exchangeInfo, + }) + // let userBalances: TokenAmount[] = [] + // if (totalDeposited.greaterThan('0')) { + // userBalances = balances.map((amount) => { + // const fraction = new Fraction(userLP ? userLP.raw : JSBI.BigInt(0), totalDeposited.raw) + // const ratio = fraction.multiply(amount.raw) + // return new TokenAmount(amount.currency, JSBI.divide(ratio.numerator, ratio.denominator)) + // }) + // } + + const poolColor = usePoolColor(meta.display) + + const display = (str: string): string => { + const peg = meta.display.peg + return (peg.position === 'before' ? peg.symbol : '').concat(str).concat(peg.position === 'after' ? peg.symbol : '') } - const totalDisplay = (amount: TokenAmount): string => { - if (coin === Coins.Bitcoin || coin === Coins.Ether) { - if (JSBI.lessThan(amount.raw, JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(19))) || openManage) { - return amount.toFixed(2) - } else return amount.toFixed(0) - } else { - if (JSBI.lessThan(amount.raw, JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(23))) || openManage) { - return formatNumber(amount.toFixed(0)) - } else { - const collapsed = JSBI.divide(amount.raw, JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(23))).toString() - return formatNumber(String((Number(collapsed) / 10).toFixed(1))).concat('M') - } - } + const totalDisplay = (amount: TokenAmount | Fraction): string => { + const decimals = meta.display.peg.decimals + if (amount.lessThan(10 ** (2 - decimals))) return display(amount.toFixed(decimals + 1)) + else if (amount.lessThan(10 ** 6)) return display(amount.toFixed(decimals)) + else return display(amount.divide(10 ** 6).toFixed(2)) } return ( - setOpenManage(!openManage)} - > + setOpenManage(!openManage)}> {openDeposit && setOpenDeposit(false)} poolInfo={poolInfo} />} {openWithdraw && ( setOpenWithdraw(false)} poolInfo={poolInfo} /> @@ -267,70 +250,45 @@ export const StablePoolCard: React.FC = ({ poolInfo }: Props) => { - {poolInfo.name} + {meta.display.name} - + + + + + Yield/day: {dpr?.toSignificant(4)}%
+ APY (daily compounded): {apy.toSignificant(4)}% + + } + /> + + {apr.denominator.toString() !== '0' ? `${apr.toFixed(1, { groupSeparator: ',' })}%` : ' -'} APR +
- {apy ? ( - - - Yield/day: {dpy?.toSignificant(4)}%
- APY (weekly compounded): {weeklyAPY}% - - } - /> - - {apy.denominator.toString() !== '0' ? `${apy.toFixed(1, { groupSeparator: ',' })}%` : ' -'} APR - -
- ) : ( - - - APY Loading - - )}
- + - {tokens.map((t) => t.symbol).join(' / ')} + {meta.display.pool.tokens.map((t) => t.symbol).join(' / ')} - {poolInfo.meta && ( - - A meta pool pairs one token with the LP token of another pool to build on already-existing liquidity.{' '} -
-
- This meta pool builds off of {poolInfo.meta} - - } - /> - )}
- {apy && boostedApy ? ( - - - up to {apy.denominator.toString() !== '0' ? `${boostedApy.toFixed(1, { groupSeparator: ',' })}%` : ' -'}{' '} - w/ boost - - - ) : null} + + + + up to {apy.denominator.toString() !== '0' ? `${boostedApr.toFixed(1, { groupSeparator: ',' })}%` : ' -'} w/ + boost + +
@@ -340,20 +298,16 @@ export const StablePoolCard: React.FC = ({ poolInfo }: Props) => { Total deposited - `${balance?.toFixed(displayDecimals, { groupSeparator: ',' })} ${balance.token.symbol}` + `${balance?.toFixed(meta.display.peg.decimals, { groupSeparator: ',' })} ${ + balance.token.symbol + }` ) .join(', ')} /> - - {totalValueDeposited - ? `${!pegComesAfter ? peggedTo : ''}${totalDisplay(totalValueDeposited)} ${ - pegComesAfter ? peggedTo : '' - }` - : '-'} - + {totalDisplay(totalDeposited)} @@ -361,11 +315,7 @@ export const StablePoolCard: React.FC = ({ poolInfo }: Props) => { Weekly volume - {poolInfo.weeklyVolume - ? `${!pegComesAfter ? peggedTo : ''}${totalDisplay(poolInfo.weeklyVolume)} ${ - pegComesAfter ? peggedTo : '' - }` - : 'Subgraph Syncing...'} + {meta.volume.volume ? totalDisplay(new Fraction(meta.volume.volume?.week)) : 'Subgraph Syncing...'} @@ -376,10 +326,8 @@ export const StablePoolCard: React.FC = ({ poolInfo }: Props) => { Total volume - {poolInfo.totalVolume - ? `${!pegComesAfter ? peggedTo : ''}${totalDisplay(poolInfo.totalVolume)} ${ - pegComesAfter ? peggedTo : '' - }` + {meta.volume.volume + ? totalDisplay(new Fraction(meta.volume.volume?.total)) : 'Subgraph Syncing...'} @@ -389,30 +337,26 @@ export const StablePoolCard: React.FC = ({ poolInfo }: Props) => { MOBI rate - {totalMobiRate - ? totalMobiRate?.multiply(BIG_INT_SECONDS_IN_WEEK)?.toFixed(0, { groupSeparator: ',' }) ?? '-' - : '0'} + {mobiRate.multiply(BIG_INT_SECONDS_IN_WEEK)?.toFixed(0, { groupSeparator: ',' })} {' / week'} )} - {poolInfo.externalRewardRates && - poolInfo.externalRewardRates.map((rate) => ( + {meta.display.gauge?.additionalRewards.length !== 0 && + meta.display.gauge?.additionalRewards.map((rate) => ( {rate.token.symbol?.toUpperCase()} rate - {rate - ? rate?.multiply(BIG_INT_SECONDS_IN_WEEK)?.toSignificant(4, { groupSeparator: ',' }) ?? '-' - : '0'} + {rate.multiply(BIG_INT_SECONDS_IN_WEEK)?.toSignificant(4, { groupSeparator: ',' })} {` / week`} ))} - {connected && isStaking && ( + {connected && userDeposited.greaterThan(0) && ( Your share @@ -427,11 +371,7 @@ export const StablePoolCard: React.FC = ({ poolInfo }: Props) => { ) .join(', ')} /> */} - - {!pegComesAfter && peggedTo} - {valueOfDeposited.toFixed(displayDecimals + 2)} - {pegComesAfter && ` ${peggedTo}`} - + {totalDisplay(userDeposited)} )} @@ -442,8 +382,12 @@ export const StablePoolCard: React.FC = ({ poolInfo }: Props) => { (isStaking ? setOpenManage(true) : setOpenDeposit(true)) : connect} - eth={coin === Coins.Ether} + onClick={ + connected + ? () => (userDeposited.greaterThan(0) ? setOpenManage(true) : setOpenDeposit(true)) + : connect + } + eth={meta.display.peg.coin === Coins.Ether} style={{ width: '10%', fontWeight: 700, @@ -452,25 +396,25 @@ export const StablePoolCard: React.FC = ({ poolInfo }: Props) => { marginTop: '-20px', }} > - {isStaking ? 'MANAGE' : 'DEPOSIT'} + {userDeposited.greaterThan(0) ? 'MANAGE' : 'DEPOSIT'} )}
- {!isStaking && (openManage || isMobile) && ( + {!userDeposited.greaterThan(0) && (openManage || isMobile) && ( setOpenDeposit(true) : connect} - eth={coin === Coins.Ether} + eth={meta.display.peg.coin === Coins.Ether} style={{ fontWeight: 700, fontSize: 18 }} > DEPOSIT )} - {connected && isStaking && (openManage || isMobile) && ( + {connected && userDeposited.greaterThan(0) && (openManage || isMobile) && (
= ({ poolInfo }: Props) => { gap: isMobile ? '0.25rem' : '1rem', flexWrap: 'wrap', padding: isMobile ? 0 : '1rem', - paddingBottom: isMobile && '0', + paddingBottom: '0', marginLeft: 'auto', marginRight: 'auto', }} @@ -489,6 +433,7 @@ export const StablePoolCard: React.FC = ({ poolInfo }: Props) => { backgroundHover={theme(false).celoGreen} onClick={() => setOpenDeposit(true)} style={{ fontWeight: 700, fontSize: isMobile ? 15 : 18 }} + eth={false} > DEPOSIT @@ -497,15 +442,17 @@ export const StablePoolCard: React.FC = ({ poolInfo }: Props) => { backgroundHover={theme(false).celoRed} onClick={() => setOpenWithdraw(true)} style={{ fontWeight: 700, fontSize: isMobile ? 15 : 18 }} + eth={false} > WITHDRAW - {poolInfo.gaugeAddress !== undefined && ( + {meta.display.gauge !== null && ( history.push(`/farm/${poolInfo.poolAddress}`)} + onClick={() => history.push(`/farm/${meta.display.gauge?.address}`)} + eth={false} > FARM diff --git a/src/hooks/useStablePools.ts b/src/hooks/useStablePools.ts index 264956d4984..c8d306d9976 100644 --- a/src/hooks/useStablePools.ts +++ b/src/hooks/useStablePools.ts @@ -1,5 +1,5 @@ import { invariant } from '@apollo/client/utilities/globals' -import { IExchangeInfo, StablePools } from 'constants/pools' +import { IExchangeInfo, IGauge, StablePools } from 'constants/pools' import JSBI from 'jsbi' import { calculateVirtualPrice } from 'lib/calculator' import { Fraction, TokenAmount } from 'lib/token-utils' @@ -28,8 +28,8 @@ export function useValueOfAllPools(): Fraction { const prices = useTokenPrices() const pools = usePools() return StablePools[CHAIN].reduce((acc, cur, i) => { - const price = cur.peg.priceQuery ? priceStringToFraction(prices[cur.peg.priceQuery]) : new Fraction(1) - invariant(price, 'price') + const price = cur.peg.priceQuery ? priceStringToFraction(prices[cur.peg.priceQuery]) : new Fraction(0) + if (!price) return acc const virtualPrice = calculateVirtualPrice(pools[i]) return virtualPrice ? acc.add(price.multiply(virtualPrice).multiply(pools[i].lpTotalSupply)) : acc @@ -41,10 +41,20 @@ export function useValueOfAllLP(amounts: JSBI[]): Fraction { const pools = usePools() invariant(amounts.length === pools.length, 'invalid amounts entry') return StablePools[CHAIN].reduce((acc, cur, i) => { - const price = cur.peg.priceQuery ? priceStringToFraction(prices[cur.peg.priceQuery]) : new Fraction(1) - invariant(price, 'price') + const price = cur.peg.priceQuery ? priceStringToFraction(prices[cur.peg.priceQuery]) : new Fraction(0) + if (!price) return acc const virtualPrice = calculateVirtualPrice(pools[i]) return virtualPrice ? acc.add(price.multiply(virtualPrice).multiply(amounts[i])) : acc }, new Fraction(0)) } + +export function useValueOfExternalRewards(gauge: IGauge | null): Fraction { + const prices = useTokenPrices() + if (!gauge) return new Fraction(0) + return gauge.additionalRewards.reduce((acc, cur) => { + const price = priceStringToFraction(prices[cur.token.address.toLowerCase()]) ?? new Fraction(0) + if (!price) return acc + return acc.add(price.multiply(cur)) + }, new Fraction(0)) +} diff --git a/src/pages/Pool/index.tsx b/src/pages/Pool/index.tsx index 76d3abbac56..f8dd4dbf166 100644 --- a/src/pages/Pool/index.tsx +++ b/src/pages/Pool/index.tsx @@ -1,6 +1,6 @@ import QuestionHelper from 'components/QuestionHelper' import { RowFixed } from 'components/Row' -import { Chain, DisplayPool, IExchangeInfo, StablePools } from 'constants/pools' +import { Chain, DisplayPool, IExchangeInfo, StablePools, Volume } from 'constants/pools' import { useValueOfAllPools } from 'hooks/useStablePools' import JSBI from 'jsbi' import { TokenAmount } from 'lib/token-utils' @@ -8,7 +8,7 @@ import React from 'react' import { isMobile } from 'react-device-detect' import { useMobiPrice } from 'state/application/hooks' import { GaugeInfo, useAllGaugesInfo, useAllUserGaugesInfo, UserGaugeInfo } from 'state/gauges/hooks' -import { useAllLpBalances, usePools } from 'state/mobiusPools/hooks' +import { useAllLpBalances, usePools, usePoolsVolume } from 'state/mobiusPools/hooks' import { useStakingInfo, useUserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' @@ -68,6 +68,15 @@ type SelectChain = SpecialChain | Chain const OtherChains = new Set([Chain.Avax, Chain.Polygon, Chain.Celo]) +export type Meta = { + display: DisplayPool + userGauge: UserGaugeInfo | null + gauge: GaugeInfo | null + lpBalance: TokenAmount + exchangeInfo: IExchangeInfo + volume: Volume +} + export default function Pool() { const userGauges = useAllUserGaugesInfo() const gauges = useAllGaugesInfo() @@ -75,14 +84,7 @@ export default function Pool() { const userStakingInfo = useUserStakingInfo() const exchanges = usePools() const lpBalances = useAllLpBalances() - - type Meta = { - display: DisplayPool - userGauge: UserGaugeInfo | null - gauge: GaugeInfo | null - lpBalance: TokenAmount - exchangeInfo: IExchangeInfo - } + const volumes = usePoolsVolume() const meta: Meta[] = StablePools[CHAIN].map((el, i) => { return { @@ -91,6 +93,7 @@ export default function Pool() { gauge: gauges[i], lpBalance: lpBalances[i], exchangeInfo: exchanges[i], + volume: volumes[i], } }) diff --git a/src/utils/calcRate.ts b/src/utils/calcRate.ts index 71d900163f3..a3884850300 100644 --- a/src/utils/calcRate.ts +++ b/src/utils/calcRate.ts @@ -1,25 +1,17 @@ import JSBI from 'jsbi' -import { Fraction, Percent } from 'lib/token-utils' +import { Fraction } from 'lib/token-utils' + +import { weiScale } from '../constants' type Rates = { - apyF: Fraction - apy: Percent - dyp: Percent + apr: Fraction + dpr: Fraction + apy: Fraction } -export function calcApy(rewardPerYear: Fraction, totalStakedAmount: Fraction): Rates { - const apyFraction = rewardPerYear - .multiply(JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18'))) - .divide(totalStakedAmount) - const apy = apyFraction - ? new Percent( - apyFraction.numerator, - JSBI.multiply(apyFraction.denominator, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18'))) - ) - : undefined - const dpy = - apy && !apy.equalTo('0') - ? new Percent(Math.floor(parseFloat(apy.divide('365').toFixed(10)) * 1_000_000).toFixed(0), '1000000') - : undefined - return { apyFraction, apy, dpy } +export function calcRates(rewardPerYear: Fraction, totalStakedAmount: Fraction): Rates { + const apr = !totalStakedAmount.equalTo(0) ? rewardPerYear.divide(totalStakedAmount) : new Fraction(0) + const dpr = apr.divide(365) + const apy = new Fraction(JSBI.exponentiate(dpr.add(1).multiply(weiScale).quotient, JSBI.BigInt(364)), weiScale) + return { apr, dpr, apy } } From 10efe8cd158c72905325ceafa7f7b5371cf464fe Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 28 Feb 2022 19:39:49 -0500 Subject: [PATCH 48/72] deposit modal --- src/components/earn/DepositModal.tsx | 213 ++++++++++++--------------- src/constants/pools.ts | 2 +- src/hooks/useWarning.ts | 12 ++ 3 files changed, 110 insertions(+), 117 deletions(-) create mode 100644 src/hooks/useWarning.ts diff --git a/src/components/earn/DepositModal.tsx b/src/components/earn/DepositModal.tsx index 9ba88194c9e..812e5fd174a 100644 --- a/src/components/earn/DepositModal.tsx +++ b/src/components/earn/DepositModal.tsx @@ -1,12 +1,13 @@ import { TransactionResponse } from '@ethersproject/providers' import CurrencyLogo from 'components/CurrencyLogo' -import JSBI from 'jsbi' -import { TokenAmount } from 'lib/token-utils' -import React, { useState } from 'react' -import { tryParseAmount } from 'state/swap/hooks' +import { useWarning } from 'hooks/useWarning' +import { calculateEstimatedMintAmount, calculateVirtualPrice } from 'lib/calculator' +import { Fraction, TokenAmount } from 'lib/token-utils' +import { Meta } from 'pages/Pool' +import React, { useMemo, useState } from 'react' +import { StakingInfo, UserStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' -import { weiScale } from '../../constants' import { useWeb3Context } from '../../hooks' import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback' import { useStableSwapContract } from '../../hooks/useContract' @@ -36,62 +37,69 @@ const ApprovalButton = styled(ButtonPrimary)` interface DepositModalProps { isOpen: boolean onDismiss: () => void - poolInfo: StablePoolInfo + meta: Meta + stakingInfo: StakingInfo + userStakingInfo: UserStakingInfo } -export default function DepositModal({ isOpen, onDismiss, poolInfo }: DepositModalProps) { - const { address, connected } = useWeb3Context() +export default function DepositModal({ isOpen, onDismiss, meta }: DepositModalProps) { + const { connected } = useWeb3Context() + const warning = useWarning(meta.display.warningType) // monitor call to help UI loading state const addTransaction = useTransactionAdder() - const { tokens, peggedTo, pegComesAfter, totalDeposited } = poolInfo - const warning = useWarning(poolInfo.poolAddress ?? undefined) const [hash, setHash] = useState() const [attempting, setAttempting] = useState(false) const [approving, setApproving] = useState(false) - const [input, setInput] = useState<(string | undefined)[]>(new Array(tokens.length).fill(undefined)) + const [input, setInput] = useState(new Array(meta.display.pool.tokens.length).fill('')) const [warningAcknowledged, setWarningAcknowledged] = useState(!warning) - const isFirstDeposit = totalDeposited.equalTo('0') + + const isFirstDeposit = meta.exchangeInfo.lpTotalSupply.equalTo(0) const forceEqualDeposit = isFirstDeposit || warning?.modification === 'require-equal-deposit' const [useEqualAmount, setUseEqualAmount] = useState(forceEqualDeposit) const deadline = useTransactionDeadline() - const sumAmount = tokens - .map((t, i) => - JSBI.multiply( - tryParseAmount(input[i], t)?.raw ?? JSBI.BigInt(0), - JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(18 - t.decimals)) - ) + // TODO: i think we need to parse the amount + const inputTokens = useMemo(() => { + return input.map((el, i) => + el ? new TokenAmount(meta.display.pool.tokens[i], el) : new TokenAmount(meta.display.pool.tokens[i], 0) ) - .reduce((acc, cur) => JSBI.add(acc, cur), JSBI.BigInt(0)) + }, [input, meta.display.pool.tokens]) - const [expectedLPTokens, selectedAmounts] = useExpectedLpTokens(poolInfo, tokens, input) - const valueOfLP = new TokenAmount( - poolInfo.lpToken, - JSBI.divide( - JSBI.multiply(expectedLPTokens.raw, poolInfo.virtualPrice), - JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) - ) - ) + const sumAmount = inputTokens.reduce((acc, cur) => acc.add(cur), new Fraction(0)) + + const expectedAmounts = calculateEstimatedMintAmount(meta.exchangeInfo, inputTokens[0].raw, inputTokens[1].raw) - const diff = JSBI.greaterThan(valueOfLP.raw, sumAmount) - ? JSBI.subtract(valueOfLP.raw, sumAmount) - : JSBI.subtract(sumAmount, valueOfLP.raw) + const virtualPrice = calculateVirtualPrice(meta.exchangeInfo) + const adjustedExpectedAmount = expectedAmounts.mintAmount.multiply(virtualPrice ?? 1) + // const valueOfLP = new TokenAmount( + // poolInfo.lpToken, + // JSBI.divide( + // JSBI.multiply(expectedLPTokens.raw, poolInfo.virtualPrice), + // JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) + // ) + // ) - const perDiff = JSBI.equal(sumAmount, JSBI.BigInt(0)) - ? JSBI.BigInt(0) - : JSBI.divide(JSBI.multiply(diff, weiScale), sumAmount) + const diff = sumAmount.greaterThan(adjustedExpectedAmount) + ? sumAmount.subtract(adjustedExpectedAmount) + : adjustedExpectedAmount.subtract(sumAmount) - const decimalPlacesForLP = expectedLPTokens?.greaterThan('1') ? 2 : expectedLPTokens?.greaterThan('0') ? 10 : 2 + const perDiff = sumAmount.equalTo(0) ? new Fraction(0) : diff.divide(sumAmount) - const withSlippage = JSBI.subtract(expectedLPTokens.raw, JSBI.divide(expectedLPTokens.raw, JSBI.BigInt('10'))) + const decimalPlacesForLP = expectedAmounts.mintAmount.greaterThan(1) + ? 2 + : expectedAmounts.mintAmount.greaterThan(0) + ? 10 + : 2 + + const expectAmountWithSlippage = expectedAmounts.mintAmount.multiply(0.9) const approvals = [ - useApproveCallback(selectedAmounts[0], poolInfo.poolAddress), - useApproveCallback(selectedAmounts[1], poolInfo.poolAddress), + useApproveCallback(inputTokens[0], meta.display.pool.address), + useApproveCallback(inputTokens[1], meta.display.pool.address), ] const toApprove = approvals - .map(([approvalState], i) => { - if (approvalState !== ApprovalState.APPROVED) return i - else return null + .map(([approvalState]) => { + if (approvalState !== ApprovalState.APPROVED) return true + else return false }) .filter((x) => x !== null) function wrappedOndismiss() { @@ -100,17 +108,16 @@ export default function DepositModal({ isOpen, onDismiss, poolInfo }: DepositMod onDismiss() } - const stakingContract = useStableSwapContract(poolInfo.poolAddress) + const stakingContract = useStableSwapContract(meta.display.pool.address) async function onDeposit() { - const allValid = selectedAmounts.reduce((accum, cur) => accum && !!cur && !!cur.raw, true) - if (stakingContract && poolInfo?.stakedAmount && allValid) { + if (stakingContract && deadline) { setAttempting(true) - const tokenAmounts = selectedAmounts.map((amount) => BigInt(amount.raw.toString())) + const tokenAmounts = inputTokens.map((el) => el.raw.toString()) await stakingContract - .addLiquidity(tokenAmounts, withSlippage.toString(), deadline, { gasLimit: 10000000 }) + .addLiquidity(tokenAmounts, expectAmountWithSlippage.toString(), deadline, { gasLimit: 10000000 }) .then((response: TransactionResponse) => { addTransaction(response, { - summary: `Deposit Liquidity into ${poolInfo.name}`, + summary: `Deposit Liquidity into ${meta.display.name}`, }) setHash(response.hash) }) @@ -125,8 +132,14 @@ export default function DepositModal({ isOpen, onDismiss, poolInfo }: DepositMod if (!connected) { error = 'Connect Wallet' } - if (!poolInfo?.stakedAmount) { - error = error ?? 'Enter an amount' + // TODO: try this + // if (!poolInfo?.stakedAmount) { + // error = error ?? 'Enter an amount' + // } + + const display = (str: string): string => { + const peg = meta.display.peg + return (peg.position === 'before' ? peg.symbol : '').concat(str).concat(peg.position === 'after' ? peg.symbol : '') } return ( @@ -146,7 +159,7 @@ export default function DepositModal({ isOpen, onDismiss, poolInfo }: DepositMod ) : ( <> - Deposit to {poolInfo.name} + Deposit to {meta.display.name} {forceEqualDeposit && ( @@ -169,21 +182,21 @@ export default function DepositModal({ isOpen, onDismiss, poolInfo }: DepositMod toggle={() => !forceEqualDeposit && setUseEqualAmount(!useEqualAmount)} /> - {poolInfo.tokens.map((token, i) => ( -
+ {meta.display.pool.tokens.map((token, i) => ( +
{ if (useEqualAmount) { - setInput(new Array(tokens.length).fill(val)) + setInput(new Array(meta.display.pool.tokens.length).fill(val)) } else { setInput([...input.slice(0, i), val, ...input.slice(i + 1)]) } }} // setUsingInsufficientFunds={setInsufficientFunds} /> - {i !== selectedAmounts.length - 1 && ( + {i !== inputTokens.length - 1 && ( + @@ -191,41 +204,44 @@ export default function DepositModal({ isOpen, onDismiss, poolInfo }: DepositMod
))} - Expected Lp Tokens Received: {expectedLPTokens.toFixed(decimalPlacesForLP)} + Expected Lp Tokens Received: {expectedAmounts.mintAmount.toFixed(decimalPlacesForLP)} {!isFirstDeposit && ( - Equivalent to: {pegComesAfter ? '' : peggedTo} - {valueOfLP.toFixed(4)} {pegComesAfter ? poolInfo.peggedTo : ''} + Equivalent to: {display(adjustedExpectedAmount.toFixed(4))} )} - {toApprove.length > 0 && expectedLPTokens.greaterThan('0') && ( + {toApprove.length > 0 && expectedAmounts.mintAmount.greaterThan('0') && (
- {toApprove.map((i) => ( - { - setApproving(true) - await approvals[i][1]() - await new Promise((resolve) => setTimeout(resolve, 20000)) - setApproving(false) - }} - > - Approve {tokens[i].symbol} - - ))} + {toApprove.map( + (el, i) => + el && ( + { + setApproving(true) + await approvals[i][1]() + // TODO: see if we can remove this time + await new Promise((resolve) => setTimeout(resolve, 20000)) + setApproving(false) + }} + > + Approve {meta.display.pool.tokens[i].symbol} + + ) + )}
)} {toApprove.length === 0 && ( - + {error ?? 'Deposit'} )} @@ -237,7 +253,7 @@ export default function DepositModal({ isOpen, onDismiss, poolInfo }: DepositMod Depositing - Claiming {expectedLPTokens.toSignificant(4)} LP Tokens + Claiming {expectedAmounts.mintAmount.toSignificant(4)} LP Tokens )} @@ -257,18 +273,13 @@ type CurrencyRowProps = { tokenAmount: TokenAmount setInput: (amount: string) => void input: string - setUsingInsufficientFunds: (isInsufficient: boolean) => void } -const InputRowLeft = styled.div`` - -const TokenInfo = styled.div`` - -const InputRow = styled.div<{ selected: boolean }>` +const InputRow = styled.div` ${({ theme }) => theme.flexRowNoWrap}; align-items: center; justify-content: space-between; - padding: ${({ selected }) => (selected ? '0.75rem 0.5rem 0.75rem 1rem' : '0.75rem 0.75rem 0.75rem 1rem')}; + padding: 0.75rem 0.75rem 0.75rem 1rem; ` const InputDiv = styled.div` @@ -282,22 +293,6 @@ const Aligner = styled.span` justify-content: space-between; ` -const InputPanel = styled.div<{ hideInput?: boolean }>` - ${({ theme }) => theme.flexColumnNoWrap} - position: relative; - border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')}; - background-color: ${({ theme }) => theme.bg1}; - z-index: 1; - width: 100%; -` - -const Container = styled.div<{ hideInput: boolean }>` - border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')}; - border: 1px solid ${({ theme }) => theme.bg2}; - background-color: ${({ theme }) => theme.bg1}; - padding: 0.5rem; -` - const StyledTokenName = styled.span<{ active?: boolean }>` ${({ active }) => (active ? ' margin: 0 0.25rem 0 0.75rem;' : ' margin: 0 0.25rem 0 0.25rem;')} font-size: ${({ active }) => (active ? '20px' : '16px')}; @@ -307,15 +302,10 @@ const BalanceText = styled(TYPE.subHeader)` cursor: pointer; ` -const CurrencyRow = ({ tokenAmount, setInput, input, setUsingInsufficientFunds }: CurrencyRowProps) => { +const CurrencyRow = ({ tokenAmount, setInput, input }: CurrencyRowProps) => { const { address, connected } = useWeb3Context() - const currency = tokenAmount.currency + const currency = tokenAmount.token const tokenBalance = useTokenBalance(connected ? address : undefined, currency ?? undefined) - const TEN = JSBI.BigInt('10') - const ZERO_TOK = new TokenAmount(currency, JSBI.BigInt('0')) - - const scaledDown = (num: JSBI) => JSBI.divide(num, JSBI.exponentiate(TEN, JSBI.BigInt(currency.decimals))) - const scaleUp = (num: JSBI) => JSBI.multiply(num, JSBI.exponentiate(TEN, JSBI.BigInt(currency.decimals))) const decimalPlacesForBalance = tokenBalance?.greaterThan( '1' //JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt(tokenBalance.token.decimals - 2)).toString() @@ -341,7 +331,6 @@ const CurrencyRow = ({ tokenAmount, setInput, input, setUsingInsufficientFunds }
{ @@ -366,11 +355,3 @@ const CurrencyRow = ({ tokenAmount, setInput, input, setUsingInsufficientFunds }
) } - -const insertDecimal = (tokenAmount: TokenAmount) => { - const { token } = tokenAmount - const amount = tokenAmount.divide( - new TokenAmount(token, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt(token.decimals))) - ) - return amount.toFixed(2) -} diff --git a/src/constants/pools.ts b/src/constants/pools.ts index 7b9ba22167b..d2cfddf65bd 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -55,7 +55,7 @@ export enum Coins { Eur, } -enum WarningType { +export enum WarningType { POOF = 'poof', } diff --git a/src/hooks/useWarning.ts b/src/hooks/useWarning.ts new file mode 100644 index 00000000000..aa4e05f5b57 --- /dev/null +++ b/src/hooks/useWarning.ts @@ -0,0 +1,12 @@ +import { WarningType } from 'constants/pools' + +import WARNINGS from '../constants/PoolWarnings.json' + +export type WarningModifications = 'require-equal-deposit' | 'none' + +export function useWarning( + warning: WarningType | undefined +): { warning: string; link?: string; modification?: WarningModifications } | undefined { + if (!warning) return undefined + return WARNINGS[warning] as any as { warning: string; link?: string; modification?: WarningModifications } +} From d4025cef64d09fd85c4f62d9bdd027a701644f48 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 28 Feb 2022 20:05:08 -0500 Subject: [PATCH 49/72] withdraw modal --- src/components/earn/ClaimRewardModal.tsx | 1 - src/components/earn/DepositModal.tsx | 9 +- src/components/earn/UnstakingModal.tsx | 1 - src/components/earn/WithdrawLP.tsx | 91 ++--- src/components/earn/WithdrawModal.tsx | 27 +- src/components/earn/WithdrawTokens.tsx | 415 ++++++++++++----------- 6 files changed, 250 insertions(+), 294 deletions(-) diff --git a/src/components/earn/ClaimRewardModal.tsx b/src/components/earn/ClaimRewardModal.tsx index d4bd6e4deec..b22d3a084cb 100644 --- a/src/components/earn/ClaimRewardModal.tsx +++ b/src/components/earn/ClaimRewardModal.tsx @@ -3,7 +3,6 @@ import { useMobi } from 'hooks/Tokens' import { TokenAmount } from 'lib/token-utils' import React, { useEffect, useState } from 'react' import { useBlockNumber } from 'state/application/hooks' -import { StablePoolInfo } from 'state/stablePools/hooks' import styled from 'styled-components' import { useWeb3Context } from '../../hooks' diff --git a/src/components/earn/DepositModal.tsx b/src/components/earn/DepositModal.tsx index 812e5fd174a..f8e041611be 100644 --- a/src/components/earn/DepositModal.tsx +++ b/src/components/earn/DepositModal.tsx @@ -5,7 +5,7 @@ import { calculateEstimatedMintAmount, calculateVirtualPrice } from 'lib/calcula import { Fraction, TokenAmount } from 'lib/token-utils' import { Meta } from 'pages/Pool' import React, { useMemo, useState } from 'react' -import { StakingInfo, UserStakingInfo } from 'state/staking/hooks' +import { tryParseAmount } from 'state/swap/hooks' import styled from 'styled-components' import { useWeb3Context } from '../../hooks' @@ -38,8 +38,6 @@ interface DepositModalProps { isOpen: boolean onDismiss: () => void meta: Meta - stakingInfo: StakingInfo - userStakingInfo: UserStakingInfo } export default function DepositModal({ isOpen, onDismiss, meta }: DepositModalProps) { @@ -58,10 +56,9 @@ export default function DepositModal({ isOpen, onDismiss, meta }: DepositModalPr const [useEqualAmount, setUseEqualAmount] = useState(forceEqualDeposit) const deadline = useTransactionDeadline() - // TODO: i think we need to parse the amount const inputTokens = useMemo(() => { - return input.map((el, i) => - el ? new TokenAmount(meta.display.pool.tokens[i], el) : new TokenAmount(meta.display.pool.tokens[i], 0) + return input.map( + (el, i) => tryParseAmount(el, meta.display.pool.tokens[i]) ?? new TokenAmount(meta.display.pool.tokens[i], 0) ) }, [input, meta.display.pool.tokens]) diff --git a/src/components/earn/UnstakingModal.tsx b/src/components/earn/UnstakingModal.tsx index 8da7603e222..3754b4586ba 100644 --- a/src/components/earn/UnstakingModal.tsx +++ b/src/components/earn/UnstakingModal.tsx @@ -2,7 +2,6 @@ import { TransactionResponse } from '@ethersproject/providers' import { useMobi } from 'hooks/Tokens' import { TokenAmount } from 'lib/token-utils' import React, { useState } from 'react' -import { StablePoolInfo } from 'state/stablePools/hooks' import styled from 'styled-components' import { useWeb3Context } from '../../hooks' diff --git a/src/components/earn/WithdrawLP.tsx b/src/components/earn/WithdrawLP.tsx index 6e81a3757b2..a79d3386939 100644 --- a/src/components/earn/WithdrawLP.tsx +++ b/src/components/earn/WithdrawLP.tsx @@ -1,7 +1,9 @@ import { TransactionResponse } from '@ethersproject/providers' import CurrencyLogo from 'components/CurrencyLogo' import JSBI from 'jsbi' +import { calculateEstimatedWithdrawAmount } from 'lib/calculator' import { Token, TokenAmount } from 'lib/token-utils' +import { Meta } from 'pages/Pool' import React, { useState } from 'react' import styled from 'styled-components' @@ -18,35 +20,33 @@ import { Input as NumericalInput } from '../NumericalInput' interface WithdrawModalProps { setAttempting: (attempting: boolean) => void setHash: (hash: string | undefined) => void - poolInfo: StablePoolInfo + meta: Meta } -export default function WithdrawLP({ poolInfo, setHash, setAttempting }: WithdrawModalProps) { +export default function WithdrawLP({ meta, setHash, setAttempting }: WithdrawModalProps) { const { connected } = useWeb3Context() - // monitor call to help UI loading state const addTransaction = useTransactionAdder() - const { tokens, lpToken } = poolInfo - const lpBalance = poolInfo.amountDeposited?.subtract(poolInfo.stakedAmount) const [approving, setApproving] = useState(false) const [input, setInput] = useState('') - const selectedAmount = tryParseAmount(input, lpToken) || new TokenAmount(lpToken, '0') - // const [selectedAmount, setSelectedAmount] = useState(new TokenAmount(lpToken, JSBI.BigInt('0'))) + const selectedAmount = + tryParseAmount(input, meta.display.pool.lpToken) || new TokenAmount(meta.display.pool.lpToken, 0) const deadline = useTransactionDeadline() - const expectedTokens = useExpectedTokens(poolInfo, selectedAmount) - const [approvalStatus, approvalCallback] = useApproveCallback(selectedAmount, poolInfo.poolAddress) - const stakingContract = useStableSwapContract(poolInfo.poolAddress) + const expectedAmount = calculateEstimatedWithdrawAmount({ poolTokenAmount: selectedAmount, ...meta.exchangeInfo }) + const [approvalStatus, approvalCallback] = useApproveCallback(selectedAmount, meta.display.pool.address) + const stakingContract = useStableSwapContract(meta.display.pool.address) + async function onWithdraw() { - if (stakingContract && poolInfo?.stakedAmount) { + if (stakingContract && deadline) { setAttempting(true) - const expected = expectedTokens.map((amount) => BigInt(amount.raw.toString())) + const expected = expectedAmount.withdrawAmounts.map((amount) => amount.raw.toString()) await stakingContract .removeLiquidity(selectedAmount.raw.toString(), expected, deadline) .then((response: TransactionResponse) => { addTransaction(response, { - summary: `Withdraw Liquidity from ${poolInfo.name}`, + summary: `Withdraw Liquidity from ${meta.display.name}`, }) setHash(response.hash) }) @@ -61,40 +61,44 @@ export default function WithdrawLP({ poolInfo, setHash, setAttempting }: Withdra if (!connected) { error = 'Connect Wallet' } - if (!poolInfo?.stakedAmount) { - error = error ?? 'Enter an amount' - } - if (selectedAmount.greaterThan(lpBalance || JSBI.BigInt('0'))) { + if (selectedAmount.greaterThan(meta.lpBalance)) { error = error ?? 'Insufficient Funds' } - const decimalPlacesForBalance = lpBalance?.greaterThan('1') ? 2 : lpBalance?.greaterThan('0') ? 10 : 2 + const decimalPlacesForBalance = meta.lpBalance?.greaterThan('1') ? 2 : meta.lpBalance?.greaterThan('0') ? 10 : 2 return ( <> - {poolInfo.stakedAmount.greaterThan(JSBI.BigInt(0)) && ( + {meta.userGauge && JSBI.greaterThan(meta.userGauge.balance, JSBI.BigInt(0)) && ( - {poolInfo.stakedAmount.toFixed(decimalPlacesForBalance)} MobLP currently deposited in the farm + {new TokenAmount(meta.display.pool.lpToken, meta.userGauge.balance).toFixed(decimalPlacesForBalance)} MobLP + currently deposited in the farm )} - + {selectedAmount.greaterThan(JSBI.BigInt('0')) && (
You will receive - {expectedTokens.map((tokenAmount, i) => ( + {expectedAmount.withdrawAmounts.map((tokenAmount, i) => ( <> null} + setTokenAmount={() => null} readOnly={true} - balance={lpBalance} + balance={meta.lpBalance} /> - {i !== expectedTokens.length - 1 && ( + {i !== expectedAmount.withdrawAmounts.length - 1 && ( + )} @@ -115,7 +119,7 @@ export default function WithdrawLP({ poolInfo, setHash, setAttempting }: Withdra )} {approvalStatus === ApprovalState.APPROVED && ( - + {error ?? 'Withdraw'} )} @@ -131,15 +135,11 @@ type CurrencyRowProps = { balance?: TokenAmount } -const InputRowLeft = styled.div`` - -const TokenInfo = styled.div`` - -const InputRow = styled.div<{ selected: boolean }>` +const InputRow = styled.div` ${({ theme }) => theme.flexRowNoWrap}; align-items: center; justify-content: space-between; - padding: ${({ selected }) => (selected ? '0.75rem 0.5rem 0.75rem 1rem' : '0.75rem 0.75rem 0.75rem 1rem')}; + padding: 0.75rem 0.75rem 0.75rem 1rem; ` const InputDiv = styled.div` @@ -153,22 +153,6 @@ const Aligner = styled.span` justify-content: space-between; ` -const InputPanel = styled.div<{ hideInput?: boolean }>` - ${({ theme }) => theme.flexColumnNoWrap} - position: relative; - border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')}; - background-color: ${({ theme }) => theme.bg2}; - z-index: 1; - width: 100%; -` - -const Container = styled.div<{ hideInput: boolean }>` - border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')}; - border: 1px solid ${({ theme }) => theme.bg2}; - background-color: ${({ theme }) => theme.bg1}; - padding: 0.5rem; -` - const StyledTokenName = styled.span<{ active?: boolean }>` ${({ active }) => (active ? ' margin: 0 0.25rem 0 0.75rem;' : ' margin: 0 0.25rem 0 0.25rem;')} font-size: ${({ active }) => (active ? '20px' : '16px')}; @@ -181,7 +165,6 @@ const BalanceText = styled(TYPE.subHeader)` const CurrencyRow = ({ val, token, setTokenAmount, balance, readOnly }: CurrencyRowProps) => { const currency = token const tokenBalance = balance - const TEN = JSBI.BigInt('10') const mainRow = ( @@ -226,11 +209,3 @@ const CurrencyRow = ({ val, token, setTokenAmount, balance, readOnly }: Currency
) } - -const insertDecimal = (tokenAmount: TokenAmount) => { - const { token } = tokenAmount - const amount = tokenAmount.divide( - new TokenAmount(token, JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt(token.decimals))) - ) - return amount.toFixed(2) -} diff --git a/src/components/earn/WithdrawModal.tsx b/src/components/earn/WithdrawModal.tsx index 6a5fe7a1cd1..8b7e9ea4984 100644 --- a/src/components/earn/WithdrawModal.tsx +++ b/src/components/earn/WithdrawModal.tsx @@ -1,4 +1,5 @@ import JSBI from 'jsbi' +import { Meta } from 'pages/Pool' import { darken } from 'polished' import React, { useState } from 'react' import styled from 'styled-components' @@ -11,7 +12,6 @@ import Modal from '../Modal' import { LoadingView, SubmittedView } from '../ModalViews' import { RowBetween } from '../Row' import WithdrawLP from './WithdrawLP' -import WithdrawTokens from './WithdrawTokens' const ContentWrapper = styled(AutoColumn)` width: 100%; @@ -34,12 +34,10 @@ const DepositWithdrawBtn = styled(StyledButton)` interface WithdrawModalProps { isOpen: boolean onDismiss: () => void - poolInfo: StablePoolInfo + meta: Meta } -export default function WithdrawModal({ isOpen, onDismiss, poolInfo }: WithdrawModalProps) { - // monitor call to help UI loading state - const [byToken, setByToken] = useState(false) +export default function WithdrawModal({ isOpen, onDismiss, meta }: WithdrawModalProps) { const [hash, setHash] = useState() const [attempting, setAttempting] = useState(false) @@ -57,30 +55,17 @@ export default function WithdrawModal({ isOpen, onDismiss, poolInfo }: WithdrawM {!attempting && !hash && ( - Withdraw from {poolInfo.name} + Withdraw from {meta.display.name} - {/* - - - By Token Amount - - - - setByToken(!byToken)} /> - */} {JSBI.greaterThan(JSBI.subtract(poolInfo.amountDeposited?.raw, poolInfo.stakedAmount.raw), JSBI.BigInt(0)) ? ( - byToken ? ( - - ) : ( - - ) + ) : ( Withdraw from farm first - + void - setHash: (hash: string | undefined) => void - poolInfo: StablePoolInfo -} - -export default function WithdrawTokens({ poolInfo, setHash, setAttempting }: WithdrawModalProps) { - const { address, connected } = useWeb3Context() - - // monitor call to help UI loading state - const addTransaction = useTransactionAdder() - const { tokens, lpToken } = poolInfo - const [approving, setApproving] = useState(false) - const lpBalance = useTokenBalance(connected ? address : undefined, lpToken) - - const [selectedAmounts, setSelectedAmounts] = useState( - tokens.map((t) => new TokenAmount(t, JSBI.BigInt('0'))) - ) - const deadline = useTransactionDeadline() - - const expectedLPTokens = useExpectedLpTokens(poolInfo, selectedAmounts, false) - const withSlippage = JSBI.add(expectedLPTokens.raw, JSBI.divide(expectedLPTokens.raw, JSBI.BigInt('10'))) - const [approvalStatus, tryApprove] = useApproveCallback(expectedLPTokens, poolInfo.poolAddress) - - const stakingContract = useStableSwapContract(poolInfo.poolAddress) - async function onDeposit() { - if (stakingContract && poolInfo?.stakedAmount) { - setAttempting(true) - const amounts = selectedAmounts.map((amount) => BigInt(amount.raw.toString())) - await stakingContract - .removeLiquidityImbalance(amounts, withSlippage.toString(), deadline) - .then((response: TransactionResponse) => { - addTransaction(response, { - summary: `Remove ${selectedAmounts - .map((amount) => `${amount.toFixed(2)} ${amount.currency.symbol}`) - .join(', ')} from ${poolInfo.name}`, - }) - setHash(response.hash) - }) - .catch((error: any) => { - setAttempting(false) - console.log(error) - }) - } - } - - let error: string | undefined - if (!connected) { - error = 'Connect Wallet' - } - if (!poolInfo?.stakedAmount) { - error = error ?? 'Enter an amount' - } - - if (expectedLPTokens.greaterThan(lpBalance || JSBI.BigInt('0'))) { - error = error ?? 'Insufficient Funds' - } - - return ( - <> - {poolInfo.tokens.map((token, i) => ( -
- - setSelectedAmounts([ - ...selectedAmounts.slice(0, i), - val, - ...selectedAmounts.slice(i + 1, selectedAmounts.length), - ]) - } - /> - {i !== selectedAmounts.length - 1 && ( - + - )} -
- ))} - - Expected Lp Tokens Required: {expectedLPTokens.toFixed(2)} - - {expectedLPTokens.greaterThan(JSBI.BigInt('0')) && approvalStatus !== ApprovalState.APPROVED && ( -
- { - setApproving(true) - await tryApprove() - await new Promise((resolve) => setTimeout(resolve, 20000)) - setApproving(false) - }} - > - Approve LP Tokens - -
- )} - {approvalStatus === ApprovalState.APPROVED && ( - - {error ?? 'Withdraw'} - - )} - - ) -} - -type CurrencyRowProps = { - tokenAmount: TokenAmount - setTokenAmount: (tokenAmount: TokenAmount) => void - readOnly: boolean | undefined -} - -const InputRow = styled.div<{ selected: boolean }>` - ${({ theme }) => theme.flexRowNoWrap}; - align-items: center; - justify-content: space-between; - padding: ${({ selected }) => (selected ? '0.75rem 0.5rem 0.75rem 1rem' : '0.75rem 0.75rem 0.75rem 1rem')}; -` - -const InputDiv = styled.div` - display: flex; - min-width: 40%; -` - -const Aligner = styled.span` - display: flex; - align-items: center; - justify-content: space-between; -` - -const StyledTokenName = styled.span<{ active?: boolean }>` - ${({ active }) => (active ? ' margin: 0 0.25rem 0 0.75rem;' : ' margin: 0 0.25rem 0 0.25rem;')} - font-size: ${({ active }) => (active ? '20px' : '16px')}; - color: ${({ theme }) => theme.text1}; -` -const BalanceText = styled(TYPE.subHeader)` - cursor: pointer; -` - -const CurrencyRow = ({ tokenAmount, setTokenAmount, readOnly }: CurrencyRowProps) => { - const { address, connected } = useWeb3Context() - const currency = tokenAmount.currency - const tokenBalance = useTokenBalance(connected ? address : undefined, currency ?? undefined) - const TEN = JSBI.BigInt('10') - const ZERO_TOK = new TokenAmount(currency, JSBI.BigInt('0')) - - const scaledDown = (num: JSBI) => JSBI.divide(num, JSBI.exponentiate(TEN, JSBI.BigInt(currency.decimals))) - - const mainRow = ( - -
- - - - {(currency && currency.symbol && currency.symbol.length > 20 - ? currency.symbol.slice(0, 4) + - '...' + - currency.symbol.slice(currency.symbol.length - 5, currency.symbol.length) - : currency?.symbol) || ''} - - -
- - { - const amount = tryParseAmount(val, currency) - setTokenAmount(amount || ZERO_TOK) - }} - /> - -
- ) - const balanceRow = !readOnly && ( -
- setTokenAmount(tokenBalance || ZERO_TOK)}> - Balance: {tokenBalance?.toFixed(2)} - -
- ) - - return ( -
- {balanceRow} - - {mainRow} -
- ) -} +// {import { TransactionResponse } from '@ethersproject/providers' +// import CurrencyLogo from 'components/CurrencyLogo' +// import JSBI from 'jsbi' +// import { TokenAmount } from 'lib/token-utils' +// import React, { useState } from 'react' +// import styled from 'styled-components' + +// import { useWeb3Context } from '../../hooks' +// import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback' +// import { useStableSwapContract } from '../../hooks/useContract' +// import useTransactionDeadline from '../../hooks/useTransactionDeadline' +// import { tryParseAmount } from '../../state/swap/hooks' +// import { useTransactionAdder } from '../../state/transactions/hooks' +// import { useTokenBalance } from '../../state/wallet/hooks' +// import { TYPE } from '../../theme' +// import { ButtonError, ButtonPrimary } from '../Button' +// import { Input as NumericalInput } from '../NumericalInput' + +// interface WithdrawModalProps { +// setAttempting: (attempting: boolean) => void +// setHash: (hash: string | undefined) => void +// poolInfo: StablePoolInfo +// } + +// export default function WithdrawTokens({ poolInfo, setHash, setAttempting }: WithdrawModalProps) { +// const { address, connected } = useWeb3Context() + +// // monitor call to help UI loading state +// const addTransaction = useTransactionAdder() +// const { tokens, lpToken } = poolInfo +// const [approving, setApproving] = useState(false) +// const lpBalance = useTokenBalance(connected ? address : undefined, lpToken) + +// const [selectedAmounts, setSelectedAmounts] = useState( +// tokens.map((t) => new TokenAmount(t, JSBI.BigInt('0'))) +// ) +// const deadline = useTransactionDeadline() + +// const expectedLPTokens = useExpectedLpTokens(poolInfo, selectedAmounts, false) +// const withSlippage = JSBI.add(expectedLPTokens.raw, JSBI.divide(expectedLPTokens.raw, JSBI.BigInt('10'))) +// const [approvalStatus, tryApprove] = useApproveCallback(expectedLPTokens, poolInfo.poolAddress) + +// const stakingContract = useStableSwapContract(poolInfo.poolAddress) +// async function onDeposit() { +// if (stakingContract && poolInfo?.stakedAmount) { +// setAttempting(true) +// const amounts = selectedAmounts.map((amount) => BigInt(amount.raw.toString())) +// await stakingContract +// .removeLiquidityImbalance(amounts, withSlippage.toString(), deadline) +// .then((response: TransactionResponse) => { +// addTransaction(response, { +// summary: `Remove ${selectedAmounts +// .map((amount) => `${amount.toFixed(2)} ${amount.currency.symbol}`) +// .join(', ')} from ${poolInfo.name}`, +// }) +// setHash(response.hash) +// }) +// .catch((error: any) => { +// setAttempting(false) +// console.log(error) +// }) +// } +// } + +// let error: string | undefined +// if (!connected) { +// error = 'Connect Wallet' +// } +// if (!poolInfo?.stakedAmount) { +// error = error ?? 'Enter an amount' +// } + +// if (expectedLPTokens.greaterThan(lpBalance || JSBI.BigInt('0'))) { +// error = error ?? 'Insufficient Funds' +// } + +// return ( +// <> +// {poolInfo.tokens.map((token, i) => ( +//
+// +// setSelectedAmounts([ +// ...selectedAmounts.slice(0, i), +// val, +// ...selectedAmounts.slice(i + 1, selectedAmounts.length), +// ]) +// } +// /> +// {i !== selectedAmounts.length - 1 && ( +// + +// )} +//
+// ))} +// +// Expected Lp Tokens Required: {expectedLPTokens.toFixed(2)} +// +// {expectedLPTokens.greaterThan(JSBI.BigInt('0')) && approvalStatus !== ApprovalState.APPROVED && ( +//
+// { +// setApproving(true) +// await tryApprove() +// await new Promise((resolve) => setTimeout(resolve, 20000)) +// setApproving(false) +// }} +// > +// Approve LP Tokens +// +//
+// )} +// {approvalStatus === ApprovalState.APPROVED && ( +// +// {error ?? 'Withdraw'} +// +// )} +// +// ) +// } + +// type CurrencyRowProps = { +// tokenAmount: TokenAmount +// setTokenAmount: (tokenAmount: TokenAmount) => void +// readOnly: boolean | undefined +// } + +// const InputRow = styled.div<{ selected: boolean }>` +// ${({ theme }) => theme.flexRowNoWrap}; +// align-items: center; +// justify-content: space-between; +// padding: ${({ selected }) => (selected ? '0.75rem 0.5rem 0.75rem 1rem' : '0.75rem 0.75rem 0.75rem 1rem')}; +// ` + +// const InputDiv = styled.div` +// display: flex; +// min-width: 40%; +// ` + +// const Aligner = styled.span` +// display: flex; +// align-items: center; +// justify-content: space-between; +// ` + +// const StyledTokenName = styled.span<{ active?: boolean }>` +// ${({ active }) => (active ? ' margin: 0 0.25rem 0 0.75rem;' : ' margin: 0 0.25rem 0 0.25rem;')} +// font-size: ${({ active }) => (active ? '20px' : '16px')}; +// color: ${({ theme }) => theme.text1}; +// ` +// const BalanceText = styled(TYPE.subHeader)` +// cursor: pointer; +// ` + +// const CurrencyRow = ({ tokenAmount, setTokenAmount, readOnly }: CurrencyRowProps) => { +// const { address, connected } = useWeb3Context() +// const currency = tokenAmount.currency +// const tokenBalance = useTokenBalance(connected ? address : undefined, currency ?? undefined) +// const TEN = JSBI.BigInt('10') +// const ZERO_TOK = new TokenAmount(currency, JSBI.BigInt('0')) + +// const scaledDown = (num: JSBI) => JSBI.divide(num, JSBI.exponentiate(TEN, JSBI.BigInt(currency.decimals))) + +// const mainRow = ( +// +//
+// +// +// +// {(currency && currency.symbol && currency.symbol.length > 20 +// ? currency.symbol.slice(0, 4) + +// '...' + +// currency.symbol.slice(currency.symbol.length - 5, currency.symbol.length) +// : currency?.symbol) || ''} +// +// +//
+// +// { +// const amount = tryParseAmount(val, currency) +// setTokenAmount(amount || ZERO_TOK) +// }} +// /> +// +//
+// ) +// const balanceRow = !readOnly && ( +//
+// setTokenAmount(tokenBalance || ZERO_TOK)}> +// Balance: {tokenBalance?.toFixed(2)} +// +//
+// ) + +// return ( +//
+// {balanceRow} + +// {mainRow} +//
+// ) +// } +export {} From bc1d8bfb6898b5fc32041613cd24b901cc7dff8f Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 28 Feb 2022 20:34:16 -0500 Subject: [PATCH 50/72] added tokens --- src/constants/ConstantSum.ts | 10 +- src/constants/pools.ts | 26 ++-- src/constants/tokens.ts | 252 +++++++++++++++++++++++++++++++++++ 3 files changed, 269 insertions(+), 19 deletions(-) diff --git a/src/constants/ConstantSum.ts b/src/constants/ConstantSum.ts index 2acc7a3fd84..923badb1209 100644 --- a/src/constants/ConstantSum.ts +++ b/src/constants/ConstantSum.ts @@ -1,12 +1,12 @@ -import { ChainId } from 'lib/token-utils' +import { ChainId, Token } from 'lib/token-utils' export type ConstantSumInfo = { address: string - tokens: [WrappedTokenInfo, WrappedTokenInfo] + tokens: [Token, Token] } export const ConstantSum: { [K in ChainId]: ConstantSumInfo[] } = { - [ChainId.MAINNET]: [ + [ChainId.Mainnet]: [ { // wETH v1/v2 pool address: '0xb1a0BDe36341065cA916c9f5619aCA82A43659A3', @@ -149,6 +149,6 @@ export const ConstantSum: { [K in ChainId]: ConstantSumInfo[] } = { // ], // }, ], - [ChainId.ALFAJORES]: [], - [ChainId.BAKLAVA]: [], + [ChainId.Alfajores]: [], + [ChainId.Baklava]: [], } diff --git a/src/constants/pools.ts b/src/constants/pools.ts index d2cfddf65bd..14724235b94 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -154,6 +154,16 @@ export const RECOMMENDED_FEES: Fees = { export const RECOMMENDED_AMP = JSBI.BigInt('100') +function lp(chainId: ChainId, address: string, name: string): Token { + return new Token({ + chainId, + address, + decimals: 18, + symbol: 'MobLP', + name, + }) +} + export const StablePools: { [K in ChainId]: DisplayPool[] } = { [ChainId.Mainnet]: [ { @@ -162,13 +172,7 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { peg: Dollar, pool: { address: '0x9F4AdBD0af281C69a582eB2E6fa2A594D4204CAe', - lpToken: new Token({ - chainId: ChainId.Mainnet, - address: '0x9438e7281D7E3e99A9dD21e0EAd9c6a254e17ab2', - decimals: 18, - symbol: 'MobLP', - name: 'Mobius cUSD/aUST LP', - }), + lpToken: lp(ChainId.Mainnet, '0x9438e7281D7E3e99A9dD21e0EAd9c6a254e17ab2', 'Mobius cUSD/aUST LP'), tokens: [CUSD[ChainId.Mainnet], UST[ChainId.Mainnet]], }, gauge: { @@ -182,13 +186,7 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { peg: Ether, pool: { address: '0x74ef28D635c6C5800DD3Cd62d4c4f8752DaACB09', - lpToken: new Token({ - chainId: ChainId.Mainnet, - address: '0x4fF08e2a4E7114af4B575AeF9250144f95790982', - decimals: 18, - symbol: 'MobLP', - name: 'Mobius cUSD/aUST LP', - }), + lpToken: lp(ChainId.Mainnet, '0x4fF08e2a4E7114af4B575AeF9250144f95790982', 'Mobius cETH/wETH LP'), tokens: [CETH[ChainId.Mainnet], WETH[ChainId.Mainnet]], }, gauge: { diff --git a/src/constants/tokens.ts b/src/constants/tokens.ts index a00fe5d54c7..bb663d2e475 100644 --- a/src/constants/tokens.ts +++ b/src/constants/tokens.ts @@ -122,6 +122,258 @@ export const WETH = makeTokens( 'https://etherscan.io/token/images/weth_28.png' ) +export const USDC = makeTokens( + { + [ChainId.Mainnet]: '0xef4229c8c3250C675F21BCefa42f58EfbfF6002a', + [ChainId.Alfajores]: '0xef4229c8c3250C675F21BCefa42f58EfbfF6002a', + [ChainId.Baklava]: '0xef4229c8c3250C675F21BCefa42f58EfbfF6002a', + }, + 6, + 'cUSDC', + 'US Dollar Coin (Optics Bridge)', + 'https://bit.ly/3CwGimW' +) + +export const DAI = makeTokens( + { + [ChainId.Mainnet]: '0x90Ca507a5D4458a4C6C6249d186b6dCb02a5BCCd', + [ChainId.Alfajores]: '0x90Ca507a5D4458a4C6C6249d186b6dCb02a5BCCd', + [ChainId.Baklava]: '0x90Ca507a5D4458a4C6C6249d186b6dCb02a5BCCd', + }, + 18, + 'DAI', + 'Optics DAI', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_DAI.png' +) + +export const CBTC = makeTokens( + { + [ChainId.Mainnet]: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', + [ChainId.Alfajores]: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', + [ChainId.Baklava]: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', + }, + 18, + 'cBTC', + 'Wrapped Bitcoin', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cBTC.png' +) + +export const WBTC = makeTokens( + { + [ChainId.Mainnet]: '0xBAAB46E28388d2779e6E31Fd00cF0e5Ad95E327B', + [ChainId.Alfajores]: '0xBAAB46E28388d2779e6E31Fd00cF0e5Ad95E327B', + [ChainId.Baklava]: '0xBAAB46E28388d2779e6E31Fd00cF0e5Ad95E327B', + }, + 8, + 'wBTC', + 'Wrapped Bitcoin (Optics Bridge)', + 'https://etherscan.io/token/images/wbtc_28.png?v=1' +) + +export const PUSDC = makeTokens( + { + [ChainId.Mainnet]: '0x1bfc26cE035c368503fAE319Cc2596716428ca44', + [ChainId.Alfajores]: '0x1bfc26cE035c368503fAE319Cc2596716428ca44', + [ChainId.Baklava]: '0x1bfc26cE035c368503fAE319Cc2596716428ca44', + }, + 6, + 'pUSDC', + 'USD Coin (PoS Optics)', + 'https://bit.ly/3CwGimW' +) + +export const USDC1 = makeTokens( + { + [ChainId.Mainnet]: '0x2A3684e9Dc20B857375EA04235F2F7edBe818FA7', + [ChainId.Alfajores]: '0x2A3684e9Dc20B857375EA04235F2F7edBe818FA7', + [ChainId.Baklava]: '0x2A3684e9Dc20B857375EA04235F2F7edBe818FA7', + }, + 6, + 'cUSDCxV1', + 'US Dollar Coin (Optics Bridge)', + 'https://bit.ly/3CwGimW' +) + +export const AAUSDC = makeTokens( + { + [ChainId.Mainnet]: '0xb70e0a782b058BFdb0d109a3599BEc1f19328E36', + [ChainId.Alfajores]: '0xb70e0a782b058BFdb0d109a3599BEc1f19328E36', + [ChainId.Baklava]: '0xb70e0a782b058BFdb0d109a3599BEc1f19328E36', + }, + 18, + 'aaUSDC', + 'US Dollar Coin (Avalanche Allbridge)', + 'https://bit.ly/3CwGimW' +) + +export const PUSD = makeTokens( + { + [ChainId.Mainnet]: '0xEadf4A7168A82D30Ba0619e64d5BCf5B30B45226', + [ChainId.Alfajores]: '0xEadf4A7168A82D30Ba0619e64d5BCf5B30B45226', + [ChainId.Baklava]: '0xEadf4A7168A82D30Ba0619e64d5BCf5B30B45226', + }, + 18, + 'pUSD', + 'Poof USD V2', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pUSD.png' +) + +export const PCELO = makeTokens( + { + [ChainId.Mainnet]: '0x301a61D01A63c8D670c2B8a43f37d12eF181F997', + [ChainId.Alfajores]: '0x301a61D01A63c8D670c2B8a43f37d12eF181F997', + [ChainId.Baklava]: '0x301a61D01A63c8D670c2B8a43f37d12eF181F997', + }, + 18, + 'pCELO', + 'Poof CELO V2', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pCELO.png' +) + +export const PEUR = makeTokens( + { + [ChainId.Mainnet]: '0xD8761DD6c7cB54febD33adD699F5E4440b62E01B', + [ChainId.Alfajores]: '0xD8761DD6c7cB54febD33adD699F5E4440b62E01B', + [ChainId.Baklava]: '0xD8761DD6c7cB54febD33adD699F5E4440b62E01B', + }, + 18, + 'pEUR', + 'Poof EUR', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pEUR.png' +) + +export const PUSD1 = makeTokens( + { + [ChainId.Mainnet]: '0xB4aa2986622249B1F45eb93F28Cfca2b2606d809', + [ChainId.Alfajores]: '0xB4aa2986622249B1F45eb93F28Cfca2b2606d809', + [ChainId.Baklava]: '0xB4aa2986622249B1F45eb93F28Cfca2b2606d809', + }, + 18, + 'pUSDxV1', + 'Poof USD V1', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pUSD.png' +) + +export const ASUSDC = makeTokens( + { + [ChainId.Mainnet]: '0xCD7D7Ff64746C1909E44Db8e95331F9316478817', + [ChainId.Alfajores]: '0xCD7D7Ff64746C1909E44Db8e95331F9316478817', + [ChainId.Baklava]: '0xCD7D7Ff64746C1909E44Db8e95331F9316478817', + }, + 18, + 'asUSDC', + 'US Dollar Coin (Solana Allbridge)', + 'https://bit.ly/3CwGimW' +) + +export const PUSDC1 = makeTokens( + { + [ChainId.Mainnet]: '0xcC82628f6A8dEFA1e2B0aD7ed448bef3647F7941', + [ChainId.Alfajores]: '0xcC82628f6A8dEFA1e2B0aD7ed448bef3647F7941', + [ChainId.Baklava]: '0xcC82628f6A8dEFA1e2B0aD7ed448bef3647F7941', + }, + 6, + 'pUSDCxV1', + 'USD Coin (PoS Optics)', + 'https://bit.ly/3CwGimW' +) + +export const CBTC1 = makeTokens( + { + [ChainId.Mainnet]: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', + [ChainId.Alfajores]: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', + [ChainId.Baklava]: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', + }, + 18, + 'cBTC', + 'Wrapped Bitcoin', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cBTC.png' +) + +export const WBTC1 = makeTokens( + { + [ChainId.Mainnet]: '0xBe50a3013A1c94768A1ABb78c3cB79AB28fc1aCE', + [ChainId.Alfajores]: '0xBe50a3013A1c94768A1ABb78c3cB79AB28fc1aCE', + [ChainId.Baklava]: '0xBe50a3013A1c94768A1ABb78c3cB79AB28fc1aCE', + }, + 8, + 'wBTCxV1', + 'Wrapped Bitcoin (Optics Bridge)', + 'https://etherscan.io/token/images/wbtc_28.png?v=1' +) + +export const CETH1 = makeTokens( + { + [ChainId.Mainnet]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', + [ChainId.Alfajores]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', + [ChainId.Baklava]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', + }, + 18, + 'cETH', + 'Wrapped Ethereum', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cETH.svg' +) + +export const WETH1 = makeTokens( + { + [ChainId.Mainnet]: '0xE919F65739c26a42616b7b8eedC6b5524d1e3aC4', + [ChainId.Alfajores]: '0xE919F65739c26a42616b7b8eedC6b5524d1e3aC4', + [ChainId.Baklava]: '0xE919F65739c26a42616b7b8eedC6b5524d1e3aC4', + }, + 18, + 'wETHxV1', + 'Wrapped Ether (Optics Bridge)', + 'https://etherscan.io/token/images/weth_28.png' +) + +export const USDTM = makeTokens( + { + [ChainId.Mainnet]: '0xcFFfE0c89a779c09Df3DF5624f54cDf7EF5fDd5D', + [ChainId.Alfajores]: '0xcFFfE0c89a779c09Df3DF5624f54cDf7EF5fDd5D', + [ChainId.Baklava]: '0xcFFfE0c89a779c09Df3DF5624f54cDf7EF5fDd5D', + }, + 18, + 'cUSDTm', + 'Tether (Moss Bridge)', + 'https://bit.ly/3AMrCyD' +) + +export const USDTC = makeTokens( + { + [ChainId.Mainnet]: '0x93DB49bE12B864019dA9Cb147ba75cDC0506190e', + [ChainId.Alfajores]: '0x93DB49bE12B864019dA9Cb147ba75cDC0506190e', + [ChainId.Baklava]: '0x93DB49bE12B864019dA9Cb147ba75cDC0506190e', + }, + 18, + 'cUSDCm', + 'US Dollar Coin (Moss Bridge)', + 'https://bit.ly/3CwGimW' +) + +export const PCELO1 = makeTokens( + { + [ChainId.Mainnet]: '0xE74AbF23E1Fdf7ACbec2F3a30a772eF77f1601E1', + [ChainId.Alfajores]: '0xE74AbF23E1Fdf7ACbec2F3a30a772eF77f1601E1', + [ChainId.Baklava]: '0xE74AbF23E1Fdf7ACbec2F3a30a772eF77f1601E1', + }, + 18, + 'pCELOxV1', + 'Poof Celo V1', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pCELO.png' +) + +export const PEUR1 = makeTokens( + { + [ChainId.Mainnet]: '0x56072D4832642dB29225dA12d6Fd1290E4744682', + [ChainId.Alfajores]: '0x56072D4832642dB29225dA12d6Fd1290E4744682', + [ChainId.Baklava]: '0x56072D4832642dB29225dA12d6Fd1290E4744682', + }, + 18, + 'pEURxV1', + 'Poof EUR V1', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pEUR.png' +) + export const ExternalRewards: { [K in ChainId]: Token[] } = { [ChainId.Mainnet]: [ new Token({ From 4c5e03ceeda3263036e12503ee3575b517b26538 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 28 Feb 2022 21:11:41 -0500 Subject: [PATCH 51/72] builds --- src/constants/ConstantSum.ts | 106 ++--------------------------- src/lib/token-utils/tokenAmount.ts | 3 +- 2 files changed, 6 insertions(+), 103 deletions(-) diff --git a/src/constants/ConstantSum.ts b/src/constants/ConstantSum.ts index 923badb1209..d205410cfbe 100644 --- a/src/constants/ConstantSum.ts +++ b/src/constants/ConstantSum.ts @@ -1,5 +1,7 @@ import { ChainId, Token } from 'lib/token-utils' +import { USDC, USDC1, WBTC, WBTC1, WETH, WETH1 } from './tokens' + export type ConstantSumInfo = { address: string tokens: [Token, Token] @@ -10,115 +12,17 @@ export const ConstantSum: { [K in ChainId]: ConstantSumInfo[] } = { { // wETH v1/v2 pool address: '0xb1a0BDe36341065cA916c9f5619aCA82A43659A3', - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xE919F65739c26a42616b7b8eedC6b5524d1e3aC4', - decimals: 18, - symbol: 'wETHxV1', - name: 'Wrapped Ether (Optics Bridge)', - logoURI: 'https://etherscan.io/token/images/weth_28.png', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x122013fd7dF1C6F636a5bb8f03108E876548b455', - decimals: 18, - symbol: 'wETH', - name: 'Wrapped Ether (Optics Bridge)', - logoURI: 'https://etherscan.io/token/images/weth_28.png', - }, - [] - ), - ], + tokens: [WETH1[ChainId.Mainnet], WETH[ChainId.Mainnet]], }, - // { - // // wETH v1/v2 pool - // address: '0x7e0B5284864916A866Fc391454ac2f452F91a336', - // tokens: [ - // new WrappedTokenInfo( - // { - // chainId: ChainId.MAINNET, - // address: '0xD68536297a01DBB4739a4e2cC1E79a8CFA2E3A3E', - // decimals: 18, - // symbol: 'wETHxV1', - // name: 'Wrapped Ether (Optics Bridge)', - // logoURI: 'https://etherscan.io/token/images/weth_28.png', - // }, - // [] - // ), - // new WrappedTokenInfo( - // { - // chainId: ChainId.MAINNET, - // address: '0xb909F71b53C621e467Ee9ECD387E6662CA4f15eF', - // decimals: 18, - // symbol: 'wETH', - // name: 'Wrapped Ether (Optics Bridge)', - // logoURI: 'https://etherscan.io/token/images/weth_28.png', - // }, - // [] - // ), - // ], - // }, - { // BTC v1/v2 address: '0xd5ab1BA8b2Ec70752068d1d728e728eAd0E19CBA', - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xBe50a3013A1c94768A1ABb78c3cB79AB28fc1aCE', - decimals: 8, - symbol: 'wBTCxV1', - name: 'Wrapped Bitcoin (Optics Bridge)', - logoURI: 'https://etherscan.io/token/images/wbtc_28.png?v=1', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xBAAB46E28388d2779e6E31Fd00cF0e5Ad95E327B', - decimals: 8, - symbol: 'wBTC', - name: 'Wrapped Bitcoin (Optics Bridge)', - logoURI: 'https://etherscan.io/token/images/wbtc_28.png?v=1', - }, - [] - ), - ], + tokens: [WBTC1[ChainId.Mainnet], WBTC[ChainId.Mainnet]], }, { // USDC v1/v2 address: '0x70bfA1C8Ab4e42B9BE74f65941EFb6e5308148c7', - tokens: [ - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0x2A3684e9Dc20B857375EA04235F2F7edBe818FA7', - decimals: 6, - symbol: 'cUSDCxV1', - name: 'US Dollar Coin (Optics Bridge)', - logoURI: 'https://bit.ly/3CwGimW', - }, - [] - ), - new WrappedTokenInfo( - { - chainId: ChainId.MAINNET, - address: '0xef4229c8c3250C675F21BCefa42f58EfbfF6002a', - decimals: 6, - symbol: 'cUSDC', - name: 'US Dollar Coin (Optics Bridge)', - logoURI: 'https://bit.ly/3CwGimW', - }, - [] - ), - ], + tokens: [USDC1[ChainId.Mainnet], USDC[ChainId.Mainnet]], }, // { // // TEST pool diff --git a/src/lib/token-utils/tokenAmount.ts b/src/lib/token-utils/tokenAmount.ts index 0d1ca2eaa6a..e271631bd6c 100644 --- a/src/lib/token-utils/tokenAmount.ts +++ b/src/lib/token-utils/tokenAmount.ts @@ -1,5 +1,5 @@ import type { BigintIsh, NumberFormat, Percent } from '@ubeswap/token-math' -import { TokenAmount as UTokenAmount, validateU64 } from '@ubeswap/token-math' +import { TokenAmount as UTokenAmount } from '@ubeswap/token-math' import type { Token } from './token' @@ -18,7 +18,6 @@ export class TokenAmount extends UTokenAmount { // amount _must_ be raw, i.e. in the native representation constructor(token: Token, amount: BigintIsh) { super(token, amount) - validateU64(this.raw) } /** From e36ed3c5ed5cda743f512cfbb1a0c3f0cd3d0383 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 28 Feb 2022 23:11:55 -0500 Subject: [PATCH 52/72] pools build --- src/components/earn/StablePoolCard.tsx | 16 +++++----------- src/components/earn/WithdrawModal.tsx | 4 ++-- src/pages/Pool/index.tsx | 7 +++---- src/state/mobiusPools/hooks.ts | 2 +- 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/components/earn/StablePoolCard.tsx b/src/components/earn/StablePoolCard.tsx index 9a2d8b5fbc5..3e10023035a 100644 --- a/src/components/earn/StablePoolCard.tsx +++ b/src/components/earn/StablePoolCard.tsx @@ -12,7 +12,7 @@ import { isMobile } from 'react-device-detect' import { useHistory } from 'react-router' import { NavLink } from 'react-router-dom' import { useMobiPrice, useTokenPrice } from 'state/application/hooks' -import { StakingInfo, UserStakingInfo } from 'state/staking/hooks' +import { StakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { calcRates } from 'utils/calcRate' @@ -142,10 +142,9 @@ const StyledNavLink = styled(NavLink)<{ color: string }>` interface Props { meta: Meta stakingInfo: StakingInfo - userStakingInfo: UserStakingInfo } -export const StablePoolCard: React.FC = ({ meta, stakingInfo, userStakingInfo }: Props) => { +export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => { const { connect, connected } = useWeb3Context() const history = useHistory() @@ -214,10 +213,7 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo, userStaking // console.error('Weekly apy overflow', e) // } const balances = calculateEstimatedWithdrawAmount({ poolTokenAmount: meta.lpBalance, ...meta.exchangeInfo }) - const userBalances = calculateEstimatedWithdrawAmount({ - poolTokenAmount: meta.exchangeInfo.lpTotalSupply, - ...meta.exchangeInfo, - }) + // let userBalances: TokenAmount[] = [] // if (totalDeposited.greaterThan('0')) { // userBalances = balances.map((amount) => { @@ -243,10 +239,8 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo, userStaking return ( setOpenManage(!openManage)}> - {openDeposit && setOpenDeposit(false)} poolInfo={poolInfo} />} - {openWithdraw && ( - setOpenWithdraw(false)} poolInfo={poolInfo} /> - )} + {openDeposit && setOpenDeposit(false)} meta={meta} />} + {openWithdraw && setOpenWithdraw(false)} meta={meta} />} diff --git a/src/components/earn/WithdrawModal.tsx b/src/components/earn/WithdrawModal.tsx index 8b7e9ea4984..28fe6c43f44 100644 --- a/src/components/earn/WithdrawModal.tsx +++ b/src/components/earn/WithdrawModal.tsx @@ -58,8 +58,8 @@ export default function WithdrawModal({ isOpen, onDismiss, meta }: WithdrawModal Withdraw from {meta.display.name} - {JSBI.greaterThan(JSBI.subtract(poolInfo.amountDeposited?.raw, poolInfo.stakedAmount.raw), JSBI.BigInt(0)) ? ( - + {meta.userGauge && !JSBI.equal(JSBI.BigInt(0), meta.userGauge?.balance) ? ( + ) : ( diff --git a/src/pages/Pool/index.tsx b/src/pages/Pool/index.tsx index f8dd4dbf166..32f476a9ce5 100644 --- a/src/pages/Pool/index.tsx +++ b/src/pages/Pool/index.tsx @@ -9,7 +9,7 @@ import { isMobile } from 'react-device-detect' import { useMobiPrice } from 'state/application/hooks' import { GaugeInfo, useAllGaugesInfo, useAllUserGaugesInfo, UserGaugeInfo } from 'state/gauges/hooks' import { useAllLpBalances, usePools, usePoolsVolume } from 'state/mobiusPools/hooks' -import { useStakingInfo, useUserStakingInfo } from 'state/staking/hooks' +import { useStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { AutoColumn } from '../../components/Column' @@ -81,7 +81,6 @@ export default function Pool() { const userGauges = useAllUserGaugesInfo() const gauges = useAllGaugesInfo() const stakingInfo = useStakingInfo() - const userStakingInfo = useUserStakingInfo() const exchanges = usePools() const lpBalances = useAllLpBalances() const volumes = usePoolsVolume() @@ -171,7 +170,7 @@ export default function Pool() { {sortedFilterdPools .filter((pool) => !pool.gauge?.isKilled) .map((pool) => ( - + ))} @@ -196,7 +195,7 @@ export default function Pool() { {showDeprecated && sortedFilterdPools .filter((pool) => pool.gauge?.isKilled) - .map((pool) => )} + .map((pool) => )} diff --git a/src/state/mobiusPools/hooks.ts b/src/state/mobiusPools/hooks.ts index 654891b4102..569a7a5e056 100644 --- a/src/state/mobiusPools/hooks.ts +++ b/src/state/mobiusPools/hooks.ts @@ -71,7 +71,7 @@ export function useAllLpBalances(): TokenAmount[] { const { address, connected } = useWeb3Context() const balances = useTokenBalances( - address, + connected ? address : undefined, StablePools[CHAIN].map(({ pool }) => pool.lpToken) ) From 44f41330a7b4094af52937eb923a29e5c8cde285 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 28 Feb 2022 23:52:09 -0500 Subject: [PATCH 53/72] update eslint --- .eslintrc.js | 48 ++++-------- package.json | 1 + src/constants/StablePools.ts | 8 +- src/constants/pools.ts | 6 ++ yarn.lock | 144 ++++++++++++++++++++++++++++++++--- 5 files changed, 156 insertions(+), 51 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 3d0a287284b..bb997801ed0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,40 +1,20 @@ -// eslint-disable-next-line no-undef +'use strict' + + module.exports = { - parser: '@typescript-eslint/parser', - parserOptions: { - ecmaVersion: 2020, - sourceType: 'module', - ecmaFeatures: { - // Allows for the parsing of JSX - jsx: true, - }, + env: { + browser: true, + es2021: true, + node: true, + jest: true, }, - ignorePatterns: ['node_modules/**/*', 'craco.config.js'], - settings: { - react: { - version: 'detect', - }, + ignorePatterns: ['*.js'], + extends: ['@saberhq/eslint-config-react', 'plugin:jsx-a11y/recommended'], + parserOptions: { + project: 'tsconfig.json', }, - plugins: ['simple-import-sort', 'import', 'unused-imports'], - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react/recommended', - 'plugin:react-hooks/recommended', - 'plugin:prettier/recommended', - ], rules: { - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/camelcase': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - - 'import/order': 'off', - 'simple-import-sort/imports': 'warn', - 'simple-import-sort/exports': 'warn', - 'import/first': 'warn', - 'import/newline-after-import': 'warn', - 'import/no-duplicates': 'warn', - 'unused-imports/no-unused-imports': 'error', + 'react/react-in-jsx-scope': 'off', + 'react/no-unescaped-entities': 'off', }, } diff --git a/package.json b/package.json index 935ba04fe20..e40236e6696 100644 --- a/package.json +++ b/package.json @@ -130,6 +130,7 @@ "@ethersproject/strings": "^5.3.0", "@ethersproject/units": "^5.3.0", "@ledgerhq/hw-transport-webusb": "^6.24.1", + "@saberhq/eslint-config-react": "^1.12.47", "@sentry/react": "^6.9.0", "@types/jest": "^27.4.1", "@types/lodash.mapvalues": "^4.6.6", diff --git a/src/constants/StablePools.ts b/src/constants/StablePools.ts index dbb6ac47ac7..aff1423ea1d 100644 --- a/src/constants/StablePools.ts +++ b/src/constants/StablePools.ts @@ -1,10 +1,4 @@ -import BigNumber from 'bignumber.js' -import { ChainId } from 'lib/token-utils' - -const weeklyEmissionToSeconds = (n: number) => { - const yearlyEmission = new BigNumber(`${n}e+18`).dividedBy(7 * 24 * 60 * 60) - return yearlyEmission.toFixed(0) -} +import type { ChainId } from 'lib/token-utils' // export const STATIC_POOL_INFO: { [K in ChainId]: StableSwapConstants[] } = { // [ChainId.MAINNET]: [ diff --git a/src/constants/pools.ts b/src/constants/pools.ts index 14724235b94..138c8aba920 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -1,3 +1,4 @@ +import BigNumber from 'bignumber.js' import JSBI from 'jsbi' import { ChainId, Percent, Token, TokenAmount } from 'lib/token-utils' @@ -164,6 +165,11 @@ function lp(chainId: ChainId, address: string, name: string): Token { }) } +const weeklyEmissionToSeconds = (n: number) => { + const yearlyEmission = new BigNumber(`${n}e+18`).dividedBy(7 * 24 * 60 * 60) + return yearlyEmission.toFixed(0) +} + export const StablePools: { [K in ChainId]: DisplayPool[] } = { [ChainId.Mainnet]: [ { diff --git a/yarn.lock b/yarn.lock index e743471380f..bfec1e1a243 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2571,6 +2571,31 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@saberhq/eslint-config-react@^1.12.47": + version "1.12.47" + resolved "https://registry.yarnpkg.com/@saberhq/eslint-config-react/-/eslint-config-react-1.12.47.tgz#6bcc049efacf34d14163b3f942d400e912fae6c9" + integrity sha512-67oEcvD91fPVMzi6DlkXDxJaR1ridb++6zJ1dJy8a86tvvibwF8ea9SrdJaofz/VcrcZiVOMD9T54aUifo1msg== + dependencies: + "@saberhq/eslint-config" "^1.12.47" + eslint-plugin-jsx-a11y "^6.5.1" + eslint-plugin-react "^7.29.2" + eslint-plugin-react-hooks "^4.3.0" + +"@saberhq/eslint-config@^1.12.47": + version "1.12.47" + resolved "https://registry.yarnpkg.com/@saberhq/eslint-config/-/eslint-config-1.12.47.tgz#4e6bf3b27e5f00154db5d6bd2f7f0730a4b850cd" + integrity sha512-lpdq3jWfO9RhFm8O5ajj2EhKlW5KIWUY22d15ZkTGgItr4QCQCGb0DZDYUqCh7yRSe09NbwPKZmV35DBRXxGPg== + dependencies: + "@typescript-eslint/eslint-plugin" "^5.12.1" + "@typescript-eslint/parser" "^5.12.1" + eslint-config-prettier "^8.4.0" + eslint-import-resolver-node "^0.3.6" + eslint-plugin-import "^2.25.4" + eslint-plugin-prettier "^4.0.0" + eslint-plugin-simple-import-sort "^7.0.0" + eslint-plugin-unused-imports "^2.0.0" + prettier "^2.5.1" + "@sentry/browser@6.18.0": version "6.18.0" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.18.0.tgz#72d3e885199e0b41272ef37162dbbfa828e9c469" @@ -3152,7 +3177,7 @@ jest-matcher-utils "^27.0.0" pretty-format "^27.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8": +"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== @@ -3497,6 +3522,21 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/eslint-plugin@^5.12.1": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz#2809052b85911ced9c54a60dac10e515e9114497" + integrity sha512-vLktb2Uec81fxm/cfz2Hd6QaWOs8qdmVAZXLdOBX6JFJDhf6oDZpMzZ4/LZ6SFM/5DgDcxIMIvy3F+O9yZBuiQ== + dependencies: + "@typescript-eslint/scope-manager" "5.13.0" + "@typescript-eslint/type-utils" "5.13.0" + "@typescript-eslint/utils" "5.13.0" + debug "^4.3.2" + functional-red-black-tree "^1.0.1" + ignore "^5.1.8" + regexpp "^3.2.0" + semver "^7.3.5" + tsutils "^3.21.0" + "@typescript-eslint/experimental-utils@4.33.0", "@typescript-eslint/experimental-utils@^4.0.1": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" @@ -3530,6 +3570,16 @@ "@typescript-eslint/typescript-estree" "4.33.0" debug "^4.3.1" +"@typescript-eslint/parser@^5.12.1": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.13.0.tgz#0394ed8f2f849273c0bf4b811994d177112ced5c" + integrity sha512-GdrU4GvBE29tm2RqWOM0P5QfCtgCyN4hXICj/X9ibKED16136l9ZpoJvCL5pSKtmJzA+NRDzQ312wWMejCVVfg== + dependencies: + "@typescript-eslint/scope-manager" "5.13.0" + "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/typescript-estree" "5.13.0" + debug "^4.3.2" + "@typescript-eslint/scope-manager@4.33.0": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" @@ -3538,6 +3588,23 @@ "@typescript-eslint/types" "4.33.0" "@typescript-eslint/visitor-keys" "4.33.0" +"@typescript-eslint/scope-manager@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz#cf6aff61ca497cb19f0397eea8444a58f46156b6" + integrity sha512-T4N8UvKYDSfVYdmJq7g2IPJYCRzwtp74KyDZytkR4OL3NRupvswvmJQJ4CX5tDSurW2cvCc1Ia1qM7d0jpa7IA== + dependencies: + "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/visitor-keys" "5.13.0" + +"@typescript-eslint/type-utils@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.13.0.tgz#b0efd45c85b7bab1125c97b752cab3a86c7b615d" + integrity sha512-/nz7qFizaBM1SuqAKb7GLkcNn2buRdDgZraXlkhz+vUGiN1NZ9LzkA595tHHeduAiS2MsHqMNhE2zNzGdw43Yg== + dependencies: + "@typescript-eslint/utils" "5.13.0" + debug "^4.3.2" + tsutils "^3.21.0" + "@typescript-eslint/types@3.10.1": version "3.10.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" @@ -3548,6 +3615,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== +"@typescript-eslint/types@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.13.0.tgz#da1de4ae905b1b9ff682cab0bed6b2e3be9c04e5" + integrity sha512-LmE/KO6DUy0nFY/OoQU0XelnmDt+V8lPQhh8MOVa7Y5k2gGRd6U9Kp3wAjhB4OHg57tUO0nOnwYQhRRyEAyOyg== + "@typescript-eslint/typescript-estree@3.10.1": version "3.10.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" @@ -3575,6 +3647,31 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz#b37c07b748ff030a3e93d87c842714e020b78141" + integrity sha512-Q9cQow0DeLjnp5DuEDjLZ6JIkwGx3oYZe+BfcNuw/POhtpcxMTy18Icl6BJqTSd+3ftsrfuVb7mNHRZf7xiaNA== + dependencies: + "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/visitor-keys" "5.13.0" + debug "^4.3.2" + globby "^11.0.4" + is-glob "^4.0.3" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.13.0.tgz#2328feca700eb02837298339a2e49c46b41bd0af" + integrity sha512-+9oHlPWYNl6AwwoEt5TQryEHwiKRVjz7Vk6kaBeD3/kwHE5YqTGHtm/JZY8Bo9ITOeKutFaXnBlMgSATMJALUQ== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.13.0" + "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/typescript-estree" "5.13.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + "@typescript-eslint/visitor-keys@3.10.1": version "3.10.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" @@ -3590,6 +3687,14 @@ "@typescript-eslint/types" "4.33.0" eslint-visitor-keys "^2.0.0" +"@typescript-eslint/visitor-keys@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz#f45ff55bcce16403b221ac9240fbeeae4764f0fd" + integrity sha512-HLKEAS/qA1V7d9EzcpLFykTePmOQqOFim8oCvhY3pZgQ8Hi38hYpHd9e5GN6nQBFQNecNhws5wkS9Y5XIO0s/g== + dependencies: + "@typescript-eslint/types" "5.13.0" + eslint-visitor-keys "^3.0.0" + "@ubeswap/sdk@^2.1.0": version "2.1.2" resolved "https://registry.yarnpkg.com/@ubeswap/sdk/-/sdk-2.1.2.tgz#e0dd4e44c1b9071668f493e8b35486aba694b198" @@ -6722,7 +6827,7 @@ debug@3.2.6: dependencies: ms "^2.1.1" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3: +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== @@ -7360,7 +7465,7 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^8.3.0: +eslint-config-prettier@^8.3.0, eslint-config-prettier@^8.4.0: version "8.4.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.4.0.tgz#8e6d17c7436649e98c4c2189868562921ef563de" integrity sha512-CFotdUcMY18nGRo5KGsnNxpznzhkopOcOo0InID+sgQssPrzjvsyKZPvOgymTFeHrFuC3Tzdf2YndhXtULK9Iw== @@ -7396,7 +7501,7 @@ eslint-plugin-flowtype@^5.2.0: lodash "^4.17.15" string-natural-compare "^3.0.1" -eslint-plugin-import@^2.22.1, eslint-plugin-import@^2.23.4: +eslint-plugin-import@^2.22.1, eslint-plugin-import@^2.23.4, eslint-plugin-import@^2.25.4: version "2.25.4" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1" integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA== @@ -7422,7 +7527,7 @@ eslint-plugin-jest@^24.1.0: dependencies: "@typescript-eslint/experimental-utils" "^4.0.1" -eslint-plugin-jsx-a11y@^6.3.1: +eslint-plugin-jsx-a11y@^6.3.1, eslint-plugin-jsx-a11y@^6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8" integrity sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g== @@ -7447,12 +7552,19 @@ eslint-plugin-prettier@^3.4.0: dependencies: prettier-linter-helpers "^1.0.0" -eslint-plugin-react-hooks@^4.2.0: +eslint-plugin-prettier@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0" + integrity sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-react-hooks@^4.2.0, eslint-plugin-react-hooks@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172" integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA== -eslint-plugin-react@^7.21.5, eslint-plugin-react@^7.24.0: +eslint-plugin-react@^7.21.5, eslint-plugin-react@^7.24.0, eslint-plugin-react@^7.29.2: version "7.29.2" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.2.tgz#2d4da69d30d0a736efd30890dc6826f3e91f3f7c" integrity sha512-ypEBTKOy5liFQXZWMchJ3LN0JX1uPI6n7MN7OPHKacqXAxq5gYC30TdO7wqGYQyxD1OrzpobdHC3hDmlRWDg9w== @@ -7491,6 +7603,13 @@ eslint-plugin-unused-imports@^1.1.1: dependencies: eslint-rule-composer "^0.3.0" +eslint-plugin-unused-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz#d8db8c4d0cfa0637a8b51ce3fd7d1b6bc3f08520" + integrity sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A== + dependencies: + eslint-rule-composer "^0.3.0" + eslint-rule-composer@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" @@ -7536,6 +7655,11 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== +eslint-visitor-keys@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== + eslint-webpack-plugin@^2.5.2: version "2.6.0" resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-2.6.0.tgz#3bd4ada4e539cb1f6687d2f619073dbb509361cd" @@ -8823,7 +8947,7 @@ globby@11.0.1: merge2 "^1.3.0" slash "^3.0.0" -globby@^11.0.3: +globby@^11.0.3, globby@^11.0.4: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -13602,7 +13726,7 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.1.2, prettier@^2.3.0, prettier@^2.3.1: +prettier@^2.1.2, prettier@^2.3.0, prettier@^2.3.1, prettier@^2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== @@ -14571,7 +14695,7 @@ regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1: call-bind "^1.0.2" define-properties "^1.1.3" -regexpp@^3.1.0: +regexpp@^3.1.0, regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== From 2f30ad3414215038dd131a49f108f96f81c9bcb6 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 1 Mar 2022 12:53:59 -0500 Subject: [PATCH 54/72] multicall fix --- .eslintrc.js | 48 ++++++++++++++++++++++---------- src/constants/multicall/index.ts | 6 ++-- src/hooks/useStablePools.ts | 6 ++-- src/lib/token-utils/token.ts | 8 +++--- src/pages/Pool/index.tsx | 1 + src/state/application/hooks.ts | 2 +- src/state/application/updater.ts | 5 +--- src/state/mobiusPools/updater.ts | 7 +++-- src/state/wallet/hooks.ts | 1 - 9 files changed, 53 insertions(+), 31 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index bb997801ed0..3d0a287284b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,20 +1,40 @@ -'use strict' - - +// eslint-disable-next-line no-undef module.exports = { - env: { - browser: true, - es2021: true, - node: true, - jest: true, - }, - ignorePatterns: ['*.js'], - extends: ['@saberhq/eslint-config-react', 'plugin:jsx-a11y/recommended'], + parser: '@typescript-eslint/parser', parserOptions: { - project: 'tsconfig.json', + ecmaVersion: 2020, + sourceType: 'module', + ecmaFeatures: { + // Allows for the parsing of JSX + jsx: true, + }, }, + ignorePatterns: ['node_modules/**/*', 'craco.config.js'], + settings: { + react: { + version: 'detect', + }, + }, + plugins: ['simple-import-sort', 'import', 'unused-imports'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react/recommended', + 'plugin:react-hooks/recommended', + 'plugin:prettier/recommended', + ], rules: { - 'react/react-in-jsx-scope': 'off', - 'react/no-unescaped-entities': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/camelcase': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + + 'import/order': 'off', + 'simple-import-sort/imports': 'warn', + 'simple-import-sort/exports': 'warn', + 'import/first': 'warn', + 'import/newline-after-import': 'warn', + 'import/no-duplicates': 'warn', + 'unused-imports/no-unused-imports': 'error', }, } diff --git a/src/constants/multicall/index.ts b/src/constants/multicall/index.ts index 0c8d04a2f98..bc45363a506 100644 --- a/src/constants/multicall/index.ts +++ b/src/constants/multicall/index.ts @@ -3,9 +3,9 @@ import { ChainId } from 'lib/token-utils' import MULTICALL_ABI from './abi.json' const MULTICALL_NETWORKS: { [chainId in ChainId]: string } = { - [ChainId.MAINNET]: '0x75f59534dd892c1f8a7b172d639fa854d529ada3', - [ChainId.ALFAJORES]: '0x75f59534dd892c1f8a7b172d639fa854d529ada3', - [ChainId.BAKLAVA]: '0x75f59534dd892c1f8a7b172d639fa854d529ada3', + [ChainId.Mainnet]: '0x75f59534dd892c1f8a7b172d639fa854d529ada3', + [ChainId.Alfajores]: '0x75f59534dd892c1f8a7b172d639fa854d529ada3', + [ChainId.Baklava]: '0x75f59534dd892c1f8a7b172d639fa854d529ada3', } export { MULTICALL_ABI, MULTICALL_NETWORKS } diff --git a/src/hooks/useStablePools.ts b/src/hooks/useStablePools.ts index c8d306d9976..2dcb912184a 100644 --- a/src/hooks/useStablePools.ts +++ b/src/hooks/useStablePools.ts @@ -28,11 +28,13 @@ export function useValueOfAllPools(): Fraction { const prices = useTokenPrices() const pools = usePools() return StablePools[CHAIN].reduce((acc, cur, i) => { - const price = cur.peg.priceQuery ? priceStringToFraction(prices[cur.peg.priceQuery]) : new Fraction(0) + const price = cur.peg.priceQuery ? priceStringToFraction(prices[cur.peg.priceQuery]) : new Fraction(1) if (!price) return acc const virtualPrice = calculateVirtualPrice(pools[i]) - return virtualPrice ? acc.add(price.multiply(virtualPrice).multiply(pools[i].lpTotalSupply)) : acc + return virtualPrice + ? acc.add(price.multiply(virtualPrice).multiply(pools[i].lpTotalSupply)) + : acc.add(price).multiply(pools[i].lpTotalSupply) }, new Fraction(0)) } diff --git a/src/lib/token-utils/token.ts b/src/lib/token-utils/token.ts index 4c79f6577bd..981164a752b 100644 --- a/src/lib/token-utils/token.ts +++ b/src/lib/token-utils/token.ts @@ -13,7 +13,7 @@ export class Token implements UToken { readonly network: Network constructor(readonly info: TokenInfo) { - this.network = chainIdToNetwork(info.chainId) ?? 'localnet' + this.network = chainIdToNetwork(info.chainId) ?? Mainnet } /** @@ -95,9 +95,9 @@ export const tokensEqual = (a: Token | undefined, b: Token | undefined): boolean export type TokenMap = { [c in ChainId]: Token } export const CHAIN_ID_TO_NETWORK = { - [ChainId.MAINNET]: Mainnet, - [ChainId.ALFAJORES]: Alfajores, - [ChainId.BAKLAVA]: Baklava, + [ChainId.Mainnet]: Mainnet, + [ChainId.Alfajores]: Alfajores, + [ChainId.Baklava]: Baklava, } /** diff --git a/src/pages/Pool/index.tsx b/src/pages/Pool/index.tsx index 32f476a9ce5..7b44589ef7a 100644 --- a/src/pages/Pool/index.tsx +++ b/src/pages/Pool/index.tsx @@ -82,6 +82,7 @@ export default function Pool() { const gauges = useAllGaugesInfo() const stakingInfo = useStakingInfo() const exchanges = usePools() + console.log(exchanges[0].lpTotalSupply.toString()) const lpBalances = useAllLpBalances() const volumes = usePoolsVolume() diff --git a/src/state/application/hooks.ts b/src/state/application/hooks.ts index 2ddc76fe703..ca6c5142b66 100644 --- a/src/state/application/hooks.ts +++ b/src/state/application/hooks.ts @@ -113,7 +113,7 @@ export function useMobiPrice(): Fraction { export function priceStringToFraction(priceString: string | undefined): Fraction | undefined { if (!priceString) return undefined const price = parseFloat(priceString) * 10 ** 4 - const asFraction = new Fraction(price.toFixed(0), '10000') + const asFraction = new Fraction(price.toFixed(0), 10000) return asFraction } diff --git a/src/state/application/updater.ts b/src/state/application/updater.ts index 49255133bc7..d63ed893a9e 100644 --- a/src/state/application/updater.ts +++ b/src/state/application/updater.ts @@ -31,10 +31,8 @@ const fetchPegPrices = async (dispatch: Dispatch) => { const resp = await axios.get( `https://api.coingecko.com/api/v3/simple/price?ids=${ids.slice(0, -2)}&vs_currencies=usd` ) - const prices: TokenPrices = pegQueries.reduce((acc, cur) => { - console.log(resp.data[cur]?.['usd']) - return { ...acc, [cur]: resp.data[cur]?.['usd'] } + return { ...acc, [cur]: (resp.data[cur]?.['usd'] as number).toString() } }, {}) dispatch(addPrices({ prices: prices })) } @@ -55,7 +53,6 @@ export function PriceData(): null { const { data, loading, error } = useQuery(mobiPriceQuery, { client: ubeswapClient }) useEffect(() => { if (!loading && !error && data) { - console.log('update prices') fetchPegPrices(dispatch) dispatch(addPrice({ token: mobi.address.toLowerCase(), price: data.token.derivedCUSD })) } diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index 04ee910eb4e..45bbb16ec78 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -22,11 +22,15 @@ export function UpdatePools() { const blockNumber = useBlockNumber() const dispatch = useDispatch() const stablePools = StablePools[CHAIN] + const lpTokenAddress = stablePools.map((p) => p.pool.lpToken.address) const poolAddress = stablePools.map((p) => p.pool.address) + const lpTotalSupply = useMultipleContractSingleData(lpTokenAddress, lpInterface, 'totalSupply') const balances = useMultipleContractSingleData(poolAddress, SwapInterface, 'getBalances') + const virtualPrices = useMultipleContractSingleData(poolAddress, SwapInterface, 'getVirtualPrice') + const query = gql` { swaps { @@ -46,7 +50,6 @@ export function UpdatePools() { const { data, loading } = useQuery(query) useEffect(() => { - if (loading) return // const inSubgraph: Set = // data?.swaps.reduce((accum: Set, cur: any) => new Set([...accum, cur.id]), new Set()) ?? new Set() try { @@ -75,6 +78,6 @@ export function UpdatePools() { } catch (error) { console.error(error) } - }, [loading, data?.swaps, dispatch, stablePools, lpTotalSupply, blockNumber, balances]) + }, [dispatch, stablePools, lpTotalSupply, blockNumber, balances]) return null } diff --git a/src/state/wallet/hooks.ts b/src/state/wallet/hooks.ts index e270d99e7e7..c1c2268a781 100644 --- a/src/state/wallet/hooks.ts +++ b/src/state/wallet/hooks.ts @@ -40,7 +40,6 @@ export function useTokenBalances( () => tokens?.filter((t?: Token): t is Token => isAddress(t?.address) !== false) ?? [], [tokens] ) - const validatedTokenAddresses = useMemo(() => validatedTokens.map((vt) => vt.address), [validatedTokens]) const balances = useMultipleContractSingleData(validatedTokenAddresses, ERC20_INTERFACE, 'balanceOf', [address]) From bab09ae1c2654951eb7fa6fda50a8b0014e44bc3 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 1 Mar 2022 13:44:15 -0500 Subject: [PATCH 55/72] bug fixes --- src/components/earn/StablePoolCard.tsx | 28 +++++++++++++++-------- src/constants/pools.ts | 12 +++++----- src/pages/Pool/index.tsx | 7 +++--- src/state/gauges/updater.ts | 2 +- src/state/mobiusPools/hooks.ts | 2 +- src/state/mobiusPools/updater.ts | 31 +++++++++++++++++++++----- 6 files changed, 56 insertions(+), 26 deletions(-) diff --git a/src/components/earn/StablePoolCard.tsx b/src/components/earn/StablePoolCard.tsx index 3e10023035a..8405866c2b3 100644 --- a/src/components/earn/StablePoolCard.tsx +++ b/src/components/earn/StablePoolCard.tsx @@ -1,9 +1,10 @@ import QuestionHelper from 'components/QuestionHelper' import { ChainLogo, Coins } from 'constants/pools' import { useWeb3Context } from 'hooks' +import { useMobi } from 'hooks/Tokens' import { useValueOfExternalRewards } from 'hooks/useStablePools' import JSBI from 'jsbi' -import { calculateEstimatedWithdrawAmount, calculateVirtualPrice } from 'lib/calculator' +import { calculateVirtualPrice } from 'lib/calculator' import { Fraction, TokenAmount } from 'lib/token-utils' import { Meta } from 'pages/Pool' import { darken } from 'polished' @@ -152,6 +153,7 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => const [openWithdraw, setOpenWithdraw] = useState(false) const [openManage, setOpenManage] = useState(false) + const mobi = useMobi() const mobiPrice = useMobiPrice() const virtualPrice = calculateVirtualPrice(meta.exchangeInfo) @@ -167,7 +169,7 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => const totalDepositedValue = pegPrice ? totalDeposited.multiply(pegPrice) : new Fraction(0) - const mobiRate = meta.gauge?.weight.multiply(stakingInfo.mobiRate).asFraction ?? new Fraction(0) + const mobiRate = new TokenAmount(mobi, meta.gauge?.weight.multiply(stakingInfo.mobiRate).quotient ?? 0) const mobiRateValue = mobiPrice.multiply(mobiRate).multiply(BIG_INT_SECONDS_IN_YEAR) // const totalStakedAmount = totalValueDeposited @@ -212,7 +214,7 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => // } catch (e) { // console.error('Weekly apy overflow', e) // } - const balances = calculateEstimatedWithdrawAmount({ poolTokenAmount: meta.lpBalance, ...meta.exchangeInfo }) + const balances = meta.exchangeInfo.reserves // let userBalances: TokenAmount[] = [] // if (totalDeposited.greaterThan('0')) { @@ -232,9 +234,15 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => const totalDisplay = (amount: TokenAmount | Fraction): string => { const decimals = meta.display.peg.decimals - if (amount.lessThan(10 ** (2 - decimals))) return display(amount.toFixed(decimals + 1)) - else if (amount.lessThan(10 ** 6)) return display(amount.toFixed(decimals)) - else return display(amount.divide(10 ** 6).toFixed(2)) + if (amount.lessThan(10 ** (2 - decimals))) return display(amount.toFixed(decimals + 1, { groupSeparator: ',' })) + else if (amount.lessThan(10 ** 6) || openManage) return display(amount.toFixed(decimals, { groupSeparator: ',' })) + else + return display( + amount + .divide(10 ** 6) + .toFixed(2, { groupSeparator: ',' }) + .concat('M') + ) } return ( @@ -292,7 +300,7 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => Total deposited `${balance?.toFixed(meta.display.peg.decimals, { groupSeparator: ',' })} ${ @@ -309,7 +317,9 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => Weekly volume - {meta.volume.volume ? totalDisplay(new Fraction(meta.volume.volume?.week)) : 'Subgraph Syncing...'} + {meta.volume.volume + ? totalDisplay(new Fraction(Math.floor(meta.volume.volume?.week))) + : 'Subgraph Syncing...'} @@ -321,7 +331,7 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => {meta.volume.volume - ? totalDisplay(new Fraction(meta.volume.volume?.total)) + ? totalDisplay(new Fraction(Math.floor(meta.volume.volume?.total))) : 'Subgraph Syncing...'} diff --git a/src/constants/pools.ts b/src/constants/pools.ts index 138c8aba920..55cfcd1082a 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -177,12 +177,12 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { chain: Chain.Terra, peg: Dollar, pool: { - address: '0x9F4AdBD0af281C69a582eB2E6fa2A594D4204CAe', - lpToken: lp(ChainId.Mainnet, '0x9438e7281D7E3e99A9dD21e0EAd9c6a254e17ab2', 'Mobius cUSD/aUST LP'), + address: '0x9F4AdBD0af281C69a582eB2E6fa2A594D4204CAe'.toLowerCase(), + lpToken: lp(ChainId.Mainnet, '0x9438e7281D7E3e99A9dD21e0EAd9c6a254e17ab2'.toLowerCase(), 'Mobius cUSD/aUST LP'), tokens: [CUSD[ChainId.Mainnet], UST[ChainId.Mainnet]], }, gauge: { - address: '0x107F94409746E8c8E6eFF139A100D17D9ca7FdfE', + address: '0x107F94409746E8c8E6eFF139A100D17D9ca7FdfE'.toLowerCase(), additionalRewards: [new TokenAmount(CELO[CHAIN], '12000000000000000')], }, }, @@ -191,12 +191,12 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { chain: Chain.Ethereum, peg: Ether, pool: { - address: '0x74ef28D635c6C5800DD3Cd62d4c4f8752DaACB09', - lpToken: lp(ChainId.Mainnet, '0x4fF08e2a4E7114af4B575AeF9250144f95790982', 'Mobius cETH/wETH LP'), + address: '0x74ef28D635c6C5800DD3Cd62d4c4f8752DaACB09'.toLowerCase(), + lpToken: lp(ChainId.Mainnet, '0x4fF08e2a4E7114af4B575AeF9250144f95790982'.toLowerCase(), 'Mobius cETH/wETH LP'), tokens: [CETH[ChainId.Mainnet], WETH[ChainId.Mainnet]], }, gauge: { - address: '0x487c30CB18AA9Ced435911E2B414e0e85D7E52bB', + address: '0x487c30CB18AA9Ced435911E2B414e0e85D7E52bB'.toLowerCase(), additionalRewards: [], }, }, diff --git a/src/pages/Pool/index.tsx b/src/pages/Pool/index.tsx index 7b44589ef7a..e331b98095f 100644 --- a/src/pages/Pool/index.tsx +++ b/src/pages/Pool/index.tsx @@ -60,8 +60,8 @@ const HeaderLinks = styled(Row)` ` enum SpecialChain { - Other, - All, + Other = 'other', + All = 'all', } type SelectChain = SpecialChain | Chain @@ -82,9 +82,9 @@ export default function Pool() { const gauges = useAllGaugesInfo() const stakingInfo = useStakingInfo() const exchanges = usePools() - console.log(exchanges[0].lpTotalSupply.toString()) const lpBalances = useAllLpBalances() const volumes = usePoolsVolume() + console.log(volumes) const meta: Meta[] = StablePools[CHAIN].map((el, i) => { return { @@ -120,7 +120,6 @@ export default function Pool() { selection === pool.display.chain || (selection === SpecialChain.Other && OtherChains.has(pool.display.chain)) ) - return ( diff --git a/src/state/gauges/updater.ts b/src/state/gauges/updater.ts index 42dac3a10c8..3718d79aa53 100644 --- a/src/state/gauges/updater.ts +++ b/src/state/gauges/updater.ts @@ -83,7 +83,7 @@ export function GaugeUpdater() { return display.gauge === null ? null : { - isKilled: isKilled[0].result?.[0] === false, + isKilled: isKilled[0].result?.[0] === true, lastClaim: parseInt(lastClaims?.[i]?.result?.[0].toString() ?? '0'), weight: JSBI.BigInt(weights[i].result?.[0] ?? 0), futureWeight: JSBI.BigInt(futureWeights[i].result?.[0] ?? 0), diff --git a/src/state/mobiusPools/hooks.ts b/src/state/mobiusPools/hooks.ts index 569a7a5e056..b1774712753 100644 --- a/src/state/mobiusPools/hooks.ts +++ b/src/state/mobiusPools/hooks.ts @@ -42,7 +42,7 @@ export function useCurrentPoolVolume(exchangeAddress: string): Volume | null { } export function usePoolsVolume(): readonly Volume[] { - return useSelector((state) => state.pools.pools) + return useSelector((state) => state.pools.pools.map((p) => p as Volume)) } export function poolInfoToExchange(info: IExchangeInfo): IExchange { diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index 45bbb16ec78..afd382ac10b 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -18,6 +18,16 @@ import { updatePools } from './actions' const lpInterface = new Interface(LP.abi) const SwapInterface = new Interface(SWAP.abi) +function index(swaps: any[]): { [address: string]: any } { + return swaps.reduce((acc: { [address: string]: any }, cur: any) => { + return { ...acc, [cur.id.toLowerCase()]: cur } + }, {}) + + // pegQueries.reduce((acc, cur) => { + // return { ...acc, [cur]: (resp.data[cur]?.['usd'] as number).toString() } + // }, {}) +} + export function UpdatePools() { const blockNumber = useBlockNumber() const dispatch = useDispatch() @@ -29,8 +39,6 @@ export function UpdatePools() { const lpTotalSupply = useMultipleContractSingleData(lpTokenAddress, lpInterface, 'totalSupply') const balances = useMultipleContractSingleData(poolAddress, SwapInterface, 'getBalances') - const virtualPrices = useMultipleContractSingleData(poolAddress, SwapInterface, 'getVirtualPrice') - const query = gql` { swaps { @@ -47,19 +55,32 @@ export function UpdatePools() { } } ` - const { data, loading } = useQuery(query) + const { data, loading, error } = useQuery(query) useEffect(() => { // const inSubgraph: Set = // data?.swaps.reduce((accum: Set, cur: any) => new Set([...accum, cur.id]), new Set()) ?? new Set() + try { + if (error) console.log(error) + const volume = loading ? null : index(data.swaps) dispatch( updatePools({ pools: stablePools.map((displayPool, i) => { return { ...displayPool.pool, fees: RECOMMENDED_FEES, - volume: null, + volume: + volume && volume[displayPool.pool.address] + ? { + total: volume[displayPool.pool.address].dailyVolumes.reduce( + (accum: number, el: any) => accum + parseFloat(el.volume), + 0 + ), + day: parseFloat(volume[displayPool.pool.address].dailyVolumes[0]?.volume ?? '0'), + week: parseFloat(volume[displayPool.pool.address].weeklyVolumes[0]?.volume ?? '0'), + } + : null, ampFactor: RECOMMENDED_AMP, lpTotalSupply: new TokenAmount( displayPool.pool.lpToken, @@ -78,6 +99,6 @@ export function UpdatePools() { } catch (error) { console.error(error) } - }, [dispatch, stablePools, lpTotalSupply, blockNumber, balances]) + }, [dispatch, stablePools, lpTotalSupply, blockNumber, balances, error, loading, data.swaps]) return null } From 66edff039841851d5c6c23690b2cc95b9a840979 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 1 Mar 2022 14:20:39 -0500 Subject: [PATCH 56/72] fix apy: --- src/components/earn/StablePoolCard.tsx | 4 ++-- src/pages/Pool/index.tsx | 1 - src/state/application/hooks.ts | 7 +++++++ src/state/mobiusPools/updater.ts | 4 +--- src/utils/calcRate.ts | 7 +++++-- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/components/earn/StablePoolCard.tsx b/src/components/earn/StablePoolCard.tsx index 8405866c2b3..55acf49ed54 100644 --- a/src/components/earn/StablePoolCard.tsx +++ b/src/components/earn/StablePoolCard.tsx @@ -12,7 +12,7 @@ import React, { useState } from 'react' import { isMobile } from 'react-device-detect' import { useHistory } from 'react-router' import { NavLink } from 'react-router-dom' -import { useMobiPrice, useTokenPrice } from 'state/application/hooks' +import { useMobiPrice, usePegPrice } from 'state/application/hooks' import { StakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { calcRates } from 'utils/calcRate' @@ -165,7 +165,7 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => virtualPrice?.multiply(meta.lpBalance.asFraction.add(meta.userGauge?.balance ?? JSBI.BigInt(0))) ?? new TokenAmount(meta.display.pool.lpToken, 0) - const pegPrice = useTokenPrice(meta.display.peg.priceQuery ?? undefined) + const pegPrice = usePegPrice(meta.display.peg.priceQuery) const totalDepositedValue = pegPrice ? totalDeposited.multiply(pegPrice) : new Fraction(0) diff --git a/src/pages/Pool/index.tsx b/src/pages/Pool/index.tsx index e331b98095f..cb638cc4320 100644 --- a/src/pages/Pool/index.tsx +++ b/src/pages/Pool/index.tsx @@ -84,7 +84,6 @@ export default function Pool() { const exchanges = usePools() const lpBalances = useAllLpBalances() const volumes = usePoolsVolume() - console.log(volumes) const meta: Meta[] = StablePools[CHAIN].map((el, i) => { return { diff --git a/src/state/application/hooks.ts b/src/state/application/hooks.ts index ca6c5142b66..ffa35aaf470 100644 --- a/src/state/application/hooks.ts +++ b/src/state/application/hooks.ts @@ -104,6 +104,13 @@ export function useTokenPrice(address: string | undefined): Fraction | undefined return priceStringToFraction(prices[address]) } +export function usePegPrice(query: string | null): Fraction | undefined { + const prices = useTokenPrices() + if (query === null) return new Fraction(1) + + return priceStringToFraction(prices[query]) +} + export function useMobiPrice(): Fraction { const mobi = useMobi() const prices = useTokenPrices() diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index afd382ac10b..b556d73ea1f 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -56,11 +56,9 @@ export function UpdatePools() { } ` const { data, loading, error } = useQuery(query) - useEffect(() => { // const inSubgraph: Set = // data?.swaps.reduce((accum: Set, cur: any) => new Set([...accum, cur.id]), new Set()) ?? new Set() - try { if (error) console.log(error) const volume = loading ? null : index(data.swaps) @@ -99,6 +97,6 @@ export function UpdatePools() { } catch (error) { console.error(error) } - }, [dispatch, stablePools, lpTotalSupply, blockNumber, balances, error, loading, data.swaps]) + }, [dispatch, stablePools, lpTotalSupply, blockNumber, balances, error, loading, data]) return null } diff --git a/src/utils/calcRate.ts b/src/utils/calcRate.ts index a3884850300..bb8d154c91f 100644 --- a/src/utils/calcRate.ts +++ b/src/utils/calcRate.ts @@ -12,6 +12,9 @@ type Rates = { export function calcRates(rewardPerYear: Fraction, totalStakedAmount: Fraction): Rates { const apr = !totalStakedAmount.equalTo(0) ? rewardPerYear.divide(totalStakedAmount) : new Fraction(0) const dpr = apr.divide(365) - const apy = new Fraction(JSBI.exponentiate(dpr.add(1).multiply(weiScale).quotient, JSBI.BigInt(364)), weiScale) - return { apr, dpr, apy } + const apy = new Fraction( + JSBI.exponentiate(dpr.add(1).multiply(weiScale).quotient, JSBI.BigInt(364)), + JSBI.exponentiate(weiScale, JSBI.BigInt(364)) + ) + return { apr: apr.multiply(100), dpr: dpr.multiply(100), apy: apy.subtract(1).multiply(100) } } From 7282b8322144793b292a619549290301298fcb78 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 1 Mar 2022 14:42:36 -0500 Subject: [PATCH 57/72] deposit and withdraw --- src/components/earn/DepositModal.tsx | 19 +++++---- src/components/earn/StablePoolCard.tsx | 53 ++------------------------ 2 files changed, 15 insertions(+), 57 deletions(-) diff --git a/src/components/earn/DepositModal.tsx b/src/components/earn/DepositModal.tsx index f8e041611be..81c927400ef 100644 --- a/src/components/earn/DepositModal.tsx +++ b/src/components/earn/DepositModal.tsx @@ -8,6 +8,7 @@ import React, { useMemo, useState } from 'react' import { tryParseAmount } from 'state/swap/hooks' import styled from 'styled-components' +import { BIPS_BASE, weiScale } from '../../constants' import { useWeb3Context } from '../../hooks' import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback' import { useStableSwapContract } from '../../hooks/useContract' @@ -80,7 +81,7 @@ export default function DepositModal({ isOpen, onDismiss, meta }: DepositModalPr ? sumAmount.subtract(adjustedExpectedAmount) : adjustedExpectedAmount.subtract(sumAmount) - const perDiff = sumAmount.equalTo(0) ? new Fraction(0) : diff.divide(sumAmount) + const perDiff = sumAmount.equalTo(0) ? new Fraction(0) : diff.divide(sumAmount).multiply(BIPS_BASE) const decimalPlacesForLP = expectedAmounts.mintAmount.greaterThan(1) ? 2 @@ -88,7 +89,7 @@ export default function DepositModal({ isOpen, onDismiss, meta }: DepositModalPr ? 10 : 2 - const expectAmountWithSlippage = expectedAmounts.mintAmount.multiply(0.9) + const expectAmountWithSlippage = expectedAmounts.mintAmount.multiply(98).divide(100).multiply(weiScale) const approvals = [ useApproveCallback(inputTokens[0], meta.display.pool.address), useApproveCallback(inputTokens[1], meta.display.pool.address), @@ -109,9 +110,11 @@ export default function DepositModal({ isOpen, onDismiss, meta }: DepositModalPr async function onDeposit() { if (stakingContract && deadline) { setAttempting(true) + console.log(1) const tokenAmounts = inputTokens.map((el) => el.raw.toString()) + console.log(2, tokenAmounts) await stakingContract - .addLiquidity(tokenAmounts, expectAmountWithSlippage.toString(), deadline, { gasLimit: 10000000 }) + .addLiquidity(tokenAmounts, expectAmountWithSlippage.quotient.toString(), deadline, { gasLimit: 10000000 }) .then((response: TransactionResponse) => { addTransaction(response, { summary: `Deposit Liquidity into ${meta.display.name}`, @@ -207,15 +210,15 @@ export default function DepositModal({ isOpen, onDismiss, meta }: DepositModalPr Equivalent to: {display(adjustedExpectedAmount.toFixed(4))} )} - {toApprove.length > 0 && expectedAmounts.mintAmount.greaterThan('0') && ( + {toApprove.includes(true) && expectedAmounts.mintAmount.greaterThan('0') && (
{toApprove.map( (el, i) => @@ -237,7 +240,7 @@ export default function DepositModal({ isOpen, onDismiss, meta }: DepositModalPr )}
)} - {toApprove.length === 0 && ( + {!toApprove.includes(true) && expectedAmounts.mintAmount.greaterThan('0') && ( {error ?? 'Deposit'} diff --git a/src/components/earn/StablePoolCard.tsx b/src/components/earn/StablePoolCard.tsx index 55acf49ed54..f3fc97389ac 100644 --- a/src/components/earn/StablePoolCard.tsx +++ b/src/components/earn/StablePoolCard.tsx @@ -3,7 +3,6 @@ import { ChainLogo, Coins } from 'constants/pools' import { useWeb3Context } from 'hooks' import { useMobi } from 'hooks/Tokens' import { useValueOfExternalRewards } from 'hooks/useStablePools' -import JSBI from 'jsbi' import { calculateVirtualPrice } from 'lib/calculator' import { Fraction, TokenAmount } from 'lib/token-utils' import { Meta } from 'pages/Pool' @@ -161,9 +160,10 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => const totalDeposited = virtualPrice?.multiply(meta.exchangeInfo.lpTotalSupply) ?? new TokenAmount(meta.display.pool.lpToken, 0) - const userDeposited = - virtualPrice?.multiply(meta.lpBalance.asFraction.add(meta.userGauge?.balance ?? JSBI.BigInt(0))) ?? - new TokenAmount(meta.display.pool.lpToken, 0) + const userDeposited = new TokenAmount( + meta.display.pool.lpToken, + virtualPrice?.multiply(meta.lpBalance.asFraction.add(meta.userGauge?.balance ?? 0)).quotient ?? 0 + ) const pegPrice = usePegPrice(meta.display.peg.priceQuery) @@ -172,59 +172,14 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => const mobiRate = new TokenAmount(mobi, meta.gauge?.weight.multiply(stakingInfo.mobiRate).quotient ?? 0) const mobiRateValue = mobiPrice.multiply(mobiRate).multiply(BIG_INT_SECONDS_IN_YEAR) - // const totalStakedAmount = totalValueDeposited - // ? totalValueDeposited.multiply(new Fraction(coinPrice?.numerator ?? '1', coinPrice?.denominator ?? '1')) - // : new Fraction(JSBI.BigInt(0)) - // const totalMobiRate = new TokenAmount(mobi, mobiRate ?? JSBI.BigInt('0')) - - // const rewardPerYear = priceOfMobi.raw.multiply(totalMobiRate.multiply(BIG_INT_SECONDS_IN_YEAR)) const externalRewardValue = useValueOfExternalRewards(meta.display.gauge).multiply(BIG_INT_SECONDS_IN_YEAR) - // let rewardPerYearExternal = new Fraction('0', '1') - // for (let i = 0; i < 8; i++) { - // const rate = poolInfo.externalRewardRates?.[i] ?? totalMobiRate - // const priceOfToken = - // tokenPrices[rate.token.address.toLowerCase()] ?? tokenPrices['0x00be915b9dcf56a3cbe739d9b9c202ca692409ec'] - // if (poolInfo.externalRewardRates && i < poolInfo.externalRewardRates.length) { - // rewardPerYearExternal = rewardPerYearExternal.add( - // priceOfToken?.multiply(rate.multiply(BIG_INT_SECONDS_IN_YEAR)) ?? '0' - // ) - // } - // } // TODO: investigate if this is the right method const { apr, dpr, apy } = calcRates(mobiRateValue.add(externalRewardValue), totalDepositedValue) const { apr: boostedApr } = calcRates(mobiRateValue.add(externalRewardValue), totalDepositedValue) - // const [boostedApyFraction, boostedApy, boostedDpy] = - // mobiRate && totalStakedAmount && !totalStakedAmount.equalTo(JSBI.BigInt(0)) - // ? calcApy( - // rewardPerYear.multiply(new Fraction(JSBI.BigInt(5), JSBI.BigInt(2))).add(rewardPerYearExternal), - // totalStakedAmount - // ) - // : [new Fraction('0', '1'), new Fraction('0', '1'), new Fraction('0', '1')] - - // let weeklyAPY: React.ReactNode | undefined = <>🤯 - // try { - // weeklyAPY = apy - // ? new Percent( - // Math.floor(parseFloat(apy.divide('52').add('1').toFixed(10)) ** 52 * 1_000_000 - 1_000_000).toFixed(0), - // '1000000' - // ).toFixed(0, { groupSeparator: ',' }) - // : undefined - // } catch (e) { - // console.error('Weekly apy overflow', e) - // } const balances = meta.exchangeInfo.reserves - // let userBalances: TokenAmount[] = [] - // if (totalDeposited.greaterThan('0')) { - // userBalances = balances.map((amount) => { - // const fraction = new Fraction(userLP ? userLP.raw : JSBI.BigInt(0), totalDeposited.raw) - // const ratio = fraction.multiply(amount.raw) - // return new TokenAmount(amount.currency, JSBI.divide(ratio.numerator, ratio.denominator)) - // }) - // } - const poolColor = usePoolColor(meta.display) const display = (str: string): string => { From c0f04f90055c23e8a57184a1893abdb48881434e Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 1 Mar 2022 14:46:23 -0500 Subject: [PATCH 58/72] price fix --- src/components/earn/DepositModal.tsx | 12 ------------ src/hooks/useExternalStakingRewards.ts | 6 ++---- src/hooks/useStablePools.ts | 2 +- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/src/components/earn/DepositModal.tsx b/src/components/earn/DepositModal.tsx index 81c927400ef..5db0b134262 100644 --- a/src/components/earn/DepositModal.tsx +++ b/src/components/earn/DepositModal.tsx @@ -69,13 +69,6 @@ export default function DepositModal({ isOpen, onDismiss, meta }: DepositModalPr const virtualPrice = calculateVirtualPrice(meta.exchangeInfo) const adjustedExpectedAmount = expectedAmounts.mintAmount.multiply(virtualPrice ?? 1) - // const valueOfLP = new TokenAmount( - // poolInfo.lpToken, - // JSBI.divide( - // JSBI.multiply(expectedLPTokens.raw, poolInfo.virtualPrice), - // JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt('18')) - // ) - // ) const diff = sumAmount.greaterThan(adjustedExpectedAmount) ? sumAmount.subtract(adjustedExpectedAmount) @@ -132,10 +125,6 @@ export default function DepositModal({ isOpen, onDismiss, meta }: DepositModalPr if (!connected) { error = 'Connect Wallet' } - // TODO: try this - // if (!poolInfo?.stakedAmount) { - // error = error ?? 'Enter an amount' - // } const display = (str: string): string => { const peg = meta.display.peg @@ -194,7 +183,6 @@ export default function DepositModal({ isOpen, onDismiss, meta }: DepositModalPr setInput([...input.slice(0, i), val, ...input.slice(i + 1)]) } }} - // setUsingInsufficientFunds={setInsufficientFunds} /> {i !== inputTokens.length - 1 && ( diff --git a/src/hooks/useExternalStakingRewards.ts b/src/hooks/useExternalStakingRewards.ts index 5fa1e5adab7..adb3b13c946 100644 --- a/src/hooks/useExternalStakingRewards.ts +++ b/src/hooks/useExternalStakingRewards.ts @@ -1,11 +1,10 @@ import { ExternalRewardsToken } from 'constants/staking' import JSBI from 'jsbi' import { Percent, TokenAmount } from 'lib/token-utils' -import { useTokenPrice } from 'state/application/hooks' +import { useMobiPrice, useTokenPrice } from 'state/application/hooks' import { useStakingState, useStakingStateCombined } from 'state/staking/hooks' import { CHAIN } from '../constants' -import { useMobi } from './Tokens' const SECONDS_IN_YEAR = JSBI.BigInt(365 * 24 * 60 * 60) const SECONDS_IN_WEEK = JSBI.BigInt(7 * 24 * 60 * 60) @@ -22,9 +21,8 @@ export type ExternalUserRewardInfo = { export function useExternalStakingRewards(): ExternalRewardInfo { const stakingState = useStakingState() - const mobi = useMobi() const priceOfReward = useTokenPrice(ExternalRewardsToken[CHAIN].address) - const priceOfMobi = useTokenPrice(mobi?.address) + const priceOfMobi = useMobiPrice() const yearlyRate = JSBI.multiply(stakingState.externalRewardsRate, SECONDS_IN_YEAR) const avgApr = diff --git a/src/hooks/useStablePools.ts b/src/hooks/useStablePools.ts index 2dcb912184a..95a0c5de3ea 100644 --- a/src/hooks/useStablePools.ts +++ b/src/hooks/useStablePools.ts @@ -43,7 +43,7 @@ export function useValueOfAllLP(amounts: JSBI[]): Fraction { const pools = usePools() invariant(amounts.length === pools.length, 'invalid amounts entry') return StablePools[CHAIN].reduce((acc, cur, i) => { - const price = cur.peg.priceQuery ? priceStringToFraction(prices[cur.peg.priceQuery]) : new Fraction(0) + const price = cur.peg.priceQuery ? priceStringToFraction(prices[cur.peg.priceQuery]) : new Fraction(1) if (!price) return acc const virtualPrice = calculateVirtualPrice(pools[i]) From ff870af0a9f40a13de6b099241cdd580eca43dd8 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 1 Mar 2022 14:54:51 -0500 Subject: [PATCH 59/72] bug fix --- src/components/Header/URLWarning.tsx | 6 +++--- src/connectors/index.ts | 11 +++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/components/Header/URLWarning.tsx b/src/components/Header/URLWarning.tsx index a51e55a8d3e..9b2849ec0e6 100644 --- a/src/components/Header/URLWarning.tsx +++ b/src/components/Header/URLWarning.tsx @@ -25,9 +25,9 @@ export const StyledClose = styled(X)` ` const appURL: { [id in ChainId]: string } = { - [ChainId.MAINNET]: 'mobius.money', - [ChainId.ALFAJORES]: 'app-alfajores.mobius.money', - [ChainId.BAKLAVA]: 'app-baklava.mobius.money', + [ChainId.Mainnet]: 'mobius.money', + [ChainId.Alfajores]: 'app-alfajores.mobius.money', + [ChainId.Baklava]: 'app-baklava.mobius.money', } export default function URLWarning() { diff --git a/src/connectors/index.ts b/src/connectors/index.ts index 55aa9294c5c..a9c4c8b7658 100644 --- a/src/connectors/index.ts +++ b/src/connectors/index.ts @@ -1,11 +1,14 @@ -import { parseNetwork } from '@ubeswap/sdk' import { ChainId } from 'lib/token-utils' +function parseNetwork(chainId: number): ChainId { + return chainId === 62320 ? ChainId.Baklava : chainId === 44787 ? ChainId.Alfajores : ChainId.Mainnet +} + const networkChainIDFromHostname: ChainId = window.location.hostname.includes('alfajores') - ? ChainId.ALFAJORES + ? ChainId.Alfajores : window.location.hostname.includes('baklava') - ? ChainId.BAKLAVA - : ChainId.MAINNET + ? ChainId.Baklava + : ChainId.Mainnet export const NETWORK_CHAIN_ID: ChainId = process.env.REACT_APP_CHAIN_ID ? parseNetwork(parseInt(process.env.REACT_APP_CHAIN_ID)) From 3d514caabcc31578695c08f519152a8bf8b247a9 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Wed, 2 Mar 2022 09:59:45 -0500 Subject: [PATCH 60/72] charts still broken --- src/pages/Charts/index.tsx | 65 +++++++++++++++++++--------------- src/pages/Pool/index.tsx | 1 - src/state/mobiusPools/hooks.ts | 17 +++++++++ 3 files changed, 53 insertions(+), 30 deletions(-) diff --git a/src/pages/Charts/index.tsx b/src/pages/Charts/index.tsx index 90d2bd249ec..cc1a19a28ca 100644 --- a/src/pages/Charts/index.tsx +++ b/src/pages/Charts/index.tsx @@ -5,13 +5,19 @@ import Logo from 'components/Logo' import Row, { RowBetween, RowFixed } from 'components/Row' import Toggle from 'components/Toggle' import VolumeChart from 'components/VolumeChart' +import { ChainLogo, StablePools } from 'constants/pools' import useTheme from 'hooks/useTheme' import { useWindowSize } from 'hooks/useWindowSize' +import { Fraction } from 'lib/token-utils' import React, { useState } from 'react' import { isMobile } from 'react-device-detect' -import { usePools } from 'state/mobiusPools/hooks' +import { useTokenPrices } from 'state/application/hooks' +import { getCurrentDisplayAddress, getCurrentExchangeAddress } from 'state/mobiusPools/hooks' import styled from 'styled-components' import { Sel, TYPE } from 'theme' +import invariant from 'tiny-invariant' + +import { CHAIN } from '../../constants' const OuterContainer = styled.div` width: min(1280px, 100%); @@ -92,7 +98,7 @@ const granularityMapping: { [g in Granularity]: string } = { [Granularity.Week]: 'weeklyVolumes', } -const timeFormat: { [g: Granularity]: (n: number) => string } = { +const timeFormat: { [g in Granularity]: (n: number) => string } = { [Granularity.Hour]: (t: number) => new Date(t * 1000).toLocaleTimeString(), [Granularity.Day]: (t: number) => new Date(t * 1000).toLocaleDateString(), [Granularity.Week]: (t: number) => new Date(t * 1000).toLocaleDateString(), @@ -102,22 +108,23 @@ export default function Charts() { const { data, loading, error } = useQuery(volumeQuery) const [granularity, setGranularity] = useState(Granularity.Week) const [showTotal, setShowTotal] = useState(true) - const [selectedPools, setSelectedPools] = useState>({}) + const [selectedPools, setSelectedPools] = useState>({}) const [showPoolSelect, setShowPoolSelect] = useState(false) - const pools = usePools().slice() + const displayPools = StablePools[CHAIN] const { width } = useWindowSize() const theme = useTheme() + const prices = useTokenPrices() const totals = data - ? data.swaps.reduce((accum, info) => { - const price = - info.id === '0x19260b9b573569dDB105780176547875fE9fedA3'.toLowerCase() - ? PRICE[Coins.Bitcoin] - : info.id === '0xE0F2cc70E52f05eDb383313393d88Df2937DA55a'.toLowerCase() - ? PRICE[Coins.Ether] - : PRICE[Coins.USD] - info[granularityMapping[granularity]].forEach((vol, i) => { - accum[vol.timestamp] = price * parseInt(vol.volume) + (accum[vol.timestamp] ?? 0) + ? data.swaps.reduce((accum: { [timestamp: string]: number }, info: any) => { + const exchange = getCurrentDisplayAddress(info.id) + if (exchange === null) return accum + const price = exchange.peg.priceQuery !== null ? prices[exchange.peg.priceQuery] : new Fraction(1) + console.log(price.valueOf()) + + info[granularityMapping[granularity]].forEach((vol: any) => { + console.log(vol) + accum[vol.timestamp] = parseInt(price.toString()) * parseInt(vol.volume) + (accum[vol.timestamp] ?? 0) }) return accum }, {}) @@ -125,15 +132,16 @@ export default function Charts() { let dataAndLabels = data ? data.swaps - .filter(({ id }: { id: string }) => selectedPools[id]) - .sort((p1, p2) => { + .filter(({ id }: { id: string }) => selectedPools[id] !== null) + .sort((p1: any, p2: any) => { + invariant(selectedPools[p1.id] !== null && selectedPools[p2.id] !== null) if (selectedPools[p1.id] < selectedPools[p2.id]) return 1 if (selectedPools[p1.id] > selectedPools[p2.id]) return -1 return 0 }) - .map((info) => [ - getPoolName(pools, info.id), - info[granularityMapping[granularity]].map((vol) => ({ + .map((info: any) => [ + getCurrentExchangeAddress(info.id), + info[granularityMapping[granularity]].map((vol: any) => ({ x: parseInt(vol.timestamp), y: parseInt(vol.volume), })), @@ -143,8 +151,8 @@ export default function Charts() { dataAndLabels.push(['Total', Object.entries(totals).map(([time, vol]) => ({ x: time, y: vol }))]) } dataAndLabels = dataAndLabels.reverse() - const chartData = dataAndLabels.map((group) => group[1]) - const labels = dataAndLabels.map((group) => group[0]) + const chartData = dataAndLabels.map((group: any) => group[1]) + const labels = dataAndLabels.map((group: any) => group[0]) return ( @@ -181,24 +189,23 @@ export default function Charts() { setShowTotal(!showTotal)} /> - {pools - .sort((p1, p2) => p1.displayChain - p2.displayChain) - .filter(({ disabled }) => !disabled) + {displayPools + .sort((p1, p2) => p1.chain - p2.chain) .map((p) => ( - {' '} + {' '} {p.name} { - if (selectedPools[p.address.toLowerCase()]) { - setSelectedPools({ ...selectedPools, [p.address.toLowerCase()]: undefined }) + if (selectedPools[p.pool.address.toLowerCase()]) { + setSelectedPools({ ...selectedPools, [p.pool.address.toLowerCase()]: null }) } else { setSelectedPools({ ...selectedPools, - [p.address.toLowerCase()]: Object.keys(selectedPools).length + 1, + [p.pool.address.toLowerCase()]: Object.keys(selectedPools).length + 1, }) } }} @@ -213,7 +220,7 @@ export default function Charts() { diff --git a/src/pages/Pool/index.tsx b/src/pages/Pool/index.tsx index cb638cc4320..8730bea726a 100644 --- a/src/pages/Pool/index.tsx +++ b/src/pages/Pool/index.tsx @@ -84,7 +84,6 @@ export default function Pool() { const exchanges = usePools() const lpBalances = useAllLpBalances() const volumes = usePoolsVolume() - const meta: Meta[] = StablePools[CHAIN].map((el, i) => { return { display: el, diff --git a/src/state/mobiusPools/hooks.ts b/src/state/mobiusPools/hooks.ts index b1774712753..affa77ac5f3 100644 --- a/src/state/mobiusPools/hooks.ts +++ b/src/state/mobiusPools/hooks.ts @@ -19,6 +19,7 @@ export function useCurrentPool(token0: string, token1: string): IExchangeInfo | invariant(pools.length === 1) return pools[0] } + export function useCurrentPoolAddress(exchangeAddress: string): IExchangeInfo | null { const pools = useSelector((state) => state.pools.pools.filter((pool) => pool.address === exchangeAddress) @@ -28,6 +29,22 @@ export function useCurrentPoolAddress(exchangeAddress: string): IExchangeInfo | return pools[0] } +export function getCurrentExchangeAddress(exchangeAddress: string): IExchange | null { + const stablePools = StablePools[CHAIN] + const pools = stablePools.filter(({ pool }) => pool.address === exchangeAddress) + if (pools.length === 0) return null + invariant(pools.length === 1) + return pools[0].pool +} + +export function getCurrentDisplayAddress(exchangeAddress: string): DisplayPool | null { + const stablePools = StablePools[CHAIN] + const pools = stablePools.filter(({ pool }) => pool.address === exchangeAddress) + if (pools.length === 0) return null + invariant(pools.length === 1) + return pools[0] +} + export function usePools(): readonly IExchangeInfo[] { return useSelector((state) => state.pools.pools) } From a3ad7dc626da8ea5ae69068e715f53a8cedf0099 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 3 Mar 2022 11:52:04 -0500 Subject: [PATCH 61/72] manage page --- src/hooks/useColor.ts | 3 +- src/hooks/useExternalStakingRewards.ts | 3 +- src/pages/App.tsx | 2 +- src/pages/Pool/Manage.tsx | 608 +++++++++++-------------- src/state/gauges/hooks.ts | 8 +- src/state/mobiusPools/hooks.ts | 8 + 6 files changed, 295 insertions(+), 337 deletions(-) diff --git a/src/hooks/useColor.ts b/src/hooks/useColor.ts index 7769522390f..d333827ed39 100644 --- a/src/hooks/useColor.ts +++ b/src/hooks/useColor.ts @@ -67,8 +67,9 @@ export function generateColorPallete(tokens: Token[]) { return colors.join('\n') } -export function usePoolColor(pool: DisplayPool) { +export function usePoolColor(pool: DisplayPool | null) { const theme = useTheme() + if (pool === null) return null const coin = pool.peg.coin if (coin === Coins.USD) return theme.cusd if (coin === Coins.Eur) return theme.ceur diff --git a/src/hooks/useExternalStakingRewards.ts b/src/hooks/useExternalStakingRewards.ts index adb3b13c946..1e3533331c7 100644 --- a/src/hooks/useExternalStakingRewards.ts +++ b/src/hooks/useExternalStakingRewards.ts @@ -3,6 +3,7 @@ import JSBI from 'jsbi' import { Percent, TokenAmount } from 'lib/token-utils' import { useMobiPrice, useTokenPrice } from 'state/application/hooks' import { useStakingState, useStakingStateCombined } from 'state/staking/hooks' +import { calcRates } from 'utils/calcRate' import { CHAIN } from '../constants' @@ -27,7 +28,7 @@ export function useExternalStakingRewards(): ExternalRewardInfo { const avgApr = priceOfReward && priceOfMobi - ? calcApy(priceOfReward?.multiply(yearlyRate), priceOfMobi?.multiply(stakingState.totalVotingPower))[1] ?? + ? calcRates(priceOfReward?.multiply(yearlyRate), priceOfMobi?.multiply(stakingState.totalVotingPower)).apr ?? new Percent('0') : new Percent('0') diff --git a/src/pages/App.tsx b/src/pages/App.tsx index 26b5b83cd97..a09777cd5b5 100644 --- a/src/pages/App.tsx +++ b/src/pages/App.tsx @@ -124,7 +124,7 @@ export default function App() { - {' '} + {' '} diff --git a/src/pages/Pool/Manage.tsx b/src/pages/Pool/Manage.tsx index 93b3b6ab175..4b77701f535 100644 --- a/src/pages/Pool/Manage.tsx +++ b/src/pages/Pool/Manage.tsx @@ -1,25 +1,23 @@ import CurrencyPoolLogo from 'components/CurrencyPoolLogo' -import ExternalRewardsModal from 'components/earn/ClaimExternalRewardsModal' -import Loader from 'components/Loader' -import QuestionHelper from 'components/QuestionHelper' import { useMobi } from 'hooks/Tokens' import JSBI from 'jsbi' +import { calculateVirtualPrice } from 'lib/calculator' import { Fraction, TokenAmount } from 'lib/token-utils' import React, { useCallback, useState } from 'react' import { Link, RouteComponentProps } from 'react-router-dom' +import { usePegPrice } from 'state/application/hooks' +import { useGaugeInfo, useUserGaugeInfo } from 'state/gauges/hooks' +import { getCurrentDisplayFromGauge, useCurrentPoolAddress } from 'state/mobiusPools/hooks' +import { useStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' import { CountUp } from 'use-count-up' import { ButtonEmpty, ButtonPrimary } from '../../components/Button' import { AutoColumn } from '../../components/Column' -import ClaimRewardModal from '../../components/earn/ClaimRewardModal' -import StakingModal from '../../components/earn/StakingModal' import { CardNoise, CardSection, DataCard } from '../../components/earn/styled' -import UnstakingModal from '../../components/earn/UnstakingModal' import { AutoRow, RowBetween, RowFixed } from '../../components/Row' import { BIG_INT_SECONDS_IN_WEEK } from '../../constants' import { useWeb3Context } from '../../hooks' -import { useColor } from '../../hooks/useColor' import usePrevious from '../../hooks/usePrevious' import { useTokenBalance } from '../../state/wallet/hooks' import { TYPE } from '../../theme' @@ -43,15 +41,9 @@ const BottomSection = styled(AutoColumn)` position: relative; ` -const StyledDataCard = styled(DataCard)<{ bgColor?: any; showBackground?: any }>` - background: radial-gradient(76.02% 75.41% at 1.84% 0%, #1e1a31 0%, #3d51a5 100%); +const StyledDataCard = styled(DataCard)` + background: radial-gradient(50% 50% at 10% 10%, #35d07f 0%, #3488ec 180%); z-index: 2; - background: ${({ theme, bgColor, showBackground }) => - `radial-gradient(91.85% 100% at 1.84% 0%, ${bgColor} 0%, ${showBackground ? theme.black : theme.bg5} 100%) `}; - ${({ showBackground }) => - showBackground && - ` box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), - 0px 24px 32px rgba(0, 0, 0, 0.01);`} ` const StyledBottomCard = styled(DataCard)<{ dim: any }>` @@ -71,7 +63,7 @@ const PoolData = styled(DataCard)` ` const VoteCard = styled(DataCard)` - background: radial-gradient(76.02% 75.41% at 1.84% 0%, #27ae60 0%, #000000 100%); + background: radial-gradient(50% 50% at 10% 10%, #35d07f 0%, #3488ec 180%); overflow: hidden; ` @@ -98,94 +90,36 @@ const MS_IN_MINUTE = 1000 * 60 export default function Manage({ match: { - params: { poolName }, + params: { gaugeAddress }, }, -}: RouteComponentProps<{ poolName: string }>) { +}: RouteComponentProps<{ gaugeAddress: string }>) { const { connect, connected, address } = useWeb3Context() const mobi = useMobi() - const externalRewards = useExternalRewards({ address: poolName }) - console.log(externalRewards, poolName, 101) - + const stakingInfo = useStakingInfo() + const display = getCurrentDisplayFromGauge(gaugeAddress) + const gaugeInfo = useGaugeInfo(display?.gauge ?? undefined) + const userGaugeInfo = useUserGaugeInfo(display?.gauge ?? undefined) + const exchangeInfo = useCurrentPoolAddress(display?.pool.address ?? '') // get currencies and pair - const stakingInfo = useStablePoolInfoByName(poolName) - - const { balances, stakedAmount, totalStakedAmount, tokens, peggedTo, pegComesAfter, lastClaim } = stakingInfo ?? { - balances: [], - stakedAmount: undefined, - totalStakedAmount: undefined, - tokens: [], - } - - const nextClaimableTime = lastClaim?.valueOf() + MS_IN_HOUR - const minutesUntilRefresh = Math.max(0, (nextClaimableTime - Date.now()) / MS_IN_MINUTE) - - const earnedMobi = new TokenAmount(mobi, stakingInfo?.pendingMobi ?? '0') - - const { valueOfStaked, totalValueDeposited } = getDepositValues(stakingInfo) - - let userMobiRate = new TokenAmount(mobi, JSBI.BigInt('0')) - if ( - stakingInfo && - totalStakedAmount && - totalStakedAmount.greaterThan('0') && - stakingInfo?.workingPercentage.greaterThan('0') - ) { - userMobiRate = new TokenAmount( - mobi, - stakingInfo?.workingPercentage.multiply(stakingInfo?.mobiRate ?? '0').toFixed(0) ?? '0' - ) - } - let userExternalRates: TokenAmount[] = [] - if ( - connected && - stakingInfo && - stakingInfo.externalRewardRates && - totalStakedAmount && - totalStakedAmount.greaterThan('0') && - stakingInfo?.workingPercentage.greaterThan('0') - ) { - userExternalRates = stakingInfo.externalRewardRates.map( - (rate) => new TokenAmount(rate.token, stakingInfo.totalPercentage.multiply(rate.raw).toFixed(0)) - ) - } + // const stakingInfo = useStablePoolInfoByName(poolName) - const totalMobiRate = new TokenAmount(mobi, stakingInfo?.mobiRate ?? JSBI.BigInt('0')) + // const { balances, stakedAmount, totalStakedAmount, tokens, peggedTo, pegComesAfter, lastClaim } = stakingInfo ?? { + // balances: [], + // stakedAmount: undefined, + // totalStakedAmount: undefined, + // tokens: [], + // } - const userBalances = balances.map((amount) => { - const fraction = new Fraction(stakedAmount?.raw.toString() ?? '0', totalStakedAmount?.raw || JSBI.BigInt('0')) - const ratio = fraction.multiply(amount.raw) - - if (JSBI.equal(ratio.denominator, JSBI.BigInt('0'))) { - return new TokenAmount(amount.currency, JSBI.BigInt('0')) - } - return new TokenAmount(amount.currency, JSBI.divide(ratio.numerator, ratio.denominator)) - }) - - const decimalPlacesForLP = stakedAmount?.greaterThan('1') ? 6 : stakedAmount?.greaterThan('0') ? 12 : 2 - - // detect existing unstaked LP position to show add button if none found - const userLiquidityUnstaked = useTokenBalance(connected ? address : undefined, stakingInfo?.lpToken) - const showAddLiquidityButton = Boolean(stakingInfo?.stakedAmount?.equalTo('0') && userLiquidityUnstaked?.equalTo('0')) - - // toggle for staking modal and unstaking modal + const userLiquidityUnstaked = useTokenBalance(connected ? address : undefined, display?.pool.lpToken) const [showStakingModal, setShowStakingModal] = useState(false) const [showUnstakingModal, setShowUnstakingModal] = useState(false) const [showClaimRewardModal, setShowClaimRewardModal] = useState(false) const [showExternalRewardModal, setShowExternalRewardModal] = useState(false) + const pegPrice = usePegPrice(display?.peg.priceQuery ?? null) - // fade cards if nothing staked or nothing earned yet - const disableTop = !stakingInfo?.stakedAmount || stakingInfo.stakedAmount.equalTo(JSBI.BigInt(0)) - - const token = stakingInfo?.tokens[0] - const backgroundColor = useColor(token ?? undefined) - - // get CUSD value of staked LP tokens - - const mobiCountUpAmount = earnedMobi?.toFixed(6) ?? '0' + const mobiCountUpAmount = userGaugeInfo?.claimableMobi.toFixed(6) ?? '0' const mobiCountUpAmountPrevious = usePrevious(mobiCountUpAmount) ?? '0' - const countUpAmount = earnedMobi?.toFixed(6) ?? '0' - const countUpAmountPrevious = usePrevious(countUpAmount) ?? '0' const handleDepositClick = useCallback(() => { if (connected) { @@ -195,70 +129,111 @@ export default function Manage({ } }, [connect, connected]) + if (!display || !gaugeInfo || !userGaugeInfo || !exchangeInfo || !userLiquidityUnstaked || !display.gauge) return null + + const mobiRate = new TokenAmount(mobi, gaugeInfo.weight.multiply(stakingInfo.mobiRate).quotient ?? 0) + + const nextClaimableTime = gaugeInfo.lastClaim.valueOf() + MS_IN_HOUR + const minutesUntilRefresh = Math.max(0, (nextClaimableTime - Date.now()) / MS_IN_MINUTE) + + // const earnedMobi = new TokenAmount(mobi, stakingInfo?.pendingMobi ?? '0') + + const totalDeposited = exchangeInfo.lpTotalSupply + + const userDeposited = new TokenAmount(display.pool.lpToken, userGaugeInfo.balance) + const virtualPrice = calculateVirtualPrice(exchangeInfo) + const userDepositedValue = + pegPrice && virtualPrice ? virtualPrice.multiply(totalDeposited).multiply(pegPrice) : new Fraction(0) + + // const { valueOfStaked, totalValueDeposited } = getDepositValues(stakingInfo) + + const userMobiRate = new TokenAmount(mobi, mobiRate.multiply(userDeposited).divide(totalDeposited).quotient) + const userExternalRates = display.gauge.additionalRewards.map( + (reward) => new TokenAmount(reward.token, reward.multiply(userDeposited).divide(totalDeposited).quotient) + ) + // const userExternalRates: TokenAmount[] = [] + // if ( + // connected && + // stakingInfo && + // stakingInfo.externalRewardRates && + // totalStakedAmount && + // totalStakedAmount.greaterThan('0') && + // stakingInfo?.workingPercentage.greaterThan('0') + // ) { + // userExternalRates = stakingInfo.externalRewardRates.map( + // (rate) => new TokenAmount(rate.token, stakingInfo.totalPercentage.multiply(rate.raw).toFixed(0)) + // ) + // } + + // const totalMobiRate = new TokenAmount(mobi, stakingInfo?.mobiRate ?? JSBI.BigInt('0')) + + // const userBalances = balances.map((amount) => { + // const fraction = new Fraction(stakedAmount?.raw.toString() ?? '0', totalStakedAmount?.raw || JSBI.BigInt('0')) + // const ratio = fraction.multiply(amount.raw) + + // if (JSBI.equal(ratio.denominator, JSBI.BigInt('0'))) { + // return new TokenAmount(amount.currency, JSBI.BigInt('0')) + // } + // return new TokenAmount(amount.currency, JSBI.divide(ratio.numerator, ratio.denominator)) + // }) + + const decimalPlacesForLP = userDeposited.greaterThan('1') ? 6 : userDeposited.greaterThan('0') ? 12 : 2 + + // fade cards if nothing staked or nothing earned yet + const disableTop = userGaugeInfo.claimableMobi.equalTo(0) && userDeposited.equalTo(0) + + const format = (str: string): string => { + const peg = display.peg + return (peg.position === 'before' ? peg.symbol : '').concat(str).concat(peg.position === 'after' ? peg.symbol : '') + } + return ( - {!stakingInfo && } - {stakingInfo && ( - <> - - {stakingInfo.name} Liquidity Mining - - - - - - - Total deposits - - {totalValueDeposited - ? `${stakingInfo.pegComesAfter ? '' : stakingInfo.peggedTo}${ - totalValueDeposited.lessThan('1') - ? totalValueDeposited.toFixed(stakingInfo.displayDecimals, { - groupSeparator: ',', - }) - : totalValueDeposited.toFixed(stakingInfo.displayDecimals, { - groupSeparator: ',', - }) - } ${stakingInfo.pegComesAfter ? stakingInfo.peggedTo : ''}` - : '-'} - - - - - - Pool Rate - - {stakingInfo - ? totalMobiRate?.multiply(BIG_INT_SECONDS_IN_WEEK)?.toFixed(0, { groupSeparator: ',' }) ?? '-' - : '0'} - {' MOBI / week'} + <> + + {display.name} Liquidity Mining + + + + + + + Total deposits + + {format(totalDeposited.toFixed(display.peg.decimals, { groupSeparator: ',' }))} + + + + + + Pool Rate + + {mobiRate.multiply(BIG_INT_SECONDS_IN_WEEK)?.toFixed(0, { groupSeparator: ',' }) ?? '-'} + {' MOBI / week'} + + {display.gauge.additionalRewards.map((tokenRate) => ( + + {`${tokenRate?.multiply(BIG_INT_SECONDS_IN_WEEK)?.toFixed(0, { groupSeparator: ',' })} ${ + tokenRate.token.symbol + } / week`} - {stakingInfo && - stakingInfo.externalRewardRates && - stakingInfo.externalRewardRates.map((rate) => ( - - {`${rate?.multiply(BIG_INT_SECONDS_IN_WEEK)?.toFixed(0, { groupSeparator: ',' })} ${ - rate.token.symbol - } / week`} - - ))} - - - - - )} + ))} + + + + - {stakingInfo && showAddLiquidityButton && ( + {userDeposited.equalTo('0') && userLiquidityUnstaked.equalTo('0') && ( - Step 1. Get MOBI-LP Liquidity tokens + Step 1. Get MOBI-LP tokens - {`Mobi-LP tokens are required. Once you've added liquidity to the ${stakingInfo.name} pool you can stake your liquidity tokens on this page.`} + {`Mobi-LP tokens are required. Once you've added liquidity to the ${display.name} pool you can stake your liquidity tokens on this page.`} @@ -270,207 +245,176 @@ export default function Manage({ )} - {stakingInfo && ( - <> - setShowStakingModal(false)} - stakingInfo={stakingInfo} - userLiquidityUnstaked={userLiquidityUnstaked} - /> - setShowUnstakingModal(false)} - stakingInfo={stakingInfo} - /> - setShowClaimRewardModal(false)} - stakingInfo={stakingInfo} - /> - setShowExternalRewardModal(false)} - stakingInfo={stakingInfo} - /> - - )} - - {stakingInfo && ( - - - - - - - - Your staked liquidity deposits - - - - {stakingInfo?.stakedAmount?.toSignificant(decimalPlacesForLP) ?? '-'} - - - MOBI-LP {stakingInfo.tokens.map(({ symbol }) => symbol).join('-')} - - - {stakingInfo?.stakedAmount && stakingInfo.stakedAmount.greaterThan('0') && ( - - - - Current value:{' '} - {valueOfStaked - ? `${pegComesAfter ? '' : peggedTo}${valueOfStaked.toFixed(4, { - separator: ',', - })} ${pegComesAfter ? peggedTo : ''}` - : '--'} - - - `${balance?.toFixed(Math.min(decimalPlacesForLP, balance.token.decimals), { - groupSeparator: ',', - })} ${balance.token.symbol}` - ) - .join(', ')} - /> - - - )} - - - - + {/* <> + setShowStakingModal(false)} + stakingInfo={stakingInfo} + userLiquidityUnstaked={userLiquidityUnstaked} + /> + setShowUnstakingModal(false)} + stakingInfo={stakingInfo} + /> + setShowClaimRewardModal(false)} + stakingInfo={stakingInfo} + /> + setShowExternalRewardModal(false)} + stakingInfo={stakingInfo} + /> + */} + + + + + - + -
- Your unclaimed rewards -
- {earnedMobi && ( - - setShowClaimRewardModal(true)} - > - Claim MOBI - - - )} + Your staked liquidity deposits
- - - - - - ⚡ - - {stakingInfo - ? userMobiRate?.multiply(BIG_INT_SECONDS_IN_WEEK)?.toSignificant(4, { groupSeparator: ',' }) ?? - '-' - : '0'} - {' MOBI / week'} - + + {userDeposited.toSignificant(decimalPlacesForLP) ?? '-'} + + + MOBI-LP {display.pool.tokens.map(({ symbol }) => symbol).join('-')} + - {externalRewards && ( - <> - - - External rewards refresh once per hour - setShowExternalRewardModal(true)} - > - Claim External - - - - Next Refresh in {minutesUntilRefresh.toFixed(0)} minutes - - {externalRewards.map((reward, i) => ( - - - - - - - ⚡ - - {stakingInfo - ? userExternalRates?.[i] - ?.multiply(BIG_INT_SECONDS_IN_WEEK) - ?.toSignificant(4, { groupSeparator: ',' }) ?? '-' - : '0'} - {` ${stakingInfo.externalRewardRates?.[i].token.symbol} / week`} - - - ))} - + {userDeposited.greaterThan('0') && ( + + + + Current value: $ + {userDepositedValue.toFixed(4, { + groupSeparator: ',', + })} + + {/* + `${balance?.toFixed(Math.min(decimalPlacesForLP, balance.token.decimals), { + groupSeparator: ',', + })} ${balance.token.symbol}` + ) + .join(', ')} + /> */} + + )}
-
-
- {/* - - ⭐️ - - When you withdraw, the contract will automagically claim MOBI on your behalf! - */} - - {!showAddLiquidityButton && ( - - {stakingInfo && ( - - {stakingInfo?.stakedAmount?.greaterThan(JSBI.BigInt(0)) ? 'Deposit' : 'Deposit MOBI-LP Tokens'} - - )} - - {stakingInfo?.stakedAmount?.greaterThan(JSBI.BigInt(0)) && ( + + + + + + +
+ Your unclaimed rewards +
+ {userGaugeInfo.claimableMobi && ( + + setShowClaimRewardModal(true)} + > + Claim MOBI + + + )} +
+ + + + + + + ⚡ + + {stakingInfo + ? userMobiRate?.multiply(BIG_INT_SECONDS_IN_WEEK)?.toSignificant(4, { groupSeparator: ',' }) ?? '-' + : '0'} + {' MOBI / week'} + + + {display.gauge.additionalRewards.length > 0 && ( <> - setShowUnstakingModal(true)} - > - Withdraw - + + + External rewards refresh once per hour + setShowExternalRewardModal(true)} + > + Claim External + + + + Next Refresh in {minutesUntilRefresh.toFixed(0)} minutes + + {display.gauge.additionalRewards.map((rewardToken, i) => ( + + + {rewardToken.toFixed(4, { groupSeparator: ',' })} + + + + ⚡ + + {stakingInfo + ? userExternalRates?.[i] + ?.multiply(BIG_INT_SECONDS_IN_WEEK) + ?.toSignificant(4, { groupSeparator: ',' }) ?? '-' + : '0'} + {` ${rewardToken.token.symbol} / week`} + + + ))} )} - {/* {stakingInfo && !stakingInfo.active && ( - - Staking Rewards inactive for this pair. - - )} */} -
+
+ + + + {!userLiquidityUnstaked.equalTo('0') && ( + + Deposit + )} - {!userLiquidityUnstaked ? null : userLiquidityUnstaked.equalTo('0') ? null : !stakingInfo ? null : ( - {userLiquidityUnstaked.toSignificant(6)} MOBI LP tokens available + + {!userDeposited.equalTo('0') && ( + <> + setShowUnstakingModal(true)}> + Withdraw + + )} - - )} + + {!userLiquidityUnstaked.equalTo('0') && ( + {userLiquidityUnstaked.toSignificant(6)} MOBI LP tokens available + )} +
) } diff --git a/src/state/gauges/hooks.ts b/src/state/gauges/hooks.ts index f346f29feb2..38b324a3856 100644 --- a/src/state/gauges/hooks.ts +++ b/src/state/gauges/hooks.ts @@ -71,7 +71,10 @@ export function useGaugeInfo(gauge: IGauge | undefined): GaugeInfo | undefined { if (!gauge) return undefined const gaugeInfo = gauges - .filter((g, i) => !StablePools[CHAIN][i].gauge && (StablePools[CHAIN][i].gauge?.address === gauge.address ?? false)) + .filter( + (g, i) => + StablePools[CHAIN][i].gauge && (StablePools[CHAIN][i].gauge?.address === gauge.address.toLowerCase() ?? false) + ) .map((g) => !g ? null @@ -95,7 +98,8 @@ export function useUserGaugeInfo(gauge: IGauge | undefined): UserGaugeInfo | und const gaugeInfo = gauges .filter( - (ug, i) => !StablePools[CHAIN][i].gauge && (StablePools[CHAIN][i].gauge?.address === gauge.address ?? false) + (ug, i) => + StablePools[CHAIN][i].gauge && (StablePools[CHAIN][i].gauge?.address === gauge.address.toLowerCase() ?? false) ) .map((ug) => !ug diff --git a/src/state/mobiusPools/hooks.ts b/src/state/mobiusPools/hooks.ts index affa77ac5f3..030c537c078 100644 --- a/src/state/mobiusPools/hooks.ts +++ b/src/state/mobiusPools/hooks.ts @@ -78,6 +78,14 @@ export function poolInfoToDisplay(info: IExchangeInfo): DisplayPool { return exchange[0] } +export function getCurrentDisplayFromGauge(gaugeAddress: string): DisplayPool | null { + const stablePools = StablePools[CHAIN] + const pools = stablePools.filter((pool) => pool.gauge?.address === gaugeAddress) + if (pools.length === 0) return null + invariant(pools.length === 1) + return pools[0] +} + export function useLpBalance(exchange: IExchange): TokenAmount { const { address, connected } = useWeb3Context() const balance = useTokenBalance(address, exchange.lpToken) From bd349b7f282cfdb290aa01e170555608e672f838 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 3 Mar 2022 12:21:31 -0500 Subject: [PATCH 62/72] staking modal --- src/components/earn/StakingModal.tsx | 176 ++++++++++++++++++++------- src/pages/Pool/Manage.tsx | 14 ++- 2 files changed, 140 insertions(+), 50 deletions(-) diff --git a/src/components/earn/StakingModal.tsx b/src/components/earn/StakingModal.tsx index 58c361eeaa8..24b48ce21ea 100644 --- a/src/components/earn/StakingModal.tsx +++ b/src/components/earn/StakingModal.tsx @@ -1,8 +1,14 @@ import { TransactionResponse } from '@ethersproject/providers' +import CurrencyLogo from 'components/CurrencyLogo' import Loader from 'components/Loader' +import NumericalInput from 'components/NumericalInput' +import { useWeb3Context } from 'hooks' import { useMobi } from 'hooks/Tokens' +import JSBI from 'jsbi' import { Token, TokenAmount } from 'lib/token-utils' import React, { useCallback, useState } from 'react' +import { tryParseAmount } from 'state/swap/hooks' +import { useTokenBalance } from 'state/wallet/hooks' import styled from 'styled-components' import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback' @@ -10,10 +16,8 @@ import { useLiquidityGaugeContract } from '../../hooks/useContract' import useTransactionDeadline from '../../hooks/useTransactionDeadline' import { useTransactionAdder } from '../../state/transactions/hooks' import { CloseIcon, TYPE } from '../../theme' -import { maxAmountSpend } from '../../utils/maxAmountSpend' import { ButtonConfirmed, ButtonError } from '../Button' import { AutoColumn } from '../Column' -import CurrencyInputPanel from '../CurrencyInputPanel' import Modal from '../Modal' import { LoadingView, SubmittedView } from '../ModalViews' import ProgressCircles from '../ProgressSteps' @@ -37,31 +41,45 @@ const ContentWrapper = styled(AutoColumn)` interface StakingModalProps { isOpen: boolean onDismiss: () => void - stakingInfo: StablePoolInfo - userLiquidityUnstaked: TokenAmount | undefined + userDeposited: TokenAmount + totalDeposited: TokenAmount + userLiquidityUnstaked: TokenAmount + gaugeAddress: string + mobiRate: TokenAmount } const calcNewRewardRate = (totalMobiRate: JSBI, totalStaked: JSBI, stakedByUser: JSBI, token: Token) => new TokenAmount(token, JSBI.multiply(totalMobiRate, JSBI.divide(stakedByUser, totalStaked))) -export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiquidityUnstaked }: StakingModalProps) { +export default function StakingModal({ + isOpen, + onDismiss, + userDeposited, + totalDeposited, + userLiquidityUnstaked, + gaugeAddress, + mobiRate, +}: StakingModalProps) { const addTransaction = useTransactionAdder() const mobi = useMobi() + const { connected } = useWeb3Context() // track and parse user input const [typedValue, setTypedValue] = useState('') - const { parsedAmount, error } = useDerivedStakeInfo(typedValue, stakingInfo.lpToken, userLiquidityUnstaked) - const parsedAmountWrapped = parsedAmount + + const inputAmount = tryParseAmount(typedValue, userDeposited.token) + // const { parsedAmount, error } = useDerivedStakeInfo(typedValue, stakingInfo.lpToken, userLiquidityUnstaked) + // const parsedAmountWrapped = parsedAmount let hypotheticalMobiRewardRate: TokenAmount = new TokenAmount(mobi, '0') - if (parsedAmountWrapped?.greaterThan('0')) { - if (stakingInfo.totalStakedAmount && stakingInfo.totalStakedAmount.equalTo('0')) { - hypotheticalMobiRewardRate = new TokenAmount(mobi, stakingInfo.mobiRate) + if (inputAmount?.greaterThan('0')) { + if (totalDeposited.equalTo('0')) { + hypotheticalMobiRewardRate = mobiRate } else { hypotheticalMobiRewardRate = calcNewRewardRate( - stakingInfo.mobiRate, - JSBI.add(stakingInfo.totalStakedAmount?.raw, parsedAmountWrapped.raw), - JSBI.add(stakingInfo.stakedAmount.raw, parsedAmountWrapped.raw), + mobiRate.raw, + JSBI.add(totalDeposited.raw, inputAmount.raw), + JSBI.add(userDeposited.raw, inputAmount.raw), mobi ) } @@ -78,16 +96,16 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui // approval data for stake const deadline = useTransactionDeadline() - const [approval, approveCallback] = useApproveCallback(parsedAmount, stakingInfo.gaugeAddress) + const [approval, approveCallback] = useApproveCallback(inputAmount, gaugeAddress) - const stakingContract = useLiquidityGaugeContract(stakingInfo.gaugeAddress) + const stakingContract = useLiquidityGaugeContract(gaugeAddress) const depositFunction = stakingContract?.['deposit(uint256)'] async function onStake() { setAttempting(true) - if (stakingContract && parsedAmount && deadline) { + if (stakingContract && inputAmount && deadline && depositFunction) { if (approval === ApprovalState.APPROVED) { - await depositFunction(parsedAmount.raw.toString(), { gasLimit: 10000000 }).then( + await depositFunction(inputAmount.raw.toString(), { gasLimit: 10000000 }).then( (response: TransactionResponse) => { addTransaction(response, { summary: `Stake deposited liquidity`, @@ -102,23 +120,13 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui } } - // wrapped onUserInput to clear signatures - const onUserInput = useCallback((typedValue: string) => { - setTypedValue(typedValue) - }, []) - - // used for max input button - const maxAmountInput = maxAmountSpend(userLiquidityUnstaked) - const atMaxAmount = Boolean(maxAmountInput && parsedAmount?.equalTo(maxAmountInput)) - const handleMax = useCallback(() => { - maxAmountInput && onUserInput(maxAmountInput.toExact()) - }, [maxAmountInput, onUserInput]) + let error: string | undefined + if (!connected) { + error = 'Connect Wallet' + } async function onAttemptToApprove() { if (!deadline) throw new Error('missing dependencies') - const liquidityAmount = parsedAmount - if (!liquidityAmount) throw new Error('missing liquidity amount') - approveCallback() } @@ -130,17 +138,7 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui Deposit - +
@@ -174,7 +172,7 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui {error ?? 'Deposit'} @@ -187,7 +185,7 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui Depositing Liquidity - {parsedAmount?.toSignificant(4)} MOBI LP + {inputAmount?.toSignificant(4)} MOBI LP )} @@ -195,10 +193,98 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui Transaction Submitted - Deposited {parsedAmount?.toSignificant(4)} MOBI LP + Deposited {inputAmount?.toSignificant(4)} MOBI LP )} ) } + +type CurrencyRowProps = { + tokenAmount: TokenAmount + setInput: (amount: string) => void + input: string +} + +const InputRow = styled.div` + ${({ theme }) => theme.flexRowNoWrap}; + align-items: center; + justify-content: space-between; + padding: 0.75rem 0.75rem 0.75rem 1rem; +` + +const InputDiv = styled.div` + display: flex; + min-width: 40%; +` + +const Aligner = styled.span` + display: flex; + align-items: center; + justify-content: space-between; +` + +const StyledTokenName = styled.span<{ active?: boolean }>` + ${({ active }) => (active ? ' margin: 0 0.25rem 0 0.75rem;' : ' margin: 0 0.25rem 0 0.25rem;')} + font-size: ${({ active }) => (active ? '20px' : '16px')}; + color: ${({ theme }) => theme.text1}; +` +const BalanceText = styled(TYPE.subHeader)` + cursor: pointer; +` + +const CurrencyRow = ({ tokenAmount, setInput, input }: CurrencyRowProps) => { + const { address, connected } = useWeb3Context() + const mobi = useMobi() + const currency = tokenAmount.token + const tokenBalance = useTokenBalance(connected ? address : undefined, currency ?? undefined) + + const decimalPlacesForBalance = tokenBalance?.greaterThan( + '1' //JSBI.exponentiate(JSBI.BigInt('10'), JSBI.BigInt(tokenBalance.token.decimals - 2)).toString() + ) + ? 2 + : tokenBalance?.greaterThan('0') + ? 6 + : 2 + + const mainRow = ( + +
+ + + + {(currency && currency.symbol && currency.symbol.length > 20 + ? currency.symbol.slice(0, 4) + + '...' + + currency.symbol.slice(currency.symbol.length - 5, currency.symbol.length) + : currency?.symbol) || ''} + + +
+ + { + setInput(val) + }} + /> + +
+ ) + const balanceRow = ( +
+ setInput(tokenBalance?.toFixed(5) ?? '')}> + Balance: {tokenBalance?.toFixed(decimalPlacesForBalance) ?? 'Loading...'} + +
+ ) + + return ( +
+ {balanceRow} + {mainRow} +
+ ) +} diff --git a/src/pages/Pool/Manage.tsx b/src/pages/Pool/Manage.tsx index 4b77701f535..5cf233f8b96 100644 --- a/src/pages/Pool/Manage.tsx +++ b/src/pages/Pool/Manage.tsx @@ -1,4 +1,5 @@ import CurrencyPoolLogo from 'components/CurrencyPoolLogo' +import StakingModal from 'components/earn/StakingModal' import { useMobi } from 'hooks/Tokens' import JSBI from 'jsbi' import { calculateVirtualPrice } from 'lib/calculator' @@ -245,14 +246,17 @@ export default function Manage({ )} - {/* <> + <> setShowStakingModal(false)} - stakingInfo={stakingInfo} + userDeposited={userDeposited} + totalDeposited={totalDeposited} userLiquidityUnstaked={userLiquidityUnstaked} + gaugeAddress={display.gauge.address} + mobiRate={mobiRate} /> - setShowUnstakingModal(false)} stakingInfo={stakingInfo} @@ -266,8 +270,8 @@ export default function Manage({ isOpen={showExternalRewardModal} onDismiss={() => setShowExternalRewardModal(false)} stakingInfo={stakingInfo} - /> - */} + /> */} + From 4e06f27dd80c53355d9828758a2d77c42323f709 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 7 Mar 2022 13:20:04 -0500 Subject: [PATCH 63/72] claim mobi modal --- src/components/earn/ClaimRewardModal.tsx | 63 +++++++----------------- src/pages/Pool/Manage.tsx | 13 +++-- 2 files changed, 27 insertions(+), 49 deletions(-) diff --git a/src/components/earn/ClaimRewardModal.tsx b/src/components/earn/ClaimRewardModal.tsx index b22d3a084cb..df65fcbee81 100644 --- a/src/components/earn/ClaimRewardModal.tsx +++ b/src/components/earn/ClaimRewardModal.tsx @@ -1,12 +1,10 @@ import { TransactionResponse } from '@ethersproject/providers' -import { useMobi } from 'hooks/Tokens' -import { TokenAmount } from 'lib/token-utils' -import React, { useEffect, useState } from 'react' -import { useBlockNumber } from 'state/application/hooks' +import React, { useCallback, useState } from 'react' +import { UserGaugeInfo } from 'state/gauges/hooks' import styled from 'styled-components' import { useWeb3Context } from '../../hooks' -import { useLiquidityGaugeContract, useMobiMinterContract } from '../../hooks/useContract' +import { useMobiMinterContract } from '../../hooks/useContract' import { useTransactionAdder } from '../../state/transactions/hooks' import { CloseIcon, TYPE } from '../../theme' import { ButtonError } from '../Button' @@ -23,12 +21,12 @@ const ContentWrapper = styled(AutoColumn)` interface StakingModalProps { isOpen: boolean onDismiss: () => void - stakingInfo: StablePoolInfo + userGaugeInfo: UserGaugeInfo + gaugeAddress: string } -export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: StakingModalProps) { - const { address, connected } = useWeb3Context() - const mobi = useMobi() +export default function ClaimRewardModal({ isOpen, onDismiss, userGaugeInfo, gaugeAddress }: StakingModalProps) { + const { connected } = useWeb3Context() // monitor call to help UI loading state const addTransaction = useTransactionAdder() @@ -41,26 +39,13 @@ export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: Sta onDismiss() } - const stakingContract = useLiquidityGaugeContract(stakingInfo.gaugeAddress) const minter = useMobiMinterContract() - const [pendingMobi, setEarnedMobi] = useState() - - const blockNumber = useBlockNumber() - - useEffect(() => { - const updateMobi = async () => { - const bigInt = await stakingContract?.claimable_tokens(address) - setEarnedMobi(new TokenAmount(mobi, bigInt.toString())) - } - connected && updateMobi() - }, [stakingContract, setEarnedMobi, address, mobi, connected]) - - async function onClaimReward() { - if (stakingContract && stakingInfo?.stakedAmount) { + const onClaimReward = useCallback(async () => { + if (minter) { setAttempting(true) await minter - .mint(stakingInfo.gaugeAddress, { gasLimit: 350000 }) + .mint(gaugeAddress, { gasLimit: 350000 }) .then((response: TransactionResponse) => { addTransaction(response, { summary: `Claim accumulated MOBI rewards`, @@ -72,15 +57,12 @@ export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: Sta console.log(error) }) } - } + }, [addTransaction, gaugeAddress, minter]) let error: string | undefined if (!connected) { error = 'Connect Wallet' } - if (!stakingInfo?.stakedAmount) { - error = error ?? 'Enter an amount' - } return ( @@ -90,23 +72,16 @@ export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: Sta Claim - {pendingMobi && ( - - - {pendingMobi.toSignificant(6)} MOBI - - {/* {stakingInfo?.dualRewards && ( - - {stakingInfo?.earnedAmount?.toSignificant(6)} {stakingInfo?.rewardToken?.symbol} - - )} */} - Unclaimed rewards - - )} + + + {userGaugeInfo.claimableMobi.toSignificant(6)} MOBI + + Unclaimed rewards + When you claim without withdrawing your liquidity remains in the mining pool. - + {error ?? 'Claim'} @@ -114,7 +89,7 @@ export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: Sta {attempting && !hash && ( - Claiming {pendingMobi.toSignificant(6)} MOBI + Claiming {userGaugeInfo.claimableMobi.toSignificant(6)} MOBI )} diff --git a/src/pages/Pool/Manage.tsx b/src/pages/Pool/Manage.tsx index 5cf233f8b96..6fce731688d 100644 --- a/src/pages/Pool/Manage.tsx +++ b/src/pages/Pool/Manage.tsx @@ -1,4 +1,5 @@ import CurrencyPoolLogo from 'components/CurrencyPoolLogo' +import ClaimRewardModal from 'components/earn/ClaimRewardModal' import StakingModal from 'components/earn/StakingModal' import { useMobi } from 'hooks/Tokens' import JSBI from 'jsbi' @@ -256,16 +257,18 @@ export default function Manage({ gaugeAddress={display.gauge.address} mobiRate={mobiRate} /> - {/* setShowUnstakingModal(false)} - stakingInfo={stakingInfo} - /> setShowClaimRewardModal(false)} + gaugeAddress={display.gauge.address} + userGaugeInfo={userGaugeInfo} + /> + {/* setShowUnstakingModal(false)} stakingInfo={stakingInfo} /> + setShowExternalRewardModal(false)} From 60e3246eb9bf476e21a4fcffd2359e66c77d6301 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 7 Mar 2022 14:23:05 -0500 Subject: [PATCH 64/72] fix on max speed --- src/components/CurrencyInputPanel/index.tsx | 6 +- .../earn/ClaimExternalRewardsModal.tsx | 51 +++++----------- src/components/earn/StakingModal.tsx | 4 +- src/components/earn/UnstakingModal.tsx | 61 ++++++------------- src/pages/Mento/index.tsx | 10 ++- src/pages/OpenSum/index.tsx | 9 ++- src/pages/Pool/Manage.tsx | 7 ++- src/pages/Swap/index.tsx | 10 ++- src/state/gauges/updater.ts | 1 + src/state/mento/hooks.ts | 4 +- src/state/wallet/hooks.ts | 6 +- 11 files changed, 70 insertions(+), 99 deletions(-) diff --git a/src/components/CurrencyInputPanel/index.tsx b/src/components/CurrencyInputPanel/index.tsx index 9e4e2344d51..3b225d95f19 100644 --- a/src/components/CurrencyInputPanel/index.tsx +++ b/src/components/CurrencyInputPanel/index.tsx @@ -1,5 +1,5 @@ import { useColor } from 'hooks/useColor' -import { Token } from 'lib/token-utils' +import { Token, TokenAmount } from 'lib/token-utils' import { darken } from 'polished' import React, { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -137,7 +137,7 @@ export enum TokenType { interface CurrencyInputPanelProps { value: string onUserInput: (value: string) => void - onMax?: () => void + onMax?: (max?: TokenAmount) => void showMaxButton: boolean label?: string onCurrencySelect?: (currency: Token) => void @@ -193,7 +193,7 @@ export default function CurrencyInputPanel({ {connected && ( (onMax ? onMax(selectedCurrencyBalance) : null)} color={theme.text2} fontWeight={500} fontSize={14} diff --git a/src/components/earn/ClaimExternalRewardsModal.tsx b/src/components/earn/ClaimExternalRewardsModal.tsx index c2ca03835a5..13664526572 100644 --- a/src/components/earn/ClaimExternalRewardsModal.tsx +++ b/src/components/earn/ClaimExternalRewardsModal.tsx @@ -1,12 +1,10 @@ import { TransactionResponse } from '@ethersproject/providers' import { useMobi } from 'hooks/Tokens' -import { TokenAmount } from 'lib/token-utils' -import React, { useEffect, useState } from 'react' -import { useBlockNumber } from 'state/application/hooks' +import React, { useState } from 'react' import styled from 'styled-components' import { useWeb3Context } from '../../hooks' -import { useLiquidityGaugeContract, useMobiMinterContract } from '../../hooks/useContract' +import { useLiquidityGaugeContract } from '../../hooks/useContract' import { useTransactionAdder } from '../../state/transactions/hooks' import { CloseIcon, TYPE } from '../../theme' import { ButtonError } from '../Button' @@ -42,19 +40,6 @@ export default function ExternalRewardsModal({ isOpen, onDismiss, stakingInfo }: } const stakingContract = useLiquidityGaugeContract(stakingInfo.gaugeAddress) - const minter = useMobiMinterContract() - - const [pendingMobi, setEarnedMobi] = useState() - - const blockNumber = useBlockNumber() - - useEffect(() => { - const updateMobi = async () => { - const bigInt = await stakingContract?.claimable_tokens(address) - setEarnedMobi(new TokenAmount(mobi, bigInt.toString())) - } - connected && updateMobi() - }, [stakingContract, setEarnedMobi, connected, address, mobi]) async function onClaimReward() { if (stakingContract && stakingInfo?.stakedAmount) { @@ -89,26 +74,20 @@ export default function ExternalRewardsModal({ isOpen, onDismiss, stakingInfo }: Claim - {pendingMobi && ( - - {externalRewards && - externalRewards.map((reward) => ( - - {reward.toSignificant(6)} {reward.token.symbol} - - ))} - {/* {stakingInfo?.dualRewards && ( - - {stakingInfo?.earnedAmount?.toSignificant(6)} {stakingInfo?.rewardToken?.symbol} + + + {externalRewards && + externalRewards.map((reward) => ( + + {reward.toSignificant(6)} {reward.token.symbol} - )} */} - Unclaimed rewards - - )} + ))} + Unclaimed rewards + When you claim without withdrawing your liquidity remains in the mining pool. diff --git a/src/components/earn/StakingModal.tsx b/src/components/earn/StakingModal.tsx index 24b48ce21ea..7d70515e90f 100644 --- a/src/components/earn/StakingModal.tsx +++ b/src/components/earn/StakingModal.tsx @@ -101,7 +101,7 @@ export default function StakingModal({ const stakingContract = useLiquidityGaugeContract(gaugeAddress) const depositFunction = stakingContract?.['deposit(uint256)'] - async function onStake() { + const onStake = useCallback(async () => { setAttempting(true) if (stakingContract && inputAmount && deadline && depositFunction) { if (approval === ApprovalState.APPROVED) { @@ -118,7 +118,7 @@ export default function StakingModal({ throw new Error('Attempting to stake without approval or a signature. Please contact support.') } } - } + }, [addTransaction, approval, deadline, depositFunction, inputAmount, stakingContract]) let error: string | undefined if (!connected) { diff --git a/src/components/earn/UnstakingModal.tsx b/src/components/earn/UnstakingModal.tsx index 3754b4586ba..a52f44c4b14 100644 --- a/src/components/earn/UnstakingModal.tsx +++ b/src/components/earn/UnstakingModal.tsx @@ -1,7 +1,6 @@ import { TransactionResponse } from '@ethersproject/providers' -import { useMobi } from 'hooks/Tokens' import { TokenAmount } from 'lib/token-utils' -import React, { useState } from 'react' +import React, { useCallback, useState } from 'react' import styled from 'styled-components' import { useWeb3Context } from '../../hooks' @@ -23,10 +22,11 @@ const ContentWrapper = styled(AutoColumn)` interface StakingModalProps { isOpen: boolean onDismiss: () => void - stakingInfo: StablePoolInfo + userDeposited: TokenAmount + gaugeAddress: string } -export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: StakingModalProps) { +export default function UnstakingModal({ isOpen, onDismiss, userDeposited, gaugeAddress }: StakingModalProps) { const { connected } = useWeb3Context() // monitor call to help UI loading state @@ -40,17 +40,13 @@ export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: Staki onDismiss() } - const stakingContract = useLiquidityGaugeContract(stakingInfo.gaugeAddress) - stakingContract?.['withdraw(uint256,bool)'] - const mobi = useMobi() - const { stakedAmount } = stakingInfo - const pendingMobi = new TokenAmount(mobi, stakingInfo.pendingMobi ?? '0') + const stakingContract = useLiquidityGaugeContract(gaugeAddress) const withdrawFunction = stakingContract?.['withdraw(uint256,bool)'] - async function onWithdraw() { - if (stakingContract && stakingInfo?.stakedAmount) { + const onWithdraw = useCallback(async () => { + if (withdrawFunction) { setAttempting(true) - await withdrawFunction(stakedAmount.raw.toString(), true, { gasLimit: 3000000 }) + await withdrawFunction(userDeposited.raw.toString(), true, { gasLimit: 3000000 }) .then((response: TransactionResponse) => { addTransaction(response, { summary: `Withdraw deposited liquidity`, @@ -62,15 +58,12 @@ export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: Staki console.log(error) }) } - } + }, [addTransaction, userDeposited.raw, withdrawFunction]) let error: string | undefined if (!connected) { error = 'Connect Wallet' } - if (!stakingInfo?.stakedAmount) { - error = error ?? 'Enter an amount' - } return ( @@ -80,34 +73,18 @@ export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: Staki Withdraw - {stakingInfo?.stakedAmount && ( - - - {} - - Deposited liquidity - - )} - {/* {pendingMobi && ( - - - {} - - Unclaimed MOBI - - )} */} - {/* {stakingInfo?.dualRewards && stakingInfo?.earnedAmount && ( - - - {} - - Unclaimed {stakingInfo?.rewardToken?.symbol} - - )} */} + + + + {} + + Deposited liquidity + + When you withdraw, your liquidity is removed from the mining pool. - + {error ?? 'Withdraw'} @@ -115,7 +92,7 @@ export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: Staki {attempting && !hash && ( - Withdrawing {stakingInfo?.stakedAmount?.toSignificant(4)} MOBI-LP + Withdrawing {userDeposited.toSignificant(4)} MOBI-LP )} diff --git a/src/pages/Mento/index.tsx b/src/pages/Mento/index.tsx index f7ab1bf8847..df1ef22da97 100644 --- a/src/pages/Mento/index.tsx +++ b/src/pages/Mento/index.tsx @@ -187,9 +187,13 @@ export default function Mento() { [onCurrencySelection] ) - const handleMaxInput = useCallback(() => { - maxAmountInput && onUserInput(Field.INPUT, maxAmountInput.toExact()) - }, [maxAmountInput, onUserInput]) + const handleMaxInput = useCallback( + (amount?: TokenAmount) => { + ;(amount && onUserInput(Field.INPUT, amount.toExact())) || + (maxAmountInput && onUserInput(Field.INPUT, maxAmountInput.toExact())) + }, + [maxAmountInput, onUserInput] + ) const handleOutputSelect = useCallback( (outputCurrency) => onCurrencySelection(Field.OUTPUT, outputCurrency), diff --git a/src/pages/OpenSum/index.tsx b/src/pages/OpenSum/index.tsx index 0e9740470cd..6057062b8ee 100644 --- a/src/pages/OpenSum/index.tsx +++ b/src/pages/OpenSum/index.tsx @@ -174,9 +174,12 @@ export default function OpenSum() { [setInputToken, setOutputToken, setApprovalSubmitted] ) - const handleMaxInput = useCallback(() => { - maxAmountInput && setInputValue(maxAmountInput.toExact()) - }, [maxAmountInput, setInputValue]) + const handleMaxInput = useCallback( + (amount?: TokenAmount) => { + ;(amount && setInputValue(amount.toExact())) || (maxAmountInput && setInputValue(maxAmountInput.toExact())) + }, + [maxAmountInput] + ) const onSwitchTokens = () => { alert('You can only swap FROM v1 assets TO v2 assets') diff --git a/src/pages/Pool/Manage.tsx b/src/pages/Pool/Manage.tsx index 6fce731688d..ec476fd25e3 100644 --- a/src/pages/Pool/Manage.tsx +++ b/src/pages/Pool/Manage.tsx @@ -1,6 +1,7 @@ import CurrencyPoolLogo from 'components/CurrencyPoolLogo' import ClaimRewardModal from 'components/earn/ClaimRewardModal' import StakingModal from 'components/earn/StakingModal' +import UnstakingModal from 'components/earn/UnstakingModal' import { useMobi } from 'hooks/Tokens' import JSBI from 'jsbi' import { calculateVirtualPrice } from 'lib/calculator' @@ -263,11 +264,13 @@ export default function Manage({ gaugeAddress={display.gauge.address} userGaugeInfo={userGaugeInfo} /> - {/* setShowUnstakingModal(false)} - stakingInfo={stakingInfo} + userDeposited={userDeposited} + gaugeAddress={display.gauge.address} /> + {/* { - maxAmountInput && onUserInput(Field.INPUT, maxAmountInput.toExact()) - }, [maxAmountInput, onUserInput]) + const handleMaxInput = useCallback( + (amount?: TokenAmount) => { + ;(amount && onUserInput(Field.INPUT, amount.toExact())) || + (maxAmountInput && onUserInput(Field.INPUT, maxAmountInput.toExact())) + }, + [maxAmountInput, onUserInput] + ) const handleOutputSelect = useCallback( (outputCurrency) => onCurrencySelection(Field.OUTPUT, outputCurrency), diff --git a/src/state/gauges/updater.ts b/src/state/gauges/updater.ts index 3718d79aa53..cc6e1dbcdaa 100644 --- a/src/state/gauges/updater.ts +++ b/src/state/gauges/updater.ts @@ -48,6 +48,7 @@ export function GaugeUpdater() { const effectiveBalances = useMultipleContractSingleData(gaugeAddresses, gaugeInterface, 'working_balances', [ connected ? address : undefined, ]) + const lastVote = useSingleContractMultipleData( gaugeController, 'last_user_vote', diff --git a/src/state/mento/hooks.ts b/src/state/mento/hooks.ts index d2405417522..6a586a4bbf7 100644 --- a/src/state/mento/hooks.ts +++ b/src/state/mento/hooks.ts @@ -172,8 +172,8 @@ export function useMentoTradeInfo(): { const parsedAmount = tryParseAmount(typedValue, (isExactIn ? inputCurrency : outputCurrency) ?? undefined) const currencyBalances = { - [Field.INPUT]: relevantTokenBalances[0], - [Field.OUTPUT]: relevantTokenBalances[1], + [Field.INPUT]: relevantTokenBalances[inputCurrency?.address.toLowerCase() ?? ''], + [Field.OUTPUT]: relevantTokenBalances[outputCurrency?.address.toLowerCase() ?? ''], } const currencies: { [field in Field]?: Token } = { diff --git a/src/state/wallet/hooks.ts b/src/state/wallet/hooks.ts index c1c2268a781..ecbd727b1a5 100644 --- a/src/state/wallet/hooks.ts +++ b/src/state/wallet/hooks.ts @@ -42,21 +42,21 @@ export function useTokenBalances( ) const validatedTokenAddresses = useMemo(() => validatedTokens.map((vt) => vt.address), [validatedTokens]) const balances = useMultipleContractSingleData(validatedTokenAddresses, ERC20_INTERFACE, 'balanceOf', [address]) - - return useMemo( + const hold = useMemo( () => address && validatedTokens.length > 0 ? validatedTokens.reduce<{ [tokenAddress: string]: TokenAmount | undefined }>((memo, token, i) => { const value = balances?.[i]?.result?.[0] const amount = value ? JSBI.BigInt(value.toString()) : undefined if (amount) { - memo[token.address] = new TokenAmount(token, amount) + memo[token.address.toLowerCase()] = new TokenAmount(token, amount) } return memo }, {}) : {}, [address, validatedTokens, balances] ) + return hold } // mimics useAllBalances From 30d37f1d5a4aaf9640181dcf301929b1e273477d Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 7 Mar 2022 14:50:37 -0500 Subject: [PATCH 65/72] claim rewards modal --- .../earn/ClaimExternalRewardsModal.tsx | 30 +++--- src/pages/Pool/Manage.tsx | 94 ++++++------------- src/state/gauges/hooks.ts | 25 ++++- 3 files changed, 64 insertions(+), 85 deletions(-) diff --git a/src/components/earn/ClaimExternalRewardsModal.tsx b/src/components/earn/ClaimExternalRewardsModal.tsx index 13664526572..caf5ff74f1c 100644 --- a/src/components/earn/ClaimExternalRewardsModal.tsx +++ b/src/components/earn/ClaimExternalRewardsModal.tsx @@ -1,6 +1,6 @@ import { TransactionResponse } from '@ethersproject/providers' -import { useMobi } from 'hooks/Tokens' -import React, { useState } from 'react' +import { TokenAmount } from 'lib/token-utils' +import React, { useCallback, useState } from 'react' import styled from 'styled-components' import { useWeb3Context } from '../../hooks' @@ -21,13 +21,12 @@ const ContentWrapper = styled(AutoColumn)` interface StakingModalProps { isOpen: boolean onDismiss: () => void - stakingInfo: StablePoolInfo + externalRewards: TokenAmount[] | undefined + gaugeAddress: string } -export default function ExternalRewardsModal({ isOpen, onDismiss, stakingInfo }: StakingModalProps) { +export default function ExternalRewardsModal({ isOpen, onDismiss, externalRewards, gaugeAddress }: StakingModalProps) { const { address, connected } = useWeb3Context() - const mobi = useMobi() - const externalRewards = useExternalRewards({ address: stakingInfo.poolAddress ?? '' }) // monitor call to help UI loading state const addTransaction = useTransactionAdder() const [hash, setHash] = useState() @@ -39,10 +38,10 @@ export default function ExternalRewardsModal({ isOpen, onDismiss, stakingInfo }: onDismiss() } - const stakingContract = useLiquidityGaugeContract(stakingInfo.gaugeAddress) + const stakingContract = useLiquidityGaugeContract(gaugeAddress) - async function onClaimReward() { - if (stakingContract && stakingInfo?.stakedAmount) { + const onClaimReward = useCallback(async () => { + if (stakingContract) { setAttempting(true) await stakingContract['claim_rewards(address)'](address, { gasLimit: 1000000 }) .then((response: TransactionResponse) => { @@ -56,15 +55,12 @@ export default function ExternalRewardsModal({ isOpen, onDismiss, stakingInfo }: console.log(error) }) } - } + }, [addTransaction, address, stakingContract]) let error: string | undefined if (!connected) { error = 'Connect Wallet' } - if (!stakingInfo?.stakedAmount) { - error = error ?? 'Enter an amount' - } return ( @@ -78,11 +74,7 @@ export default function ExternalRewardsModal({ isOpen, onDismiss, stakingInfo }: {externalRewards && externalRewards.map((reward) => ( - + {reward.toSignificant(6)} {reward.token.symbol} ))} @@ -91,7 +83,7 @@ export default function ExternalRewardsModal({ isOpen, onDismiss, stakingInfo }: When you claim without withdrawing your liquidity remains in the mining pool. - + {error ?? 'Claim'} diff --git a/src/pages/Pool/Manage.tsx b/src/pages/Pool/Manage.tsx index ec476fd25e3..4c913c7ff68 100644 --- a/src/pages/Pool/Manage.tsx +++ b/src/pages/Pool/Manage.tsx @@ -1,4 +1,5 @@ import CurrencyPoolLogo from 'components/CurrencyPoolLogo' +import ExternalRewardsModal from 'components/earn/ClaimExternalRewardsModal' import ClaimRewardModal from 'components/earn/ClaimRewardModal' import StakingModal from 'components/earn/StakingModal' import UnstakingModal from 'components/earn/UnstakingModal' @@ -9,7 +10,7 @@ import { Fraction, TokenAmount } from 'lib/token-utils' import React, { useCallback, useState } from 'react' import { Link, RouteComponentProps } from 'react-router-dom' import { usePegPrice } from 'state/application/hooks' -import { useGaugeInfo, useUserGaugeInfo } from 'state/gauges/hooks' +import { useExternalRewards, useGaugeInfo, useUserGaugeInfo } from 'state/gauges/hooks' import { getCurrentDisplayFromGauge, useCurrentPoolAddress } from 'state/mobiusPools/hooks' import { useStakingInfo } from 'state/staking/hooks' import styled from 'styled-components' @@ -103,16 +104,6 @@ export default function Manage({ const gaugeInfo = useGaugeInfo(display?.gauge ?? undefined) const userGaugeInfo = useUserGaugeInfo(display?.gauge ?? undefined) const exchangeInfo = useCurrentPoolAddress(display?.pool.address ?? '') - // get currencies and pair - - // const stakingInfo = useStablePoolInfoByName(poolName) - - // const { balances, stakedAmount, totalStakedAmount, tokens, peggedTo, pegComesAfter, lastClaim } = stakingInfo ?? { - // balances: [], - // stakedAmount: undefined, - // totalStakedAmount: undefined, - // tokens: [], - // } const userLiquidityUnstaked = useTokenBalance(connected ? address : undefined, display?.pool.lpToken) const [showStakingModal, setShowStakingModal] = useState(false) @@ -124,6 +115,8 @@ export default function Manage({ const mobiCountUpAmount = userGaugeInfo?.claimableMobi.toFixed(6) ?? '0' const mobiCountUpAmountPrevious = usePrevious(mobiCountUpAmount) ?? '0' + const externalRewards = useExternalRewards(display?.gauge) + const handleDepositClick = useCallback(() => { if (connected) { setShowStakingModal(true) @@ -139,8 +132,6 @@ export default function Manage({ const nextClaimableTime = gaugeInfo.lastClaim.valueOf() + MS_IN_HOUR const minutesUntilRefresh = Math.max(0, (nextClaimableTime - Date.now()) / MS_IN_MINUTE) - // const earnedMobi = new TokenAmount(mobi, stakingInfo?.pendingMobi ?? '0') - const totalDeposited = exchangeInfo.lpTotalSupply const userDeposited = new TokenAmount(display.pool.lpToken, userGaugeInfo.balance) @@ -148,37 +139,10 @@ export default function Manage({ const userDepositedValue = pegPrice && virtualPrice ? virtualPrice.multiply(totalDeposited).multiply(pegPrice) : new Fraction(0) - // const { valueOfStaked, totalValueDeposited } = getDepositValues(stakingInfo) - const userMobiRate = new TokenAmount(mobi, mobiRate.multiply(userDeposited).divide(totalDeposited).quotient) const userExternalRates = display.gauge.additionalRewards.map( (reward) => new TokenAmount(reward.token, reward.multiply(userDeposited).divide(totalDeposited).quotient) ) - // const userExternalRates: TokenAmount[] = [] - // if ( - // connected && - // stakingInfo && - // stakingInfo.externalRewardRates && - // totalStakedAmount && - // totalStakedAmount.greaterThan('0') && - // stakingInfo?.workingPercentage.greaterThan('0') - // ) { - // userExternalRates = stakingInfo.externalRewardRates.map( - // (rate) => new TokenAmount(rate.token, stakingInfo.totalPercentage.multiply(rate.raw).toFixed(0)) - // ) - // } - - // const totalMobiRate = new TokenAmount(mobi, stakingInfo?.mobiRate ?? JSBI.BigInt('0')) - - // const userBalances = balances.map((amount) => { - // const fraction = new Fraction(stakedAmount?.raw.toString() ?? '0', totalStakedAmount?.raw || JSBI.BigInt('0')) - // const ratio = fraction.multiply(amount.raw) - - // if (JSBI.equal(ratio.denominator, JSBI.BigInt('0'))) { - // return new TokenAmount(amount.currency, JSBI.BigInt('0')) - // } - // return new TokenAmount(amount.currency, JSBI.divide(ratio.numerator, ratio.denominator)) - // }) const decimalPlacesForLP = userDeposited.greaterThan('1') ? 6 : userDeposited.greaterThan('0') ? 12 : 2 @@ -270,13 +234,12 @@ export default function Manage({ userDeposited={userDeposited} gaugeAddress={display.gauge.address} /> - {/* - setShowExternalRewardModal(false)} - stakingInfo={stakingInfo} - /> */} + gaugeAddress={display.gauge.address} + externalRewards={externalRewards} + /> @@ -380,27 +343,28 @@ export default function Manage({ Next Refresh in {minutesUntilRefresh.toFixed(0)} minutes - {display.gauge.additionalRewards.map((rewardToken, i) => ( - - - {rewardToken.toFixed(4, { groupSeparator: ',' })} - - - - ⚡ - - {stakingInfo - ? userExternalRates?.[i] - ?.multiply(BIG_INT_SECONDS_IN_WEEK) - ?.toSignificant(4, { groupSeparator: ',' }) ?? '-' - : '0'} - {` ${rewardToken.token.symbol} / week`} - - - ))} + {externalRewards && + externalRewards.map((rewardToken, i) => ( + + + {rewardToken.toFixed(4, { groupSeparator: ',' })} + + + + ⚡ + + {stakingInfo + ? userExternalRates?.[i] + ?.multiply(BIG_INT_SECONDS_IN_WEEK) + ?.toSignificant(4, { groupSeparator: ',' }) ?? '-' + : '0'} + {` ${rewardToken.token.symbol} / week`} + + + ))} )} diff --git a/src/state/gauges/hooks.ts b/src/state/gauges/hooks.ts index 38b324a3856..a009315c806 100644 --- a/src/state/gauges/hooks.ts +++ b/src/state/gauges/hooks.ts @@ -1,11 +1,14 @@ import { invariant } from '@apollo/client/utilities/globals' import { IGauge, StablePools } from 'constants/pools' +import { useWeb3Context } from 'hooks' import { useMobi } from 'hooks/Tokens' +import { useLiquidityGaugeContract } from 'hooks/useContract' import JSBI from 'jsbi' import { Percent, TokenAmount } from 'lib/token-utils' import { useSelector } from 'react-redux' +import { useSingleContractMultipleData } from 'state/multicall/hooks' -import { CHAIN } from '../../constants' +import { CHAIN, ZERO_ADDRESS } from '../../constants' import { AppState } from '..' import { IGaugeState, IUserGaugeState } from './reducer' @@ -113,3 +116,23 @@ export function useUserGaugeInfo(gauge: IGauge | undefined): UserGaugeInfo | und invariant(!!gaugeInfo[0], 'gauge not found') return gaugeInfo[0] } + +export function useExternalRewards(gauge: IGauge | undefined | null): TokenAmount[] | undefined { + const gaugeContract = useLiquidityGaugeContract(gauge?.address ?? ZERO_ADDRESS) + const { address: userAddress, connected } = useWeb3Context() + + const claimableTokens = useSingleContractMultipleData( + gaugeContract, + 'claimable_reward_write', + gauge?.additionalRewards.map((token) => [ + connected ? userAddress : ZERO_ADDRESS, + token.token.address ?? ZERO_ADDRESS, + ]) ?? [] + ) + + if (!gauge) return undefined + + return claimableTokens?.map((result, i) => { + return new TokenAmount(gauge.additionalRewards[i].token, JSBI.BigInt(result.result?.[0] ?? '0')) + }) +} From dd9826f9152f311fa33e680ad918d2c2d94d2287 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Mon, 7 Mar 2022 16:11:27 -0500 Subject: [PATCH 66/72] add some pools --- src/constants/StablePools.ts | 5 -- src/constants/pools.ts | 167 ++++++++++++++++++++++++++++++++++- src/constants/tokens.ts | 51 ++++++----- 3 files changed, 190 insertions(+), 33 deletions(-) diff --git a/src/constants/StablePools.ts b/src/constants/StablePools.ts index aff1423ea1d..f7b7ef91a10 100644 --- a/src/constants/StablePools.ts +++ b/src/constants/StablePools.ts @@ -1,5 +1,3 @@ -import type { ChainId } from 'lib/token-utils' - // export const STATIC_POOL_INFO: { [K in ChainId]: StableSwapConstants[] } = { // [ChainId.MAINNET]: [ // { @@ -1111,6 +1109,3 @@ import type { ChainId } from 'lib/token-utils' // [ChainId.ALFAJORES]: [], // [ChainId.BAKLAVA]: [], // } - -//todo: replace Mainnet and Baklava Pool Addresses -type AddressMap = { [K in ChainId]: string } diff --git a/src/constants/pools.ts b/src/constants/pools.ts index 55cfcd1082a..ec55aa72923 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -7,7 +7,24 @@ import ethLogo from '../assets/images/ethereum-chain-logo.png' import polygonLogo from '../assets/images/polygon-chain-logo.png' import terraLogo from '../assets/images/terra-logo.png' import { CHAIN } from './' -import { CELO, CETH, CUSD, UST, WETH } from './tokens' +import { + AAUSDC, + CBTC, + CELO, + CETH, + CUSD, + DAI, + PCELO, + PEUR, + POOF, + PUSD, + PUSDC, + USDC, + USDC1, + UST, + WBTC, + WETH, +} from './tokens' export type Fees = { trade: Percent @@ -183,7 +200,7 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { }, gauge: { address: '0x107F94409746E8c8E6eFF139A100D17D9ca7FdfE'.toLowerCase(), - additionalRewards: [new TokenAmount(CELO[CHAIN], '12000000000000000')], + additionalRewards: [new TokenAmount(CELO[CHAIN], weeklyEmissionToSeconds(2268))], }, }, { @@ -200,6 +217,152 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { additionalRewards: [], }, }, + { + name: 'USDC (Optics V2)', + chain: Chain.Ethereum, + peg: Dollar, + pool: { + address: '0x9906589Ea8fd27504974b7e8201DF5bBdE986b03'.toLowerCase(), + lpToken: lp( + ChainId.Mainnet, + '0x39b6F09ef97dB406ab78D869471adb2384C494E3'.toLowerCase(), + 'Mobius cUSD/cUSDC LP' + ), + tokens: [CUSD[ChainId.Mainnet], USDC[ChainId.Mainnet]], + }, + gauge: { + address: '0xc96AeeaFF32129da934149F6134Aa7bf291a754E'.toLowerCase(), + additionalRewards: [new TokenAmount(CELO[CHAIN], weeklyEmissionToSeconds(11088))], + }, + }, + { + name: 'DAI (Optics V2)', + chain: Chain.Ethereum, + peg: Dollar, + pool: { + address: '0xF3f65dFe0c8c8f2986da0FEc159ABE6fd4E700B4'.toLowerCase(), + lpToken: lp(ChainId.Mainnet, '0x274DD2dF039f1f6131419C82173D97770e6af6B7'.toLowerCase(), 'Mobius cUSD/cDAI LP'), + tokens: [CUSD[ChainId.Mainnet], DAI[ChainId.Mainnet]], + }, + gauge: { + address: '0xE1f9D952EecC07cfEFa69df9fBB0cEF260957119'.toLowerCase(), + additionalRewards: [new TokenAmount(CELO[CHAIN], weeklyEmissionToSeconds(3780))], + }, + }, + { + name: 'WBTC (Optics V2)', + chain: Chain.Ethereum, + peg: Bitcoin, + pool: { + address: '0xaEFc4e8cF655a182E8346B24c8AbcE45616eE0d2'.toLowerCase(), + lpToken: lp(ChainId.Mainnet, '0x20d7274C5aF4f9DE6e8C93025e44aF3979d9Ab2b'.toLowerCase(), 'Mobius cBTC/wBTC LP'), + tokens: [CBTC[ChainId.Mainnet], WBTC[ChainId.Mainnet]], + }, + gauge: { + address: '0x127b524c74C2162Ee4BB2e42d8d2eB9050C0293E'.toLowerCase(), + additionalRewards: [], + }, + }, + { + name: 'pUSDC (Optics V2)', + chain: Chain.Ethereum, + peg: Dollar, + pool: { + address: '0xcCe0d62Ce14FB3e4363Eb92Db37Ff3630836c252'.toLowerCase(), + lpToken: lp( + ChainId.Mainnet, + '0x68b239b415970dD7a5234A9701cbB5BfaB544C7C'.toLowerCase(), + 'Mobius cUSD/pUSDC LP' + ), + tokens: [CUSD[ChainId.Mainnet], PUSDC[ChainId.Mainnet]], + }, + gauge: { + address: '0x0A125D473cd3b1968e728DDF7d424c928C09222A'.toLowerCase(), + additionalRewards: [], + }, + }, + { + name: 'USDC (Optics V1)', + chain: Chain.Ethereum, + peg: Dollar, + pool: { + address: '0xA5037661989789d0310aC2B796fa78F1B01F195D'.toLowerCase(), + lpToken: lp( + ChainId.Mainnet, + '0xd7Bf6946b740930c60131044bD2F08787e1DdBd4'.toLowerCase(), + 'Mobius cUSD/cUSDC LP' + ), + tokens: [CUSD[ChainId.Mainnet], USDC1[ChainId.Mainnet]], + }, + gauge: { + address: '0xdAA2ab880b7f3D5697e6F85e63c28b9120AA9E07'.toLowerCase(), + additionalRewards: [], + }, + }, + { + name: 'aaUSDC (Allbridge)', + chain: Chain.Avax, + peg: Dollar, + pool: { + address: '0x0986B42F5f9C42FeEef66fC23eba9ea1164C916D'.toLowerCase(), + lpToken: lp( + ChainId.Mainnet, + '0x730e677f39C4Ca96012c394B9Da09A025E922F81'.toLowerCase(), + 'Mobius cUSD/aaUSDC LP' + ), + tokens: [CUSD[ChainId.Mainnet], AAUSDC[ChainId.Mainnet]], + }, + gauge: { + address: '0xF2ae5c2D2D2eD13dd324C0942163054fc4A3D4d9'.toLowerCase(), + additionalRewards: [], + }, + }, + { + name: 'Poof cUSD V2', + chain: Chain.Celo, + peg: Dollar, + pool: { + address: '0xa2F0E57d4cEAcF025E81C76f28b9Ad6E9Fbe8735'.toLowerCase(), + lpToken: lp(ChainId.Mainnet, '0x07e137E5605E15C93f22545868Fa70CECfCbbFFE'.toLowerCase(), 'Mobius cUSD/pUSD LP'), + tokens: [CUSD[ChainId.Mainnet], PUSD[ChainId.Mainnet]], + }, + gauge: { + address: '0xE7195E651Cc47853f0054d85c8ADFc79D532929f'.toLowerCase(), + additionalRewards: [new TokenAmount(POOF[ChainId.Mainnet], '6283068780000000')], + }, + }, + { + name: 'Poof CELO V2', + chain: Chain.Celo, + peg: Celo, + pool: { + address: '0xFc9e2C63370D8deb3521922a7B2b60f4Cff7e75a'.toLowerCase(), + lpToken: lp( + ChainId.Mainnet, + '0xAfFD8d6b5e5A0e25034DD3D075532F9CE01C305c'.toLowerCase(), + 'Mobius cUSD/pCELO LP' + ), + tokens: [CUSD[ChainId.Mainnet], PCELO[ChainId.Mainnet]], + }, + gauge: { + address: '0xD0d57a6689188F854F996BEAE0Cb1949FDB5FF86'.toLowerCase(), + additionalRewards: [new TokenAmount(POOF[ChainId.Mainnet], '6283068780000000')], + }, + }, + { + name: 'Poof cEUR V2', + chain: Chain.Celo, + peg: Celo, + pool: { + address: '0x23C95678862a229fAC088bd9705622d78130bC3e'.toLowerCase(), + lpToken: lp(ChainId.Mainnet, '0xec8e37876Fd9De919B58788B87A078e546149F87'.toLowerCase(), 'Mobius cUSD/pEUR LP'), + tokens: [CUSD[ChainId.Mainnet], PEUR[ChainId.Mainnet]], + }, + gauge: { + address: '0xCAEd243de23264Bdd8297c6eECcF320846eee18A'.toLowerCase(), + additionalRewards: [new TokenAmount(POOF[ChainId.Mainnet], '6283068780000000')], + }, + }, ], [ChainId.Alfajores]: [], [ChainId.Baklava]: [], diff --git a/src/constants/tokens.ts b/src/constants/tokens.ts index bb663d2e475..35d5e7e3b6e 100644 --- a/src/constants/tokens.ts +++ b/src/constants/tokens.ts @@ -374,33 +374,32 @@ export const PEUR1 = makeTokens( 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_pEUR.png' ) +export const POOF = makeTokens( + { + [ChainId.Mainnet]: '0x00400FcbF0816bebB94654259de7273f4A05c762', + [ChainId.Alfajores]: '0x00400FcbF0816bebB94654259de7273f4A05c762', + [ChainId.Baklava]: '0x00400FcbF0816bebB94654259de7273f4A05c762', + }, + 18, + 'Poof', + 'POOF', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_POOF.png' +) + +export const MOO = makeTokens( + { + [ChainId.Mainnet]: '0x17700282592D6917F6A73D0bF8AcCf4D578c131e', + [ChainId.Alfajores]: '0x17700282592D6917F6A73D0bF8AcCf4D578c131e', + [ChainId.Baklava]: '0x17700282592D6917F6A73D0bF8AcCf4D578c131e', + }, + 18, + 'Moola', + 'MOO', + 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_MOO.png' +) + export const ExternalRewards: { [K in ChainId]: Token[] } = { - [ChainId.Mainnet]: [ - new Token({ - address: '0x00400FcbF0816bebB94654259de7273f4A05c762', - name: 'Poof', - symbol: 'POOF', - chainId: ChainId.Mainnet, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_POOF.png', - }), - new Token({ - address: '0x17700282592D6917F6A73D0bF8AcCf4D578c131e', - name: 'Moola', - symbol: 'MOO', - chainId: ChainId.Mainnet, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_MOO.png', - }), - new Token({ - address: '0x471EcE3750Da237f93B8E339c536989b8978a438', - name: 'Celo', - symbol: 'CELO', - chainId: ChainId.Mainnet, - decimals: 18, - logoURI: 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_CELO.png', - }), - ], + [ChainId.Mainnet]: [POOF[ChainId.Mainnet], MOO[ChainId.Mainnet], CELO[ChainId.Mainnet]], [ChainId.Alfajores]: [], [ChainId.Baklava]: [], } From 9b89f0b0d091a24cde847c6b392fb02ead71a902 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 8 Mar 2022 10:22:27 -0500 Subject: [PATCH 67/72] add hooks to pool page --- src/components/earn/StablePoolCard.tsx | 99 ++++-- src/constants/pools.ts | 463 ++++++++++++++++--------- src/constants/tokens.ts | 26 +- src/pages/Pool/index.tsx | 52 +-- src/state/application/updater.ts | 2 + src/state/claim/updater.ts | 1 + src/state/gauges/updater.ts | 1 + src/state/logs/updater.ts | 2 +- src/state/mentoPools/updater.ts | 1 + src/state/mobiusPools/updater.ts | 1 + src/state/multicall/updater.tsx | 2 +- src/state/openSum/updater.ts | 2 +- src/state/staking/updater.ts | 1 + src/state/transactions/updater.tsx | 1 + src/state/user/updater.tsx | 1 + 15 files changed, 408 insertions(+), 247 deletions(-) diff --git a/src/components/earn/StablePoolCard.tsx b/src/components/earn/StablePoolCard.tsx index f3fc97389ac..6dad022a60b 100644 --- a/src/components/earn/StablePoolCard.tsx +++ b/src/components/earn/StablePoolCard.tsx @@ -7,7 +7,7 @@ import { calculateVirtualPrice } from 'lib/calculator' import { Fraction, TokenAmount } from 'lib/token-utils' import { Meta } from 'pages/Pool' import { darken } from 'polished' -import React, { useState } from 'react' +import React, { useCallback, useMemo, useState } from 'react' import { isMobile } from 'react-device-detect' import { useHistory } from 'react-router' import { NavLink } from 'react-router-dom' @@ -155,50 +155,81 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => const mobi = useMobi() const mobiPrice = useMobiPrice() - const virtualPrice = calculateVirtualPrice(meta.exchangeInfo) + const pegPrice = usePegPrice(meta.display.peg.priceQuery) - const totalDeposited = - virtualPrice?.multiply(meta.exchangeInfo.lpTotalSupply) ?? new TokenAmount(meta.display.pool.lpToken, 0) + const externalRewardValue = useValueOfExternalRewards(meta.display.gauge).multiply(BIG_INT_SECONDS_IN_YEAR) - const userDeposited = new TokenAmount( - meta.display.pool.lpToken, - virtualPrice?.multiply(meta.lpBalance.asFraction.add(meta.userGauge?.balance ?? 0)).quotient ?? 0 - ) + const poolColor = usePoolColor(meta.display) - const pegPrice = usePegPrice(meta.display.peg.priceQuery) + const virtualPrice = calculateVirtualPrice(meta.exchangeInfo) - const totalDepositedValue = pegPrice ? totalDeposited.multiply(pegPrice) : new Fraction(0) + const { totalDeposited, userDeposited, mobiRate, apr, dpr, apy, boostedApr } = useMemo(() => { + const totalDeposited = + virtualPrice?.multiply(meta.exchangeInfo.lpTotalSupply) ?? new TokenAmount(meta.display.pool.lpToken, 0) - const mobiRate = new TokenAmount(mobi, meta.gauge?.weight.multiply(stakingInfo.mobiRate).quotient ?? 0) - const mobiRateValue = mobiPrice.multiply(mobiRate).multiply(BIG_INT_SECONDS_IN_YEAR) + const userDeposited = new TokenAmount( + meta.display.pool.lpToken, + virtualPrice?.multiply(meta.lpBalance.asFraction.add(meta.userGauge?.balance ?? 0)).quotient ?? 0 + ) - const externalRewardValue = useValueOfExternalRewards(meta.display.gauge).multiply(BIG_INT_SECONDS_IN_YEAR) + const totalDepositedValue = pegPrice ? totalDeposited.multiply(pegPrice) : new Fraction(0) - // TODO: investigate if this is the right method - const { apr, dpr, apy } = calcRates(mobiRateValue.add(externalRewardValue), totalDepositedValue) - const { apr: boostedApr } = calcRates(mobiRateValue.add(externalRewardValue), totalDepositedValue) + const mobiRate = new TokenAmount(mobi, meta.gauge?.weight.multiply(stakingInfo.mobiRate).quotient ?? 0) + const mobiRateValue = mobiPrice.multiply(mobiRate).multiply(BIG_INT_SECONDS_IN_YEAR) - const balances = meta.exchangeInfo.reserves + // TODO: investigate if this is the right method + const { apr, dpr, apy } = calcRates(mobiRateValue.add(externalRewardValue), totalDepositedValue) + const { apr: boostedApr } = calcRates(mobiRateValue.add(externalRewardValue), totalDepositedValue) - const poolColor = usePoolColor(meta.display) + return { + totalDeposited, + userDeposited, + mobiRate, + apr, + dpr, + apy, + boostedApr, + } + }, [ + externalRewardValue, + meta.display.pool.lpToken, + meta.exchangeInfo.lpTotalSupply, + meta.gauge?.weight, + meta.lpBalance.asFraction, + meta.userGauge?.balance, + mobi, + mobiPrice, + pegPrice, + stakingInfo.mobiRate, + virtualPrice, + ]) - const display = (str: string): string => { - const peg = meta.display.peg - return (peg.position === 'before' ? peg.symbol : '').concat(str).concat(peg.position === 'after' ? peg.symbol : '') - } + const balances = meta.exchangeInfo.reserves + const display = useCallback( + (str: string): string => { + const peg = meta.display.peg + return (peg.position === 'before' ? peg.symbol : '') + .concat(str) + .concat(peg.position === 'after' ? peg.symbol : '') + }, + [meta.display.peg] + ) - const totalDisplay = (amount: TokenAmount | Fraction): string => { - const decimals = meta.display.peg.decimals - if (amount.lessThan(10 ** (2 - decimals))) return display(amount.toFixed(decimals + 1, { groupSeparator: ',' })) - else if (amount.lessThan(10 ** 6) || openManage) return display(amount.toFixed(decimals, { groupSeparator: ',' })) - else - return display( - amount - .divide(10 ** 6) - .toFixed(2, { groupSeparator: ',' }) - .concat('M') - ) - } + const totalDisplay = useCallback( + (amount: TokenAmount | Fraction): string => { + const decimals = meta.display.peg.decimals + if (amount.lessThan(10 ** (2 - decimals))) return display(amount.toFixed(decimals + 1, { groupSeparator: ',' })) + else if (amount.lessThan(10 ** 6) || openManage) return display(amount.toFixed(decimals, { groupSeparator: ',' })) + else + return display( + amount + .divide(10 ** 6) + .toFixed(2, { groupSeparator: ',' }) + .concat('M') + ) + }, + [display, meta.display.peg.decimals, openManage] + ) return ( setOpenManage(!openManage)}> diff --git a/src/constants/pools.ts b/src/constants/pools.ts index ec55aa72923..98ae3cf3e57 100644 --- a/src/constants/pools.ts +++ b/src/constants/pools.ts @@ -7,24 +7,7 @@ import ethLogo from '../assets/images/ethereum-chain-logo.png' import polygonLogo from '../assets/images/polygon-chain-logo.png' import terraLogo from '../assets/images/terra-logo.png' import { CHAIN } from './' -import { - AAUSDC, - CBTC, - CELO, - CETH, - CUSD, - DAI, - PCELO, - PEUR, - POOF, - PUSD, - PUSDC, - USDC, - USDC1, - UST, - WBTC, - WETH, -} from './tokens' +import { CELO, CETH, CUSD, UST, WETH } from './tokens' export type Fees = { trade: Percent @@ -217,152 +200,304 @@ export const StablePools: { [K in ChainId]: DisplayPool[] } = { additionalRewards: [], }, }, - { - name: 'USDC (Optics V2)', - chain: Chain.Ethereum, - peg: Dollar, - pool: { - address: '0x9906589Ea8fd27504974b7e8201DF5bBdE986b03'.toLowerCase(), - lpToken: lp( - ChainId.Mainnet, - '0x39b6F09ef97dB406ab78D869471adb2384C494E3'.toLowerCase(), - 'Mobius cUSD/cUSDC LP' - ), - tokens: [CUSD[ChainId.Mainnet], USDC[ChainId.Mainnet]], - }, - gauge: { - address: '0xc96AeeaFF32129da934149F6134Aa7bf291a754E'.toLowerCase(), - additionalRewards: [new TokenAmount(CELO[CHAIN], weeklyEmissionToSeconds(11088))], - }, - }, - { - name: 'DAI (Optics V2)', - chain: Chain.Ethereum, - peg: Dollar, - pool: { - address: '0xF3f65dFe0c8c8f2986da0FEc159ABE6fd4E700B4'.toLowerCase(), - lpToken: lp(ChainId.Mainnet, '0x274DD2dF039f1f6131419C82173D97770e6af6B7'.toLowerCase(), 'Mobius cUSD/cDAI LP'), - tokens: [CUSD[ChainId.Mainnet], DAI[ChainId.Mainnet]], - }, - gauge: { - address: '0xE1f9D952EecC07cfEFa69df9fBB0cEF260957119'.toLowerCase(), - additionalRewards: [new TokenAmount(CELO[CHAIN], weeklyEmissionToSeconds(3780))], - }, - }, - { - name: 'WBTC (Optics V2)', - chain: Chain.Ethereum, - peg: Bitcoin, - pool: { - address: '0xaEFc4e8cF655a182E8346B24c8AbcE45616eE0d2'.toLowerCase(), - lpToken: lp(ChainId.Mainnet, '0x20d7274C5aF4f9DE6e8C93025e44aF3979d9Ab2b'.toLowerCase(), 'Mobius cBTC/wBTC LP'), - tokens: [CBTC[ChainId.Mainnet], WBTC[ChainId.Mainnet]], - }, - gauge: { - address: '0x127b524c74C2162Ee4BB2e42d8d2eB9050C0293E'.toLowerCase(), - additionalRewards: [], - }, - }, - { - name: 'pUSDC (Optics V2)', - chain: Chain.Ethereum, - peg: Dollar, - pool: { - address: '0xcCe0d62Ce14FB3e4363Eb92Db37Ff3630836c252'.toLowerCase(), - lpToken: lp( - ChainId.Mainnet, - '0x68b239b415970dD7a5234A9701cbB5BfaB544C7C'.toLowerCase(), - 'Mobius cUSD/pUSDC LP' - ), - tokens: [CUSD[ChainId.Mainnet], PUSDC[ChainId.Mainnet]], - }, - gauge: { - address: '0x0A125D473cd3b1968e728DDF7d424c928C09222A'.toLowerCase(), - additionalRewards: [], - }, - }, - { - name: 'USDC (Optics V1)', - chain: Chain.Ethereum, - peg: Dollar, - pool: { - address: '0xA5037661989789d0310aC2B796fa78F1B01F195D'.toLowerCase(), - lpToken: lp( - ChainId.Mainnet, - '0xd7Bf6946b740930c60131044bD2F08787e1DdBd4'.toLowerCase(), - 'Mobius cUSD/cUSDC LP' - ), - tokens: [CUSD[ChainId.Mainnet], USDC1[ChainId.Mainnet]], - }, - gauge: { - address: '0xdAA2ab880b7f3D5697e6F85e63c28b9120AA9E07'.toLowerCase(), - additionalRewards: [], - }, - }, - { - name: 'aaUSDC (Allbridge)', - chain: Chain.Avax, - peg: Dollar, - pool: { - address: '0x0986B42F5f9C42FeEef66fC23eba9ea1164C916D'.toLowerCase(), - lpToken: lp( - ChainId.Mainnet, - '0x730e677f39C4Ca96012c394B9Da09A025E922F81'.toLowerCase(), - 'Mobius cUSD/aaUSDC LP' - ), - tokens: [CUSD[ChainId.Mainnet], AAUSDC[ChainId.Mainnet]], - }, - gauge: { - address: '0xF2ae5c2D2D2eD13dd324C0942163054fc4A3D4d9'.toLowerCase(), - additionalRewards: [], - }, - }, - { - name: 'Poof cUSD V2', - chain: Chain.Celo, - peg: Dollar, - pool: { - address: '0xa2F0E57d4cEAcF025E81C76f28b9Ad6E9Fbe8735'.toLowerCase(), - lpToken: lp(ChainId.Mainnet, '0x07e137E5605E15C93f22545868Fa70CECfCbbFFE'.toLowerCase(), 'Mobius cUSD/pUSD LP'), - tokens: [CUSD[ChainId.Mainnet], PUSD[ChainId.Mainnet]], - }, - gauge: { - address: '0xE7195E651Cc47853f0054d85c8ADFc79D532929f'.toLowerCase(), - additionalRewards: [new TokenAmount(POOF[ChainId.Mainnet], '6283068780000000')], - }, - }, - { - name: 'Poof CELO V2', - chain: Chain.Celo, - peg: Celo, - pool: { - address: '0xFc9e2C63370D8deb3521922a7B2b60f4Cff7e75a'.toLowerCase(), - lpToken: lp( - ChainId.Mainnet, - '0xAfFD8d6b5e5A0e25034DD3D075532F9CE01C305c'.toLowerCase(), - 'Mobius cUSD/pCELO LP' - ), - tokens: [CUSD[ChainId.Mainnet], PCELO[ChainId.Mainnet]], - }, - gauge: { - address: '0xD0d57a6689188F854F996BEAE0Cb1949FDB5FF86'.toLowerCase(), - additionalRewards: [new TokenAmount(POOF[ChainId.Mainnet], '6283068780000000')], - }, - }, - { - name: 'Poof cEUR V2', - chain: Chain.Celo, - peg: Celo, - pool: { - address: '0x23C95678862a229fAC088bd9705622d78130bC3e'.toLowerCase(), - lpToken: lp(ChainId.Mainnet, '0xec8e37876Fd9De919B58788B87A078e546149F87'.toLowerCase(), 'Mobius cUSD/pEUR LP'), - tokens: [CUSD[ChainId.Mainnet], PEUR[ChainId.Mainnet]], - }, - gauge: { - address: '0xCAEd243de23264Bdd8297c6eECcF320846eee18A'.toLowerCase(), - additionalRewards: [new TokenAmount(POOF[ChainId.Mainnet], '6283068780000000')], - }, - }, + // { + // name: 'USDC (Optics V2)', + // chain: Chain.Ethereum, + // peg: Dollar, + // pool: { + // address: '0x9906589Ea8fd27504974b7e8201DF5bBdE986b03'.toLowerCase(), + // lpToken: lp( + // ChainId.Mainnet, + // '0x39b6F09ef97dB406ab78D869471adb2384C494E3'.toLowerCase(), + // 'Mobius cUSD/cUSDC LP' + // ), + // tokens: [CUSD[ChainId.Mainnet], USDC[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0xc96AeeaFF32129da934149F6134Aa7bf291a754E'.toLowerCase(), + // additionalRewards: [new TokenAmount(CELO[CHAIN], weeklyEmissionToSeconds(11088))], + // }, + // }, + // { + // name: 'DAI (Optics V2)', + // chain: Chain.Ethereum, + // peg: Dollar, + // pool: { + // address: '0xF3f65dFe0c8c8f2986da0FEc159ABE6fd4E700B4'.toLowerCase(), + // lpToken: lp(ChainId.Mainnet, '0x274DD2dF039f1f6131419C82173D97770e6af6B7'.toLowerCase(), 'Mobius cUSD/cDAI LP'), + // tokens: [CUSD[ChainId.Mainnet], DAI[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0xE1f9D952EecC07cfEFa69df9fBB0cEF260957119'.toLowerCase(), + // additionalRewards: [new TokenAmount(CELO[CHAIN], weeklyEmissionToSeconds(3780))], + // }, + // }, + // { + // name: 'WBTC (Optics V2)', + // chain: Chain.Ethereum, + // peg: Bitcoin, + // pool: { + // address: '0xaEFc4e8cF655a182E8346B24c8AbcE45616eE0d2'.toLowerCase(), + // lpToken: lp(ChainId.Mainnet, '0x20d7274C5aF4f9DE6e8C93025e44aF3979d9Ab2b'.toLowerCase(), 'Mobius cBTC/wBTC LP'), + // tokens: [CBTC[ChainId.Mainnet], WBTC[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0x127b524c74C2162Ee4BB2e42d8d2eB9050C0293E'.toLowerCase(), + // additionalRewards: [], + // }, + // }, + // { + // name: 'pUSDC (Optics V2)', + // chain: Chain.Polygon, + // peg: Dollar, + // pool: { + // address: '0xcCe0d62Ce14FB3e4363Eb92Db37Ff3630836c252'.toLowerCase(), + // lpToken: lp( + // ChainId.Mainnet, + // '0x68b239b415970dD7a5234A9701cbB5BfaB544C7C'.toLowerCase(), + // 'Mobius cUSD/pUSDC LP' + // ), + // tokens: [CUSD[ChainId.Mainnet], PUSDC[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0x0A125D473cd3b1968e728DDF7d424c928C09222A'.toLowerCase(), + // additionalRewards: [], + // }, + // }, + // { + // name: 'USDC (Optics V1)', + // chain: Chain.Ethereum, + // peg: Dollar, + // pool: { + // address: '0xA5037661989789d0310aC2B796fa78F1B01F195D'.toLowerCase(), + // lpToken: lp( + // ChainId.Mainnet, + // '0xd7Bf6946b740930c60131044bD2F08787e1DdBd4'.toLowerCase(), + // 'Mobius cUSD/cUSDC LP' + // ), + // tokens: [CUSD[ChainId.Mainnet], USDC1[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0xdAA2ab880b7f3D5697e6F85e63c28b9120AA9E07'.toLowerCase(), + // additionalRewards: [], + // }, + // }, + // { + // name: 'aaUSDC (Allbridge)', + // chain: Chain.Avax, + // peg: Dollar, + // pool: { + // address: '0x0986B42F5f9C42FeEef66fC23eba9ea1164C916D'.toLowerCase(), + // lpToken: lp( + // ChainId.Mainnet, + // '0x730e677f39C4Ca96012c394B9Da09A025E922F81'.toLowerCase(), + // 'Mobius cUSD/aaUSDC LP' + // ), + // tokens: [CUSD[ChainId.Mainnet], AAUSDC[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0xF2ae5c2D2D2eD13dd324C0942163054fc4A3D4d9'.toLowerCase(), + // additionalRewards: [], + // }, + // }, + // { + // name: 'Poof cUSD V2', + // chain: Chain.Celo, + // peg: Dollar, + // warningType: WarningType.POOF, + // pool: { + // address: '0xa2F0E57d4cEAcF025E81C76f28b9Ad6E9Fbe8735'.toLowerCase(), + // lpToken: lp(ChainId.Mainnet, '0x07e137E5605E15C93f22545868Fa70CECfCbbFFE'.toLowerCase(), 'Mobius cUSD/pUSD LP'), + // tokens: [CUSD[ChainId.Mainnet], PUSD[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0xE7195E651Cc47853f0054d85c8ADFc79D532929f'.toLowerCase(), + // additionalRewards: [new TokenAmount(POOF[ChainId.Mainnet], '6283068780000000')], + // }, + // }, + // { + // name: 'Poof CELO V2', + // chain: Chain.Celo, + // peg: Celo, + // warningType: WarningType.POOF, + // pool: { + // address: '0xFc9e2C63370D8deb3521922a7B2b60f4Cff7e75a'.toLowerCase(), + // lpToken: lp( + // ChainId.Mainnet, + // '0xAfFD8d6b5e5A0e25034DD3D075532F9CE01C305c'.toLowerCase(), + // 'Mobius cUSD/pCELO LP' + // ), + // tokens: [CUSD[ChainId.Mainnet], PCELO[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0xD0d57a6689188F854F996BEAE0Cb1949FDB5FF86'.toLowerCase(), + // additionalRewards: [new TokenAmount(POOF[ChainId.Mainnet], '6283068780000000')], + // }, + // }, + // { + // name: 'Poof cEUR V2', + // chain: Chain.Celo, + // peg: Euro, + // warningType: WarningType.POOF, + // pool: { + // address: '0x23C95678862a229fAC088bd9705622d78130bC3e'.toLowerCase(), + // lpToken: lp(ChainId.Mainnet, '0xec8e37876Fd9De919B58788B87A078e546149F87'.toLowerCase(), 'Mobius cUSD/pEUR LP'), + // tokens: [CEUR[ChainId.Mainnet], PEUR[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0xCAEd243de23264Bdd8297c6eECcF320846eee18A'.toLowerCase(), + // additionalRewards: [new TokenAmount(POOF[ChainId.Mainnet], '6283068780000000')], + // }, + // }, + // { + // name: 'Poof cUSD V1', + // chain: Chain.Celo, + // peg: Dollar, + // warningType: WarningType.POOF, + // pool: { + // address: '0x02Db089fb09Fda92e05e92aFcd41D9AAfE9C7C7C'.toLowerCase(), + // lpToken: lp(ChainId.Mainnet, '0x18d71b8664E69D6Dd61C79247dBf12bFAaf66C10'.toLowerCase(), 'Mobius cUSD/pUSD LP'), + // tokens: [CUSD[ChainId.Mainnet], PUSD1[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0x2459BDb59a3BF6Ab6C412Ac0b220e7CDA1D4ea26'.toLowerCase(), + // additionalRewards: [], + // }, + // }, + // { + // name: 'asUSDC (Allbridge)', + // chain: Chain.Solana, + // peg: Dollar, + // pool: { + // address: '0x63C1914bf00A9b395A2bF89aaDa55A5615A3656e'.toLowerCase(), + // lpToken: lp( + // ChainId.Mainnet, + // '0xAFEe90ab6A2D3B265262f94F6e437E7f6d94e26E'.toLowerCase(), + // 'Mobius cUSD/asUSDC LP' + // ), + // tokens: [CUSD[ChainId.Mainnet], ASUSDC[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0x27D9Bfa5F864862BeDC23cFab7e00b6b94488CC6'.toLowerCase(), + // additionalRewards: [new TokenAmount(CELO[ChainId.Mainnet], weeklyEmissionToSeconds(3780))], + // }, + // }, + // { + // name: 'pUSDC (Optics V1)', + // chain: Chain.Polygon, + // peg: Dollar, + // pool: { + // address: '0x2080AAa167e2225e1FC9923250bA60E19a180Fb2'.toLowerCase(), + // lpToken: lp( + // ChainId.Mainnet, + // '0xf5b454cF47Caca418D95930AA03975Ee4bf409bc'.toLowerCase(), + // 'Mobius cUSD/pUSDC LP' + // ), + // tokens: [CUSD[ChainId.Mainnet], PUSDC1[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0x52517feb1Fc6141d5CF6718111C7Cc0FD764fA5d'.toLowerCase(), + // additionalRewards: [], + // }, + // }, + // { + // name: 'wBTC (Optics V1)', + // chain: Chain.Ethereum, + // peg: Bitcoin, + // pool: { + // address: '0x19260b9b573569dDB105780176547875fE9fedA3'.toLowerCase(), + // lpToken: lp(ChainId.Mainnet, '0x8cD0E2F11ed2E896a8307280dEEEE15B27e46BbE'.toLowerCase(), 'Mobius cBTC/wBTC LP'), + // tokens: [CBTC[ChainId.Mainnet], WBTC1[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0x1A8938a37093d34581B21bAd2AE7DC1c19150C05'.toLowerCase(), + // additionalRewards: [], + // }, + // }, + // { + // name: 'wETH (Optics V1)', + // chain: Chain.Ethereum, + // peg: Ether, + // pool: { + // address: '0xE0F2cc70E52f05eDb383313393d88Df2937DA55a'.toLowerCase(), + // lpToken: lp(ChainId.Mainnet, '0x846b784Ab5302155542c1B3952B54305F220fd84'.toLowerCase(), 'Mobius cETH/wETH LP'), + // tokens: [CETH[ChainId.Mainnet], WETH1[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0xD38e76E17E66b562B61c149Ca0EE53CEa1145733'.toLowerCase(), + // additionalRewards: [], + // }, + // }, + // { + // name: 'USDT (Moss)', + // chain: Chain.Ethereum, + // peg: Dollar, + // pool: { + // address: '0xdBF27fD2a702Cc02ac7aCF0aea376db780D53247'.toLowerCase(), + // lpToken: lp( + // ChainId.Mainnet, + // '0xC7a4c6EF4A16Dc24634Cc2A951bA5Fec4398f7e0'.toLowerCase(), + // 'Mobius cUSD/cUSDT LP' + // ), + // tokens: [CUSD[ChainId.Mainnet], USDTM[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0xe2d6095685248F38Ae9fef1b360D772b78Ea19D1'.toLowerCase(), + // additionalRewards: [], + // }, + // }, + // { + // name: 'USDC (Moss)', + // chain: Chain.Ethereum, + // peg: Dollar, + // pool: { + // address: '0x0ff04189Ef135b6541E56f7C638489De92E9c778'.toLowerCase(), + // lpToken: lp( + // ChainId.Mainnet, + // '0x635aec36c4b61bac5eB1C3EEe191147d006F8a21'.toLowerCase(), + // 'Mobius cUSD/cUSDC LP' + // ), + // tokens: [CUSD[ChainId.Mainnet], USDCM[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0xd1B3C05FE24bda6F52e704daf1ACBa8c440d8573'.toLowerCase(), + // additionalRewards: [], + // }, + // }, + // { + // name: 'Poof Celo V1', + // chain: Chain.Celo, + // peg: Celo, + // warningType: WarningType.POOF, + // pool: { + // address: '0x413FfCc28e6cDDE7e93625Ef4742810fE9738578'.toLowerCase(), + // lpToken: lp( + // ChainId.Mainnet, + // '0x4D6B17828d0173668e8Eb730106444556a98c0F9'.toLowerCase(), + // 'Mobius Celo/pCelo LP' + // ), + // tokens: [CELO[ChainId.Mainnet], PCELO1[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0x5489b2F0A1992b889F47601D71E068Fd15c63f26'.toLowerCase(), + // additionalRewards: [], + // }, + // }, + // { + // name: 'Poof cEUR V1', + // chain: Chain.Celo, + // peg: Euro, + // warningType: WarningType.POOF, + // pool: { + // address: '0x382Ed834c6b7dBD10E4798B08889eaEd1455E820'.toLowerCase(), + // lpToken: lp(ChainId.Mainnet, '0x2642Ab16Bfb7A8b36EE42c9CbA2289C4Ca9F33b9'.toLowerCase(), 'Mobius cEUR/pEUR LP'), + // tokens: [CEUR[ChainId.Mainnet], PEUR1[ChainId.Mainnet]], + // }, + // gauge: { + // address: '0xCF34F4ec5DC9E09428A4f4a45475f6277694166c'.toLowerCase(), + // additionalRewards: [], + // }, + // }, ], [ChainId.Alfajores]: [], [ChainId.Baklava]: [], diff --git a/src/constants/tokens.ts b/src/constants/tokens.ts index 35d5e7e3b6e..e68336b2e40 100644 --- a/src/constants/tokens.ts +++ b/src/constants/tokens.ts @@ -278,18 +278,6 @@ export const PUSDC1 = makeTokens( 'https://bit.ly/3CwGimW' ) -export const CBTC1 = makeTokens( - { - [ChainId.Mainnet]: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', - [ChainId.Alfajores]: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', - [ChainId.Baklava]: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', - }, - 18, - 'cBTC', - 'Wrapped Bitcoin', - 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cBTC.png' -) - export const WBTC1 = makeTokens( { [ChainId.Mainnet]: '0xBe50a3013A1c94768A1ABb78c3cB79AB28fc1aCE', @@ -302,18 +290,6 @@ export const WBTC1 = makeTokens( 'https://etherscan.io/token/images/wbtc_28.png?v=1' ) -export const CETH1 = makeTokens( - { - [ChainId.Mainnet]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', - [ChainId.Alfajores]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', - [ChainId.Baklava]: '0x2DEf4285787d58a2f811AF24755A8150622f4361', - }, - 18, - 'cETH', - 'Wrapped Ethereum', - 'https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_cETH.svg' -) - export const WETH1 = makeTokens( { [ChainId.Mainnet]: '0xE919F65739c26a42616b7b8eedC6b5524d1e3aC4', @@ -338,7 +314,7 @@ export const USDTM = makeTokens( 'https://bit.ly/3AMrCyD' ) -export const USDTC = makeTokens( +export const USDCM = makeTokens( { [ChainId.Mainnet]: '0x93DB49bE12B864019dA9Cb147ba75cDC0506190e', [ChainId.Alfajores]: '0x93DB49bE12B864019dA9Cb147ba75cDC0506190e', diff --git a/src/pages/Pool/index.tsx b/src/pages/Pool/index.tsx index 8730bea726a..dce0e61847c 100644 --- a/src/pages/Pool/index.tsx +++ b/src/pages/Pool/index.tsx @@ -4,7 +4,7 @@ import { Chain, DisplayPool, IExchangeInfo, StablePools, Volume } from 'constant import { useValueOfAllPools } from 'hooks/useStablePools' import JSBI from 'jsbi' import { TokenAmount } from 'lib/token-utils' -import React from 'react' +import React, { useCallback, useMemo } from 'react' import { isMobile } from 'react-device-detect' import { useMobiPrice } from 'state/application/hooks' import { GaugeInfo, useAllGaugesInfo, useAllUserGaugesInfo, UserGaugeInfo } from 'state/gauges/hooks' @@ -84,16 +84,6 @@ export default function Pool() { const exchanges = usePools() const lpBalances = useAllLpBalances() const volumes = usePoolsVolume() - const meta: Meta[] = StablePools[CHAIN].map((el, i) => { - return { - display: el, - userGauge: userGauges[i], - gauge: gauges[i], - lpBalance: lpBalances[i], - exchangeInfo: exchanges[i], - volume: volumes[i], - } - }) const [selection, setSelection] = React.useState(SpecialChain.All) const [showDeprecated, setShowDeprecated] = React.useState(false) @@ -101,23 +91,43 @@ export default function Pool() { const tvl = useValueOfAllPools() const mobiprice = useMobiPrice() - const sortCallback = (pool1: Meta, pool2: Meta) => { + const meta: Meta[] = useMemo( + () => + StablePools[CHAIN].map((el, i) => { + return { + display: el, + userGauge: userGauges[i], + gauge: gauges[i], + lpBalance: lpBalances[i], + exchangeInfo: exchanges[i], + volume: volumes[i], + } + }), + [exchanges, gauges, lpBalances, userGauges, volumes] + ) + + const sortCallback = useCallback((pool1: Meta, pool2: Meta) => { const isStaking1 = pool1.lpBalance.greaterThan(0) || (pool1.userGauge && JSBI.greaterThan(pool1.userGauge.balance, JSBI.BigInt(0))) const isStaking2 = pool2.lpBalance.greaterThan(0) || (pool2.userGauge && JSBI.greaterThan(pool2.userGauge?.balance, JSBI.BigInt(0))) if (isStaking1 && !isStaking2) return 1 return -1 - } + }, []) - const sortedFilterdPools = meta - .sort(sortCallback) - .filter( - (pool) => - selection === SpecialChain.All || - selection === pool.display.chain || - (selection === SpecialChain.Other && OtherChains.has(pool.display.chain)) - ) + const sortedFilterdPools = useMemo( + () => + meta + .sort(sortCallback) + .filter( + (pool) => + selection === SpecialChain.All || + selection === pool.display.chain || + (selection === SpecialChain.Other && OtherChains.has(pool.display.chain)) + ), + [meta, selection, sortCallback] + ) + console.log('pools page') return ( diff --git a/src/state/application/updater.ts b/src/state/application/updater.ts index d63ed893a9e..9638b1c0183 100644 --- a/src/state/application/updater.ts +++ b/src/state/application/updater.ts @@ -53,6 +53,7 @@ export function PriceData(): null { const { data, loading, error } = useQuery(mobiPriceQuery, { client: ubeswapClient }) useEffect(() => { if (!loading && !error && data) { + console.log('price update') fetchPegPrices(dispatch) dispatch(addPrice({ token: mobi.address.toLowerCase(), price: data.token.derivedCUSD })) } @@ -104,6 +105,7 @@ export default function Updater(): null { useEffect(() => { if (!debouncedState.chainId || !debouncedState.blockNumber || !windowVisible) return + console.log('block update') dispatch(updateBlockNumber({ chainId: debouncedState.chainId, blockNumber: debouncedState.blockNumber })) }, [windowVisible, dispatch, debouncedState.blockNumber, debouncedState.chainId]) diff --git a/src/state/claim/updater.ts b/src/state/claim/updater.ts index 78cdf009ddf..483c862dd5f 100644 --- a/src/state/claim/updater.ts +++ b/src/state/claim/updater.ts @@ -28,6 +28,7 @@ export default function UpdateClaim(): null { JSBI.subtract(initialLocked, JSBI.BigInt(await vesting?.['lockedOf'](address))), unclaimed ) + console.log('claim update') dispatch( update({ type, diff --git a/src/state/gauges/updater.ts b/src/state/gauges/updater.ts index cc6e1dbcdaa..a18879a9beb 100644 --- a/src/state/gauges/updater.ts +++ b/src/state/gauges/updater.ts @@ -62,6 +62,7 @@ export function GaugeUpdater() { ) useEffect(() => { + console.log('gauge update') connected && dispatch( updateGaugesUser({ diff --git a/src/state/logs/updater.ts b/src/state/logs/updater.ts index 4b77ea09173..a4e58faa422 100644 --- a/src/state/logs/updater.ts +++ b/src/state/logs/updater.ts @@ -34,7 +34,7 @@ export default function Updater(): null { useEffect(() => { if (!provider || typeof blockNumber !== 'number' || filtersNeedFetch.length === 0) return - + console.log('log update') dispatch(fetchingLogs({ chainId: CHAIN, filters: filtersNeedFetch, blockNumber })) filtersNeedFetch.forEach((filter) => { provider diff --git a/src/state/mentoPools/updater.ts b/src/state/mentoPools/updater.ts index 55cdd53e429..4ab8a6e4b0b 100644 --- a/src/state/mentoPools/updater.ts +++ b/src/state/mentoPools/updater.ts @@ -32,6 +32,7 @@ export function UpdateMento() { const balances = (await contract.getBuyAndSellBuckets(false)).map((x) => JSBI.BigInt(x)) invariant(balances.length === 2, 'mento balances') const swapFee = JSBI.BigInt(await contract.spread()) + console.log('mento update') dispatch( updateMento({ mento: { diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index b556d73ea1f..78550658981 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -62,6 +62,7 @@ export function UpdatePools() { try { if (error) console.log(error) const volume = loading ? null : index(data.swaps) + console.log('pools update') dispatch( updatePools({ pools: stablePools.map((displayPool, i) => { diff --git a/src/state/multicall/updater.tsx b/src/state/multicall/updater.tsx index 3094da25d1f..7cc1b68c156 100644 --- a/src/state/multicall/updater.tsx +++ b/src/state/multicall/updater.tsx @@ -140,7 +140,7 @@ export default function Updater(): null { if (cancellations.current?.blockNumber !== latestBlockNumber) { cancellations.current?.cancellations?.forEach((c) => c()) } - + console.log('multicall update') dispatch( fetchingMulticallResults({ calls, diff --git a/src/state/openSum/updater.ts b/src/state/openSum/updater.ts index ec5f75bce74..5095239af10 100644 --- a/src/state/openSum/updater.ts +++ b/src/state/openSum/updater.ts @@ -26,7 +26,7 @@ export function UpdateOpenSum(): null { ConstantSumInterface, 'getBalances' ) - + console.log('migrate update') useMemo(() => { const balances = balancesMany?.map( ({ result }) => result?.[0].map((n) => BigIntToJSBI(n as BigInt, '0')) ?? [ZERO, ZERO] diff --git a/src/state/staking/updater.ts b/src/state/staking/updater.ts index 78c796c2dc1..c2f956ae143 100644 --- a/src/state/staking/updater.ts +++ b/src/state/staking/updater.ts @@ -46,6 +46,7 @@ export default function StakingUpdater() { (roundDate(Date.now()).valueOf() / 1000 - SECONDS_IN_WEEK).toFixed(0), ]) useEffect(() => { + console.log('staking update') connected && dispatch( updateStakingUser({ diff --git a/src/state/transactions/updater.tsx b/src/state/transactions/updater.tsx index 610a78c020b..743d73a839f 100644 --- a/src/state/transactions/updater.tsx +++ b/src/state/transactions/updater.tsx @@ -50,6 +50,7 @@ export default function Updater(): null { .getTransactionReceipt(hash) .then((receipt) => { if (receipt) { + console.log('transaction update') dispatch( finalizeTransaction({ chainId: CHAIN, diff --git a/src/state/user/updater.tsx b/src/state/user/updater.tsx index b8e60b5932e..59b664cf740 100644 --- a/src/state/user/updater.tsx +++ b/src/state/user/updater.tsx @@ -14,6 +14,7 @@ export default function Updater(): null { } const match = window?.matchMedia('(prefers-color-scheme: dark)') + console.log('user update') dispatch(updateMatchesDarkMode({ matchesDarkMode: match.matches })) if (match?.addListener) { From baa9a99a468bca7f5deec41a2bb0e23c2ea69b7b Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Tue, 8 Mar 2022 10:28:34 -0500 Subject: [PATCH 68/72] bug fix --- src/components/earn/StablePoolCard.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/earn/StablePoolCard.tsx b/src/components/earn/StablePoolCard.tsx index 6dad022a60b..1ca2d3fc1c2 100644 --- a/src/components/earn/StablePoolCard.tsx +++ b/src/components/earn/StablePoolCard.tsx @@ -272,7 +272,12 @@ export const StablePoolCard: React.FC = ({ meta, stakingInfo }: Props) => - + up to {apy.denominator.toString() !== '0' ? `${boostedApr.toFixed(1, { groupSeparator: ',' })}%` : ' -'} w/ boost From 25027d0e2f5f1557e258720a44b770a27f9510ec Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Thu, 10 Mar 2022 11:19:23 -0500 Subject: [PATCH 69/72] cleanup and backup subgraph --- src/state/application/actions.ts | 4 ---- src/state/application/hooks.ts | 16 ---------------- src/state/application/reducer.ts | 2 +- 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/src/state/application/actions.ts b/src/state/application/actions.ts index 8afb0e74804..acac85e2414 100644 --- a/src/state/application/actions.ts +++ b/src/state/application/actions.ts @@ -11,11 +11,7 @@ export type PopupContent = { export enum ApplicationModal { WALLET, SETTINGS, - SELF_CLAIM, - ADDRESS_CLAIM, - CLAIM_POPUP, MENU, - DELEGATE, VOTE, } diff --git a/src/state/application/hooks.ts b/src/state/application/hooks.ts index ffa35aaf470..ecb094ed133 100644 --- a/src/state/application/hooks.ts +++ b/src/state/application/hooks.ts @@ -44,22 +44,6 @@ export function useToggleSettingsMenu(): () => void { return useToggleModal(ApplicationModal.SETTINGS) } -export function useShowClaimPopup(): boolean { - return useModalOpen(ApplicationModal.CLAIM_POPUP) -} - -export function useToggleShowClaimPopup(): () => void { - return useToggleModal(ApplicationModal.CLAIM_POPUP) -} - -export function useToggleSelfClaimModal(): () => void { - return useToggleModal(ApplicationModal.SELF_CLAIM) -} - -export function useToggleDelegateModal(): () => void { - return useToggleModal(ApplicationModal.DELEGATE) -} - export function useToggleVoteModal(): () => void { return useToggleModal(ApplicationModal.VOTE) } diff --git a/src/state/application/reducer.ts b/src/state/application/reducer.ts index 4073057d313..25012f589bf 100644 --- a/src/state/application/reducer.ts +++ b/src/state/application/reducer.ts @@ -32,7 +32,7 @@ const initialState: ApplicationState = { openModal: null, tokenPrices: {}, ubeswapClient: new ApolloClient({ - uri: 'https://api.thegraph.com/subgraphs/name/ubeswap/ubeswap', + uri: 'https://api.thegraph.com/subgraphs/name/ubeswap/ubeswap-backup', cache: new InMemoryCache(), }), } From 3b4c1a541eb70f04f8bda9840005fa2f18b669b9 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Wed, 16 Mar 2022 10:44:50 -0400 Subject: [PATCH 70/72] price impact fix --- src/state/swap/hooks.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/state/swap/hooks.ts b/src/state/swap/hooks.ts index fb8e1906913..b261f73245a 100644 --- a/src/state/swap/hooks.ts +++ b/src/state/swap/hooks.ts @@ -9,6 +9,7 @@ import { useDispatch, useSelector } from 'react-redux' import { useCurrentPool, usePools } from 'state/mobiusPools/hooks' import invariant from 'tiny-invariant' +import { BIPS_BASE } from '../../constants' import { useWeb3Context } from '../../hooks' import { useCurrency } from '../../hooks/Tokens' import { isAddress } from '../../utils' @@ -212,7 +213,7 @@ export function useMobiusTradeInfo(): { const tradeData = calcInputOutput(inputCurrency, outputCurrency, parsedAmount, pool) - const basisPrice = calculateSwapPrice(pool) + const basisPrice = indexFrom === 1 ? calculateSwapPrice(pool) : calculateSwapPrice(pool).invert() const input = tradeData[0] const output = tradeData[1] const fee = tradeData[2] @@ -232,7 +233,10 @@ export function useMobiusTradeInfo(): { } const executionPrice = new Price(inputCurrency, outputCurrency, input?.raw, output?.raw) - const priceImpactFraction = basisPrice.subtract(executionPrice).divide(basisPrice) + const priceImpactFraction = basisPrice + .subtract(executionPrice) + .divide(basisPrice) + .subtract(pool.fees.trade.divide(BIPS_BASE).multiply('100')) const priceImpact = new Percent(priceImpactFraction.numerator, priceImpactFraction.denominator) const v2Trade: MobiusTrade | undefined = From 1ab0ebec1fb7fde1d1b6c03262dea7285ac9649c Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Wed, 16 Mar 2022 10:54:33 -0400 Subject: [PATCH 71/72] mento updater cleanup --- src/state/mentoPools/updater.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/state/mentoPools/updater.ts b/src/state/mentoPools/updater.ts index e98d1c4de94..c4141358107 100644 --- a/src/state/mentoPools/updater.ts +++ b/src/state/mentoPools/updater.ts @@ -16,7 +16,7 @@ import { updateMento } from './actions' import { stableToToken } from './hooks' export function UpdateMento() { - const { provider, kit } = useWeb3Context() + const { kit } = useWeb3Context() const blockNumber = useBlockNumber() const dispatch = useDispatch() const mentoPools = MENTO_POOL_INFO[CHAIN] @@ -49,7 +49,7 @@ export function UpdateMento() { const address = await kit.registry.addressFor(pool.contract) updatePool(pool, mentoContract?.attach(address) ?? null) }) - }, [blockNumber, provider, dispatch, kit.contracts, mentoContract, kit.registry, mentoPools]) + }, [blockNumber, dispatch, kit.contracts, mentoContract, kit.registry, mentoPools]) return null } From f9d24359dec7a52484e0a34f8cd44cf309c920c2 Mon Sep 17 00:00:00 2001 From: Kyle Scott Date: Wed, 23 Mar 2022 13:23:36 -0400 Subject: [PATCH 72/72] . --- src/hooks/web3/web3-context.tsx | 24 +++---- src/state/claim/updater.ts | 59 ++++++++--------- src/state/gauges/updater.ts | 107 +++++++++++++++---------------- src/state/mentoPools/updater.ts | 68 +++++++++----------- src/state/mobiusPools/updater.ts | 93 +++++++++++++-------------- src/state/multicall/hooks.ts | 42 +++--------- src/state/multicall/updater.tsx | 65 +++++++++++-------- src/state/openSum/updater.ts | 14 ++-- src/state/staking/updater.ts | 97 ++++++++++++++-------------- 9 files changed, 260 insertions(+), 309 deletions(-) diff --git a/src/hooks/web3/web3-context.tsx b/src/hooks/web3/web3-context.tsx index 8fd40eb5518..08917d3324f 100644 --- a/src/hooks/web3/web3-context.tsx +++ b/src/hooks/web3/web3-context.tsx @@ -1,7 +1,6 @@ import { ContractKit } from '@celo/contractkit' import { Connector, useContractKit, useProvider } from '@celo-tools/use-contractkit' import { Web3Provider } from '@ethersproject/providers' -import { useMemo } from 'react' import { CHAIN } from '../../constants' @@ -34,19 +33,16 @@ export const useWeb3Context = () => { connected = true address = uck.address } - return useMemo( - () => ({ - connect: uck.connect, - disconnect: uck.destroy, - kit: uck.kit, - provider, - connected, - address, - chainID, - providerChainID, - }), - [address, chainID, connected, provider, providerChainID, uck.connect, uck.destroy, uck.kit] - ) + return { + connect: uck.connect, + disconnect: uck.destroy, + kit: uck.kit, + provider, + connected, + address, + chainID, + providerChainID, + } } export const useAddress = () => { diff --git a/src/state/claim/updater.ts b/src/state/claim/updater.ts index 483c862dd5f..e8ea8def5f3 100644 --- a/src/state/claim/updater.ts +++ b/src/state/claim/updater.ts @@ -1,16 +1,9 @@ -import JSBI from 'jsbi' -import { useEffect } from 'react' import { useDispatch } from 'react-redux' -import { CHAIN } from '../../constants' -import { VestingAddresses } from '../../constants/tokens' -import { VestingEscrow } from '../../generated' import { useWeb3Context } from '../../hooks' import { useVestingContract } from '../../hooks/useContract' import useCurrentBlockTimestamp from '../../hooks/useCurrentBlockTimestamp' import { AppDispatch } from '../index' -import { update } from './actions' -import { VestType } from './reducer' export default function UpdateClaim(): null { const { address, connected, provider } = useWeb3Context() @@ -19,32 +12,32 @@ export default function UpdateClaim(): null { const claimContract = useVestingContract() // automatically update lists if versions are minor/patch - useEffect(() => { - const updateClaim = async (vesting: VestingEscrow | undefined, type: VestType) => { - if (!vesting || !connected) return - const initialLocked = JSBI.BigInt(await vesting?.['initial_locked'](address)) - const unclaimed = JSBI.BigInt(await vesting?.['balanceOf'](address)) - const claimed = JSBI.subtract( - JSBI.subtract(initialLocked, JSBI.BigInt(await vesting?.['lockedOf'](address))), - unclaimed - ) - console.log('claim update') - dispatch( - update({ - type, - claim: { - allocatedAmount: initialLocked, - claimedAmount: claimed, - unclaimedAmount: unclaimed, - }, - }) - ) - } - Object.entries(VestingAddresses).forEach(([type, addresses]) => { - const vestingContract = claimContract?.attach(addresses[CHAIN]) - updateClaim(vestingContract, parseInt(type)) - }) - }, [provider, blockNumber, claimContract, dispatch, connected, address]) + // useEffect(() => { + // const updateClaim = async (vesting: VestingEscrow | undefined, type: VestType) => { + // if (!vesting || !connected) return + // const initialLocked = JSBI.BigInt(await vesting?.['initial_locked'](address)) + // const unclaimed = JSBI.BigInt(await vesting?.['balanceOf'](address)) + // const claimed = JSBI.subtract( + // JSBI.subtract(initialLocked, JSBI.BigInt(await vesting?.['lockedOf'](address))), + // unclaimed + // ) + // console.log('claim update') + // dispatch( + // update({ + // type, + // claim: { + // allocatedAmount: initialLocked, + // claimedAmount: claimed, + // unclaimedAmount: unclaimed, + // }, + // }) + // ) + // } + // Object.entries(VestingAddresses).forEach(([type, addresses]) => { + // const vestingContract = claimContract?.attach(addresses[CHAIN]) + // updateClaim(vestingContract, parseInt(type)) + // }) + // }, [provider, blockNumber, claimContract, dispatch, connected, address]) return null } diff --git a/src/state/gauges/updater.ts b/src/state/gauges/updater.ts index a18879a9beb..db9fe388621 100644 --- a/src/state/gauges/updater.ts +++ b/src/state/gauges/updater.ts @@ -1,8 +1,6 @@ import { Interface } from '@ethersproject/abi' import { IGauge, StablePools } from 'constants/pools' import { useWeb3Context } from 'hooks' -import JSBI from 'jsbi' -import { useEffect } from 'react' import { useDispatch } from 'react-redux' import { AppDispatch } from 'state' import { useBlockNumber } from 'state/application/hooks' @@ -11,7 +9,6 @@ import { useMultipleContractSingleData, useSingleContractMultipleData } from 'st import { CHAIN } from '../../constants' import GAUGE_V3 from '../../constants/abis/LiquidityGaugeV3.json' import { useGaugeControllerContract } from '../../hooks/useContract' -import { updateGauges, updateGaugesUser } from './actions' const gaugeInterface = new Interface(GAUGE_V3.abi) @@ -61,58 +58,58 @@ export function GaugeUpdater() { gaugeAddresses.map((a) => [connected ? address : a, a]) ) - useEffect(() => { - console.log('gauge update') - connected && - dispatch( - updateGaugesUser({ - userGaugeState: StablePools[CHAIN].map((displayPool, i) => { - return displayPool.gauge === null - ? null - : { - balance: JSBI.BigInt(balance[i].result?.[0] ?? '0'), - claimableMobi: JSBI.BigInt(claimableMobi[i].result?.[0] ?? '0'), - lastVote: parseInt(lastVote[i].result?.[0].toString() ?? '0'), - powerAllocated: parseInt(slopes[i].result?.[1] ?? '0'), - effectiveBalance: JSBI.BigInt(effectiveBalances[i].result?.[0] ?? '0'), - } - }), - }) - ) - dispatch( - updateGauges({ - gaugeState: StablePools[CHAIN].map((display, i) => { - return display.gauge === null - ? null - : { - isKilled: isKilled[0].result?.[0] === true, - lastClaim: parseInt(lastClaims?.[i]?.result?.[0].toString() ?? '0'), - weight: JSBI.BigInt(weights[i].result?.[0] ?? 0), - futureWeight: JSBI.BigInt(futureWeights[i].result?.[0] ?? 0), - totalSupply: JSBI.BigInt(totalSupply[i].result?.[0] ?? 0), - workingSupply: JSBI.BigInt(workingSupply[i].result?.[0] ?? 0), - totalEffectiveBalance: JSBI.BigInt(totalEffectiveBalances[i].result?.[0] ?? 0), - } - }), - }) - ) - }, [ - connected, - dispatch, - blockNumber, - balance, - claimableMobi, - lastVote, - slopes, - isKilled, - lastClaims, - totalSupply, - workingSupply, - weights, - futureWeights, - effectiveBalances, - totalEffectiveBalances, - ]) + // useEffect(() => { + // console.log('gauge update') + // connected && + // dispatch( + // updateGaugesUser({ + // userGaugeState: StablePools[CHAIN].map((displayPool, i) => { + // return displayPool.gauge === null + // ? null + // : { + // balance: JSBI.BigInt(balance[i].result?.[0] ?? '0'), + // claimableMobi: JSBI.BigInt(claimableMobi[i].result?.[0] ?? '0'), + // lastVote: parseInt(lastVote[i].result?.[0].toString() ?? '0'), + // powerAllocated: parseInt(slopes[i].result?.[1] ?? '0'), + // effectiveBalance: JSBI.BigInt(effectiveBalances[i].result?.[0] ?? '0'), + // } + // }), + // }) + // ) + // dispatch( + // updateGauges({ + // gaugeState: StablePools[CHAIN].map((display, i) => { + // return display.gauge === null + // ? null + // : { + // isKilled: isKilled[0].result?.[0] === true, + // lastClaim: parseInt(lastClaims?.[i]?.result?.[0].toString() ?? '0'), + // weight: JSBI.BigInt(weights[i].result?.[0] ?? 0), + // futureWeight: JSBI.BigInt(futureWeights[i].result?.[0] ?? 0), + // totalSupply: JSBI.BigInt(totalSupply[i].result?.[0] ?? 0), + // workingSupply: JSBI.BigInt(workingSupply[i].result?.[0] ?? 0), + // totalEffectiveBalance: JSBI.BigInt(totalEffectiveBalances[i].result?.[0] ?? 0), + // } + // }), + // }) + // ) + // }, [ + // connected, + // dispatch, + // blockNumber, + // balance, + // claimableMobi, + // lastVote, + // slopes, + // isKilled, + // lastClaims, + // totalSupply, + // workingSupply, + // weights, + // futureWeights, + // effectiveBalances, + // totalEffectiveBalances, + // ]) return null } diff --git a/src/state/mentoPools/updater.ts b/src/state/mentoPools/updater.ts index c4141358107..c20f2c7593b 100644 --- a/src/state/mentoPools/updater.ts +++ b/src/state/mentoPools/updater.ts @@ -1,19 +1,11 @@ -import { CELO } from 'constants/tokens' -import { Exchange } from 'generated' -import JSBI from 'jsbi' -import { Percent, TokenAmount } from 'lib/token-utils' -import { useEffect } from 'react' import { useDispatch } from 'react-redux' import { useBlockNumber } from 'state/application/hooks' -import invariant from 'tiny-invariant' -import { CHAIN, weiScale } from '../../constants' -import { IMentoExchange, MENTO_POOL_INFO } from '../../constants/mento' +import { CHAIN } from '../../constants' +import { MENTO_POOL_INFO } from '../../constants/mento' import { useWeb3Context } from '../../hooks' import { useMentoContract } from '../../hooks/useContract' import { AppDispatch } from '../index' -import { updateMento } from './actions' -import { stableToToken } from './hooks' export function UpdateMento() { const { kit } = useWeb3Context() @@ -22,34 +14,34 @@ export function UpdateMento() { const mentoPools = MENTO_POOL_INFO[CHAIN] const mentoContract = useMentoContract('0x12364a15F52b822F12dd858FAeEdC49F472fbA57') - useEffect(() => { - const updatePool = async (poolInfo: IMentoExchange, contract: Exchange | null) => { - if (!contract) return - try { - const balances = (await contract.getBuyAndSellBuckets(false)).map((x) => JSBI.BigInt(x)) - invariant(balances.length === 2, 'mento balances') - const swapFee = JSBI.BigInt(await contract.spread()) - console.log('mento update') - dispatch( - updateMento({ - mento: { - ...poolInfo, - fee: new Percent(swapFee, JSBI.multiply(weiScale, JSBI.BigInt('10000'))), - address: contract.address, - celoReserve: new TokenAmount(CELO[CHAIN], balances[0]), - stableReserve: new TokenAmount(stableToToken(poolInfo.stable), balances[1]), - }, - }) - ) - } catch (error) { - console.error(error) - } - } - mentoPools.forEach(async (pool) => { - const address = await kit.registry.addressFor(pool.contract) - updatePool(pool, mentoContract?.attach(address) ?? null) - }) - }, [blockNumber, dispatch, kit.contracts, mentoContract, kit.registry, mentoPools]) + // useEffect(() => { + // const updatePool = async (poolInfo: IMentoExchange, contract: Exchange | null) => { + // if (!contract) return + // try { + // const balances = (await contract.getBuyAndSellBuckets(false)).map((x) => JSBI.BigInt(x)) + // invariant(balances.length === 2, 'mento balances') + // const swapFee = JSBI.BigInt(await contract.spread()) + // console.log('mento update') + // dispatch( + // updateMento({ + // mento: { + // ...poolInfo, + // fee: new Percent(swapFee, JSBI.multiply(weiScale, JSBI.BigInt('10000'))), + // address: contract.address, + // celoReserve: new TokenAmount(CELO[CHAIN], balances[0]), + // stableReserve: new TokenAmount(stableToToken(poolInfo.stable), balances[1]), + // }, + // }) + // ) + // } catch (error) { + // console.error(error) + // } + // } + // mentoPools.forEach(async (pool) => { + // const address = await kit.registry.addressFor(pool.contract) + // updatePool(pool, mentoContract?.attach(address) ?? null) + // }) + // }, [blockNumber, dispatch, kit.contracts, mentoContract, kit.registry, mentoPools]) return null } diff --git a/src/state/mobiusPools/updater.ts b/src/state/mobiusPools/updater.ts index 78550658981..e1a186bdb67 100644 --- a/src/state/mobiusPools/updater.ts +++ b/src/state/mobiusPools/updater.ts @@ -1,19 +1,14 @@ import { gql, useQuery } from '@apollo/client' import { Interface } from '@ethersproject/abi' -import { RECOMMENDED_AMP, RECOMMENDED_FEES, StablePools } from 'constants/pools' -import JSBI from 'jsbi' -import { TokenAmount } from 'lib/token-utils' -import { useEffect } from 'react' +import { StablePools } from 'constants/pools' import { useDispatch } from 'react-redux' import { useBlockNumber } from 'state/application/hooks' import { useMultipleContractSingleData } from 'state/multicall/hooks' -import { BigIntToJSBI } from 'state/openSum/updater' import { CHAIN } from '../../constants' import LP from '../../constants/abis/LPToken.json' import SWAP from '../../constants/abis/Swap.json' import { AppDispatch } from '../index' -import { updatePools } from './actions' const lpInterface = new Interface(LP.abi) const SwapInterface = new Interface(SWAP.abi) @@ -56,48 +51,48 @@ export function UpdatePools() { } ` const { data, loading, error } = useQuery(query) - useEffect(() => { - // const inSubgraph: Set = - // data?.swaps.reduce((accum: Set, cur: any) => new Set([...accum, cur.id]), new Set()) ?? new Set() - try { - if (error) console.log(error) - const volume = loading ? null : index(data.swaps) - console.log('pools update') - dispatch( - updatePools({ - pools: stablePools.map((displayPool, i) => { - return { - ...displayPool.pool, - fees: RECOMMENDED_FEES, - volume: - volume && volume[displayPool.pool.address] - ? { - total: volume[displayPool.pool.address].dailyVolumes.reduce( - (accum: number, el: any) => accum + parseFloat(el.volume), - 0 - ), - day: parseFloat(volume[displayPool.pool.address].dailyVolumes[0]?.volume ?? '0'), - week: parseFloat(volume[displayPool.pool.address].weeklyVolumes[0]?.volume ?? '0'), - } - : null, - ampFactor: RECOMMENDED_AMP, - lpTotalSupply: new TokenAmount( - displayPool.pool.lpToken, - JSBI.BigInt(lpTotalSupply[i]?.result?.[0] ?? '0') - ), - reserves: balances?.[i]?.result?.[0] - ? balances?.[i]?.result?.[0].map( - (amt: BigInt, j: number): TokenAmount => - new TokenAmount(displayPool.pool.tokens[j], BigIntToJSBI(amt)) - ) - : [new TokenAmount(displayPool.pool.tokens[0], '0'), new TokenAmount(displayPool.pool.tokens[1], '0')], - } - }), - }) - ) - } catch (error) { - console.error(error) - } - }, [dispatch, stablePools, lpTotalSupply, blockNumber, balances, error, loading, data]) + // useEffect(() => { + // // const inSubgraph: Set = + // // data?.swaps.reduce((accum: Set, cur: any) => new Set([...accum, cur.id]), new Set()) ?? new Set() + // try { + // if (error) console.log(error) + // const volume = loading ? null : index(data.swaps) + // console.log('pools update') + // dispatch( + // updatePools({ + // pools: stablePools.map((displayPool, i) => { + // return { + // ...displayPool.pool, + // fees: RECOMMENDED_FEES, + // volume: + // volume && volume[displayPool.pool.address] + // ? { + // total: volume[displayPool.pool.address].dailyVolumes.reduce( + // (accum: number, el: any) => accum + parseFloat(el.volume), + // 0 + // ), + // day: parseFloat(volume[displayPool.pool.address].dailyVolumes[0]?.volume ?? '0'), + // week: parseFloat(volume[displayPool.pool.address].weeklyVolumes[0]?.volume ?? '0'), + // } + // : null, + // ampFactor: RECOMMENDED_AMP, + // lpTotalSupply: new TokenAmount( + // displayPool.pool.lpToken, + // JSBI.BigInt(lpTotalSupply[i]?.result?.[0] ?? '0') + // ), + // reserves: balances?.[i]?.result?.[0] + // ? balances?.[i]?.result?.[0].map( + // (amt: BigInt, j: number): TokenAmount => + // new TokenAmount(displayPool.pool.tokens[j], BigIntToJSBI(amt)) + // ) + // : [new TokenAmount(displayPool.pool.tokens[0], '0'), new TokenAmount(displayPool.pool.tokens[1], '0')], + // } + // }), + // }) + // ) + // } catch (error) { + // console.error(error) + // } + // }, [dispatch, stablePools, lpTotalSupply, blockNumber, balances, error, loading, data]) return null } diff --git a/src/state/multicall/hooks.ts b/src/state/multicall/hooks.ts index 174ce372688..2767061cd26 100644 --- a/src/state/multicall/hooks.ts +++ b/src/state/multicall/hooks.ts @@ -51,6 +51,7 @@ export const NEVER_RELOAD: ListenerOptions = { // the lowest level call for subscribing to contract data function useCallsData(calls: (Call | undefined)[], options?: ListenerOptions): CallResult[] { + const chainId = CHAIN const callResults = useSelector( (state) => state.multicall.callResults ) @@ -70,11 +71,11 @@ function useCallsData(calls: (Call | undefined)[], options?: ListenerOptions): C // update listeners when there is an actual change that persists for at least 100ms useEffect(() => { const callKeys: string[] = JSON.parse(serializedCallKeys) - if (callKeys.length === 0) return undefined + if (!chainId || callKeys.length === 0) return undefined const calls = callKeys.map((key) => parseCallKey(key)) dispatch( addMulticallListeners({ - chainId: CHAIN, + chainId, calls, options, }) @@ -83,20 +84,20 @@ function useCallsData(calls: (Call | undefined)[], options?: ListenerOptions): C return () => { dispatch( removeMulticallListeners({ - chainId: CHAIN, + chainId, calls, options, }) ) } - }, [dispatch, options, serializedCallKeys]) + }, [chainId, dispatch, options, serializedCallKeys]) return useMemo( () => calls.map((call) => { - if (!call) return INVALID_RESULT + if (!chainId || !call) return INVALID_RESULT - const result = callResults[CHAIN]?.[toCallKey(call)] + const result = callResults[chainId]?.[toCallKey(call)] let data if (result?.data && result?.data !== '0x') { data = result.data @@ -104,7 +105,7 @@ function useCallsData(calls: (Call | undefined)[], options?: ListenerOptions): C return { valid: true, data, blockNumber: result?.blockNumber } }), - [callResults, calls] + [callResults, calls, chainId] ) } @@ -252,33 +253,6 @@ export function useSingleCallResult( const result = useCallsData(calls, options)[0] const latestBlockNumber = useBlockNumber() - // if (methodName === 'calculateTokenAmount') { - // console.log({ - // calls, - // fragment, - // result, - // inputs, - // }) - // } - // useEffect(() => { - // console.log({ calls }) - // }, [calls]) - // useEffect(() => { - // console.log({ fragment }) - // }, [fragment]) - // useEffect(() => { - // console.log({ result }) - // }, [result]) - // useEffect(() => { - // console.log({ inputs }) - // }, [inputs]) - // useEffect(() => { - // console.log({ methodName }) - // }, [methodName]) - // useEffect(() => { - // console.log({ latestBlockNumber }) - // }, [latestBlockNumber]) - return useMemo(() => { return toCallState(result, contract?.interface, fragment, latestBlockNumber) }, [result, contract, fragment, latestBlockNumber]) diff --git a/src/state/multicall/updater.tsx b/src/state/multicall/updater.tsx index 079632e6ad6..6d893ae912b 100644 --- a/src/state/multicall/updater.tsx +++ b/src/state/multicall/updater.tsx @@ -6,10 +6,16 @@ import { CHAIN } from '../../constants' import { useMulticallContract } from '../../hooks/useContract' import useDebounce from '../../hooks/useDebounce' import chunkArray from '../../utils/chunkArray' -import { CancelledError, retry } from '../../utils/retry' +import { CancelledError, retry, RetryableError } from '../../utils/retry' import { useBlockNumber } from '../application/hooks' import { AppDispatch, AppState } from '../index' -import { Call, fetchingMulticallResults, parseCallKey, updateMulticallResults } from './actions' +import { + Call, + errorFetchingMulticallResults, + fetchingMulticallResults, + parseCallKey, + updateMulticallResults, +} from './actions' // chunk calls so we do not exceed the gas limit const CALL_CHUNK_SIZE = 500 @@ -33,13 +39,13 @@ async function fetchChunk( ) } catch (error) { console.debug('Failed to fetch chunk inside retry', error) - // throw error + throw error } - // if (resultsBlockNumber.toNumber() < minBlockNumber) { - // console.debug(`Fetched results for old block number: ${resultsBlockNumber.toString()} vs. ${minBlockNumber}`) - // throw new RetryableError('Fetched for old block number') - // } - return { results: returnData, blockNumber: resultsBlockNumber } + if (resultsBlockNumber.toNumber() < minBlockNumber) { + console.debug(`Fetched results for old block number: ${resultsBlockNumber.toString()} vs. ${minBlockNumber}`) + throw new RetryableError('Fetched for old block number') + } + return { results: returnData, blockNumber: resultsBlockNumber.toNumber() } } /** @@ -108,28 +114,31 @@ export function outdatedListeningKeys( } export default function Updater(): null { + console.log('multicall updater') const dispatch = useDispatch() const state = useSelector((state) => state.multicall) // wait for listeners to settle before triggering updates const debouncedListeners = useDebounce(state.callListeners, 100) const latestBlockNumber = useBlockNumber() + const chainId = CHAIN const multicallContract = useMulticallContract() const cancellations = useRef<{ blockNumber: number; cancellations: (() => void)[] }>() const listeningKeys: { [callKey: string]: number } = useMemo(() => { - return activeListeningKeys(debouncedListeners, CHAIN) - }, [debouncedListeners]) + return activeListeningKeys(debouncedListeners, chainId) + }, [debouncedListeners, chainId]) const unserializedOutdatedCallKeys = useMemo(() => { - return outdatedListeningKeys(state.callResults, listeningKeys, CHAIN, latestBlockNumber) - }, [state.callResults, listeningKeys, latestBlockNumber]) + return outdatedListeningKeys(state.callResults, listeningKeys, chainId, latestBlockNumber) + }, [chainId, state.callResults, listeningKeys, latestBlockNumber]) const serializedOutdatedCallKeys = useMemo( () => JSON.stringify(unserializedOutdatedCallKeys.sort()), [unserializedOutdatedCallKeys] ) + useEffect(() => { - if (!latestBlockNumber || !multicallContract) return + if (!latestBlockNumber || !chainId || !multicallContract) return const outdatedCallKeys: string[] = JSON.parse(serializedOutdatedCallKeys) if (outdatedCallKeys.length === 0) return @@ -137,14 +146,14 @@ export default function Updater(): null { const chunkedCalls = chunkArray(calls, CALL_CHUNK_SIZE) - if (cancellations.current?.blockNumber !== latestBlockNumber) { + if (cancellations.current && latestBlockNumber - cancellations.current?.blockNumber > 2) { cancellations.current?.cancellations?.forEach((c) => c()) } - console.log('multicall update') + dispatch( fetchingMulticallResults({ calls, - chainId: CHAIN, + chainId, fetchingBlockNumber: latestBlockNumber, }) ) @@ -154,7 +163,7 @@ export default function Updater(): null { cancellations: chunkedCalls.map((chunk, index) => { const { cancel, promise } = retry(() => fetchChunk(multicallContract, chunk, latestBlockNumber), { n: Infinity, - minWait: 2500, + minWait: 1500, maxWait: 3500, }) promise @@ -164,10 +173,10 @@ export default function Updater(): null { // accumulates the length of all previous indices const firstCallKeyIndex = chunkedCalls.slice(0, index).reduce((memo, curr) => memo + curr.length, 0) const lastCallKeyIndex = firstCallKeyIndex + returnData.length - + console.log(3) dispatch( updateMulticallResults({ - chainId: CHAIN, + chainId, results: outdatedCallKeys .slice(firstCallKeyIndex, lastCallKeyIndex) .reduce<{ [callKey: string]: string | null }>((memo, callKey, i) => { @@ -183,19 +192,19 @@ export default function Updater(): null { console.debug('Cancelled fetch for blockNumber', latestBlockNumber) return } - console.error('Failed to fetch multicall chunk', chunk, CHAIN, error) - // dispatch( - // errorFetchingMulticallResults({ - // calls: chunk, - // chainId, - // fetchingBlockNumber: latestBlockNumber, - // }) - // ) + console.error('Failed to fetch multicall chunk', chunk, chainId, error) + dispatch( + errorFetchingMulticallResults({ + calls: chunk, + chainId, + fetchingBlockNumber: latestBlockNumber, + }) + ) }) return cancel }), } - }, [dispatch, latestBlockNumber, multicallContract, serializedOutdatedCallKeys]) + }, [chainId, multicallContract, dispatch, serializedOutdatedCallKeys, latestBlockNumber]) return null } diff --git a/src/state/openSum/updater.ts b/src/state/openSum/updater.ts index 5095239af10..5a91afb6662 100644 --- a/src/state/openSum/updater.ts +++ b/src/state/openSum/updater.ts @@ -1,14 +1,12 @@ import { Interface } from '@ethersproject/abi' import { ConstantSum, ConstantSumInfo } from 'constants/ConstantSum' import JSBI from 'jsbi' -import { useMemo } from 'react' import { useDispatch } from 'react-redux' import { useMultipleContractSingleData } from 'state/multicall/hooks' import { CHAIN } from '../../constants' import CONSTANT_SUM from '../../constants/abis/ConstantSum.json' import { AppDispatch } from '../index' -import { updateBalances } from './actions' export const BigIntToJSBI = (num: BigInt | undefined, fallBack = '0') => { return JSBI.BigInt(num?.toString() ?? fallBack) @@ -27,12 +25,12 @@ export function UpdateOpenSum(): null { 'getBalances' ) console.log('migrate update') - useMemo(() => { - const balances = balancesMany?.map( - ({ result }) => result?.[0].map((n) => BigIntToJSBI(n as BigInt, '0')) ?? [ZERO, ZERO] - ) - dispatch(updateBalances({ balances })) - }, [dispatch, balancesMany]) + // useMemo(() => { + // const balances = balancesMany?.map( + // ({ result }) => result?.[0].map((n) => BigIntToJSBI(n as BigInt, '0')) ?? [ZERO, ZERO] + // ) + // dispatch(updateBalances({ balances })) + // }, [dispatch, balancesMany]) return null } diff --git a/src/state/staking/updater.ts b/src/state/staking/updater.ts index c2f956ae143..98bd5f414e8 100644 --- a/src/state/staking/updater.ts +++ b/src/state/staking/updater.ts @@ -1,9 +1,7 @@ import { ExternalStakingRewards } from 'constants/staking' import { VEMOBI } from 'constants/tokens' import { useWeb3Context } from 'hooks' -import JSBI from 'jsbi' import { roundDate } from 'pages/Staking/Lock/Lock' -import { useEffect } from 'react' import { useDispatch } from 'react-redux' import { AppDispatch } from 'state' import { useSingleCallResult } from 'state/multicall/hooks' @@ -16,7 +14,6 @@ import { useStakingContract, useVotingEscrowContract, } from '../../hooks/useContract' -import { updateStaking, updateStakingUser } from './actions' export default function StakingUpdater() { const dispatch = useDispatch() @@ -45,53 +42,53 @@ export default function StakingUpdater() { const totalFeesThisWeek = useSingleCallResult(feeDistributorContract, 'tokens_per_week', [ (roundDate(Date.now()).valueOf() / 1000 - SECONDS_IN_WEEK).toFixed(0), ]) - useEffect(() => { - console.log('staking update') - connected && - dispatch( - updateStakingUser({ - userStakingState: { - voteUserPower: JSBI.BigInt(allocatedPower?.result?.[0] ?? '0'), - votingPower: JSBI.BigInt(votingPower?.result?.[0] ?? '0'), - claimableExternalRewards: JSBI.BigInt(snxToClaim?.result?.[0] ?? '0'), - claimableFees: JSBI.BigInt(feesToClaim?.result?.[0] ?? '0'), - lock: { - amount: JSBI.BigInt(locked?.result?.amount ?? '0'), - end: parseInt(locked?.result?.end.toString()) * 1000, // Need unix in milliseconds - }, - }, - }) - ) - dispatch( - updateStaking({ - stakingState: { - totalVotingPower: JSBI.BigInt(totalVotingPower?.result?.[0] ?? '0'), - totalWeight: JSBI.BigInt(totalWeight?.result?.[0] ?? '0'), - totalMobiLocked: JSBI.BigInt(totalMobiLocked?.result?.[0] ?? '0'), - externalRewardsRate: JSBI.BigInt(snxRewardRate?.result?.[0] ?? '0'), - feesThisWeek: JSBI.BigInt(totalFeesThisWeek?.result?.[0] ?? '0'), - feesNextWeek: JSBI.BigInt(totalFeesNextWeek?.result?.[0] ?? '0'), - mobiRate: JSBI.BigInt(mobiRate?.result?.[0] ?? '0'), - }, - }) - ) - }, [ - allocatedPower?.result, - connected, - dispatch, - feesToClaim?.result, - locked?.result?.amount, - locked?.result?.end, - mobiRate?.result, - snxRewardRate?.result, - snxToClaim?.result, - totalFeesNextWeek?.result, - totalFeesThisWeek?.result, - totalMobiLocked?.result, - totalVotingPower?.result, - totalWeight?.result, - votingPower?.result, - ]) + // useEffect(() => { + // console.log('staking update') + // connected && + // dispatch( + // updateStakingUser({ + // userStakingState: { + // voteUserPower: JSBI.BigInt(allocatedPower?.result?.[0] ?? '0'), + // votingPower: JSBI.BigInt(votingPower?.result?.[0] ?? '0'), + // claimableExternalRewards: JSBI.BigInt(snxToClaim?.result?.[0] ?? '0'), + // claimableFees: JSBI.BigInt(feesToClaim?.result?.[0] ?? '0'), + // lock: { + // amount: JSBI.BigInt(locked?.result?.amount ?? '0'), + // end: parseInt(locked?.result?.end.toString()) * 1000, // Need unix in milliseconds + // }, + // }, + // }) + // ) + // dispatch( + // updateStaking({ + // stakingState: { + // totalVotingPower: JSBI.BigInt(totalVotingPower?.result?.[0] ?? '0'), + // totalWeight: JSBI.BigInt(totalWeight?.result?.[0] ?? '0'), + // totalMobiLocked: JSBI.BigInt(totalMobiLocked?.result?.[0] ?? '0'), + // externalRewardsRate: JSBI.BigInt(snxRewardRate?.result?.[0] ?? '0'), + // feesThisWeek: JSBI.BigInt(totalFeesThisWeek?.result?.[0] ?? '0'), + // feesNextWeek: JSBI.BigInt(totalFeesNextWeek?.result?.[0] ?? '0'), + // mobiRate: JSBI.BigInt(mobiRate?.result?.[0] ?? '0'), + // }, + // }) + // ) + // }, [ + // allocatedPower?.result, + // connected, + // dispatch, + // feesToClaim?.result, + // locked?.result?.amount, + // locked?.result?.end, + // mobiRate?.result, + // snxRewardRate?.result, + // snxToClaim?.result, + // totalFeesNextWeek?.result, + // totalFeesThisWeek?.result, + // totalMobiLocked?.result, + // totalVotingPower?.result, + // totalWeight?.result, + // votingPower?.result, + // ]) return null }