utils#returnTokenFromKey TypeScript Examples
The following examples show how to use
utils#returnTokenFromKey.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SyrupAPR.tsx From interface-v2 with GNU General Public License v3.0 | 6 votes |
SyrupAPR: React.FC<{ syrup: SyrupInfo; dQUICKAPY: string }> = ({
syrup,
dQUICKAPY,
}) => {
const { palette } = useTheme();
const isDQUICKStakingToken = syrup.stakingToken.equals(
returnTokenFromKey('DQUICK'),
);
return (
<>
<Typography variant='body2' style={{ color: palette.success.main }}>
{getTokenAPRSyrup(syrup).toLocaleString()}%
</Typography>
{isDQUICKStakingToken && (
<Box display='flex'>
<Box
borderRadius='4px'
border={`1px solid ${palette.grey.A400}`}
padding='4px'
marginTop='4px'
display='flex'
alignItems='center'
>
<CurrencyLogo currency={returnTokenFromKey('QUICK')} size='12px' />
<Typography variant='caption' style={{ marginLeft: 4 }}>
{dQUICKAPY}% <span style={{ color: palette.text.hint }}>APY</span>
</Typography>
</Box>
</Box>
)}
</>
);
}
Example #2
Source File: hooks.ts From interface-v2 with GNU General Public License v3.0 | 6 votes |
export function useDQUICKtoQUICK() {
const lair = useLairContract();
const inputs = ['1000000000000000000'];
const dQuickToQuickState = useSingleCallResult(
lair,
'dQUICKForQUICK',
inputs,
);
if (dQuickToQuickState.loading || dQuickToQuickState.error) return 0;
return Number(
new TokenAmount(
returnTokenFromKey('QUICK'),
JSBI.BigInt(dQuickToQuickState?.result?.[0] ?? 0),
).toExact(),
);
}
Example #3
Source File: useUSDCPrice.ts From interface-v2 with GNU General Public License v3.0 | 6 votes |
export function useUSDCPricesToken(tokens: Token[]) {
const dQUICKtoQUICK = useDQUICKtoQUICK();
const [, quickUsdcPair] = usePair(
returnTokenFromKey('QUICK'),
returnTokenFromKey('USDC'),
);
const quickPrice = Number(
quickUsdcPair?.priceOf(returnTokenFromKey('QUICK'))?.toSignificant(6) ?? 0,
);
const filteredTokens = tokens
.filter((item, pos, self) => {
return self.findIndex((token) => token.equals(item)) == pos;
})
.filter(
(token) =>
!token.equals(returnTokenFromKey('QUICK')) &&
!token.equals(returnTokenFromKey('DQUICK')),
);
const currencies = filteredTokens.map((token) => unwrappedToken(token));
const usdPrices = useUSDCPrices(currencies);
const usdPricesWithToken = filteredTokens.map((token, index) => {
return { token, price: Number(usdPrices[index]?.toSignificant(6) ?? 0) };
});
return tokens.map((token) => {
if (token.equals(returnTokenFromKey('DQUICK'))) {
return dQUICKtoQUICK * quickPrice;
} else if (token.equals(returnTokenFromKey('QUICK'))) {
return quickPrice;
} else {
const priceObj = usdPricesWithToken.find((item) =>
item.token.equals(token),
);
return priceObj?.price ?? 0;
}
});
}
Example #4
Source File: index.ts From interface-v2 with GNU General Public License v3.0 | 5 votes |
GlobalData = {
bases: {
// used to construct intermediary pairs for trading
BASES_TO_CHECK_TRADES_AGAINST: {
...WETH_ONLY,
[ChainId.MATIC]: [
...WETH_ONLY[ChainId.MATIC],
returnTokenFromKey('USDC'),
returnTokenFromKey('USDT'),
returnTokenFromKey('QUICK'),
returnTokenFromKey('ETHER'),
returnTokenFromKey('WBTC'),
returnTokenFromKey('DAI'),
returnTokenFromKey('MAUSDC'),
returnTokenFromKey('MI'),
returnTokenFromKey('CXETH'),
returnTokenFromKey('GHST'),
],
},
// Some tokens can only be swapped via certain pairs, so we override the list of bases that are considered for these tokens.
CUSTOM_BASES: { [ChainId.MATIC]: undefined, [ChainId.MUMBAI]: undefined },
// used for display in the default list when adding liquidity
SUGGESTED_BASES: {
...WETH_ONLY,
[ChainId.MATIC]: [
...WETH_ONLY[ChainId.MATIC],
returnTokenFromKey('DAI'),
returnTokenFromKey('USDC'),
returnTokenFromKey('USDT'),
returnTokenFromKey('QUICK'),
returnTokenFromKey('ETHER'),
returnTokenFromKey('WBTC'),
returnTokenFromKey('SAND'),
returnTokenFromKey('MI'),
],
},
// used to construct the list of all pairs we consider by default in the frontend
BASES_TO_TRACK_LIQUIDITY_FOR: {
...WETH_ONLY,
[ChainId.MATIC]: [
...WETH_ONLY[ChainId.MATIC],
returnTokenFromKey('DAI'),
returnTokenFromKey('USDC'),
returnTokenFromKey('USDT'),
returnTokenFromKey('QUICK'),
returnTokenFromKey('ETHER'),
returnTokenFromKey('WBTC'),
],
},
},
pairs: {
PINNED_PAIRS: {
[ChainId.MATIC]: [
[returnTokenFromKey('USDC'), returnTokenFromKey('USDT')],
[returnTokenFromKey('USDC'), returnTokenFromKey('DAI')],
[returnTokenFromKey('ETHER'), returnTokenFromKey('USDC')],
[returnTokenFromKey('WBTC'), returnTokenFromKey('ETHER')],
[WETH[ChainId.MATIC], returnTokenFromKey('USDT')],
[WETH[ChainId.MATIC], returnTokenFromKey('USDC')],
[WETH[ChainId.MATIC], returnTokenFromKey('ETHER')],
[returnTokenFromKey('ETHER'), returnTokenFromKey('QUICK')],
],
[ChainId.MUMBAI]: undefined,
},
},
analytics: {
CHART_DURATIONS: [
GlobalConst.analyticChart.ONE_MONTH_CHART,
GlobalConst.analyticChart.THREE_MONTH_CHART,
GlobalConst.analyticChart.SIX_MONTH_CHART,
GlobalConst.analyticChart.ONE_YEAR_CHART,
GlobalConst.analyticChart.ALL_CHART,
],
CHART_DURATION_TEXTS: ['1M', '3M', '6M', '1Y', 'All'],
},
}
Example #5
Source File: hooks.ts From interface-v2 with GNU General Public License v3.0 | 5 votes |
export function useLairInfo(): LairInfo {
const { account } = useActiveWeb3React();
let accountArg = useMemo(() => [account ?? undefined], [account]);
const lair = useLairContract();
const quick = useQUICKContract();
const _dQuickTotalSupply = useSingleCallResult(lair, 'totalSupply', []);
const quickBalance = useSingleCallResult(lair, 'QUICKBalance', accountArg);
const dQuickBalance = useSingleCallResult(lair, 'balanceOf', accountArg);
accountArg = [GlobalConst.addresses.LAIR_ADDRESS ?? undefined];
const lairsQuickBalance = useSingleCallResult(quick, 'balanceOf', accountArg);
useEffect(() => {
getOneDayVolume();
}, []);
return useMemo(() => {
return {
lairAddress: GlobalConst.addresses.LAIR_ADDRESS,
dQUICKBalance: new TokenAmount(
returnTokenFromKey('DQUICK'),
JSBI.BigInt(dQuickBalance?.result?.[0] ?? 0),
),
QUICKBalance: new TokenAmount(
returnTokenFromKey('QUICK'),
JSBI.BigInt(quickBalance?.result?.[0] ?? 0),
),
totalQuickBalance: new TokenAmount(
returnTokenFromKey('QUICK'),
JSBI.BigInt(lairsQuickBalance?.result?.[0] ?? 0),
),
dQuickTotalSupply: new TokenAmount(
returnTokenFromKey('DQUICK'),
JSBI.BigInt(_dQuickTotalSupply?.result?.[0] ?? 0),
),
oneDayVol: oneDayVol,
};
}, [quickBalance, dQuickBalance, _dQuickTotalSupply, lairsQuickBalance]);
}
Example #6
Source File: AddLiquidity.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
AddLiquidity: React.FC<{
currency0?: Currency;
currency1?: Currency;
currencyBg?: string;
}> = ({ currency0, currency1, currencyBg }) => {
const classes = useStyles({});
const { palette } = useTheme();
const { t } = useTranslation();
const [addLiquidityErrorMessage, setAddLiquidityErrorMessage] = useState<
string | null
>(null);
const { account, chainId, library } = useActiveWeb3React();
const [showConfirm, setShowConfirm] = useState(false);
const [attemptingTxn, setAttemptingTxn] = useState(false);
const [txPending, setTxPending] = useState(false);
const [allowedSlippage] = useUserSlippageTolerance();
const deadline = useTransactionDeadline();
const [txHash, setTxHash] = useState('');
const addTransaction = useTransactionAdder();
const finalizedTransaction = useTransactionFinalizer();
const { independentField, typedValue, otherTypedValue } = useMintState();
const expertMode = useIsExpertMode();
const {
dependentField,
currencies,
pair,
pairState,
currencyBalances,
parsedAmounts,
price,
noLiquidity,
liquidityMinted,
poolTokenPercentage,
error,
} = useDerivedMintInfo();
const liquidityTokenData = {
amountA: formatTokenAmount(parsedAmounts[Field.CURRENCY_A]),
symbolA: currencies[Field.CURRENCY_A]?.symbol,
amountB: formatTokenAmount(parsedAmounts[Field.CURRENCY_B]),
symbolB: currencies[Field.CURRENCY_B]?.symbol,
};
const pendingText = t('supplyingTokens', liquidityTokenData);
const {
onFieldAInput,
onFieldBInput,
onCurrencySelection,
} = useMintActionHandlers(noLiquidity);
const maxAmounts: { [field in Field]?: TokenAmount } = [
Field.CURRENCY_A,
Field.CURRENCY_B,
].reduce((accumulator, field) => {
return {
...accumulator,
[field]: maxAmountSpend(currencyBalances[field]),
};
}, {});
const formattedAmounts = {
[independentField]: typedValue,
[dependentField]: noLiquidity
? otherTypedValue
: parsedAmounts[dependentField]?.toExact() ?? '',
};
const { ethereum } = window as any;
const toggleWalletModal = useWalletModalToggle();
const [approvingA, setApprovingA] = useState(false);
const [approvingB, setApprovingB] = useState(false);
const [approvalA, approveACallback] = useApproveCallback(
parsedAmounts[Field.CURRENCY_A],
chainId ? GlobalConst.addresses.ROUTER_ADDRESS[chainId] : undefined,
);
const [approvalB, approveBCallback] = useApproveCallback(
parsedAmounts[Field.CURRENCY_B],
chainId ? GlobalConst.addresses.ROUTER_ADDRESS[chainId] : undefined,
);
const userPoolBalance = useTokenBalance(
account ?? undefined,
pair?.liquidityToken,
);
const atMaxAmounts: { [field in Field]?: TokenAmount } = [
Field.CURRENCY_A,
Field.CURRENCY_B,
].reduce((accumulator, field) => {
return {
...accumulator,
[field]: maxAmounts[field]?.equalTo(parsedAmounts[field] ?? '0'),
};
}, {});
const handleCurrencyASelect = useCallback(
(currencyA: Currency) => {
onCurrencySelection(Field.CURRENCY_A, currencyA);
},
[onCurrencySelection],
);
const handleCurrencyBSelect = useCallback(
(currencyB: Currency) => {
onCurrencySelection(Field.CURRENCY_B, currencyB);
},
[onCurrencySelection],
);
useEffect(() => {
if (currency0) {
onCurrencySelection(Field.CURRENCY_A, currency0);
} else {
onCurrencySelection(Field.CURRENCY_A, Token.ETHER);
}
if (currency1) {
onCurrencySelection(Field.CURRENCY_B, currency1);
} else {
onCurrencySelection(Field.CURRENCY_B, returnTokenFromKey('QUICK'));
}
}, [onCurrencySelection, currency0, currency1]);
const onAdd = () => {
if (expertMode) {
onAddLiquidity();
} else {
setShowConfirm(true);
}
};
const router = useRouterContract();
const onAddLiquidity = async () => {
if (!chainId || !library || !account || !router) return;
const {
[Field.CURRENCY_A]: parsedAmountA,
[Field.CURRENCY_B]: parsedAmountB,
} = parsedAmounts;
if (
!parsedAmountA ||
!parsedAmountB ||
!currencies[Field.CURRENCY_A] ||
!currencies[Field.CURRENCY_B] ||
!deadline
) {
return;
}
const amountsMin = {
[Field.CURRENCY_A]: calculateSlippageAmount(
parsedAmountA,
noLiquidity ? 0 : allowedSlippage,
)[0],
[Field.CURRENCY_B]: calculateSlippageAmount(
parsedAmountB,
noLiquidity ? 0 : allowedSlippage,
)[0],
};
let estimate,
method: (...args: any) => Promise<TransactionResponse>,
args: Array<string | string[] | number>,
value: BigNumber | null;
if (
currencies[Field.CURRENCY_A] === ETHER ||
currencies[Field.CURRENCY_B] === ETHER
) {
const tokenBIsETH = currencies[Field.CURRENCY_B] === ETHER;
estimate = router.estimateGas.addLiquidityETH;
method = router.addLiquidityETH;
args = [
wrappedCurrency(
tokenBIsETH
? currencies[Field.CURRENCY_A]
: currencies[Field.CURRENCY_B],
chainId,
)?.address ?? '', // token
(tokenBIsETH ? parsedAmountA : parsedAmountB).raw.toString(), // token desired
amountsMin[
tokenBIsETH ? Field.CURRENCY_A : Field.CURRENCY_B
].toString(), // token min
amountsMin[
tokenBIsETH ? Field.CURRENCY_B : Field.CURRENCY_A
].toString(), // eth min
account,
deadline.toHexString(),
];
value = BigNumber.from(
(tokenBIsETH ? parsedAmountB : parsedAmountA).raw.toString(),
);
} else {
estimate = router.estimateGas.addLiquidity;
method = router.addLiquidity;
args = [
wrappedCurrency(currencies[Field.CURRENCY_A], chainId)?.address ?? '',
wrappedCurrency(currencies[Field.CURRENCY_B], chainId)?.address ?? '',
parsedAmountA.raw.toString(),
parsedAmountB.raw.toString(),
amountsMin[Field.CURRENCY_A].toString(),
amountsMin[Field.CURRENCY_B].toString(),
account,
deadline.toHexString(),
];
value = null;
}
setAttemptingTxn(true);
await estimate(...args, value ? { value } : {})
.then((estimatedGasLimit) =>
method(...args, {
...(value ? { value } : {}),
gasLimit: calculateGasMargin(estimatedGasLimit),
}).then(async (response) => {
setAttemptingTxn(false);
setTxPending(true);
const summary = t('addLiquidityTokens', liquidityTokenData);
addTransaction(response, {
summary,
});
setTxHash(response.hash);
try {
const receipt = await response.wait();
finalizedTransaction(receipt, {
summary,
});
setTxPending(false);
} catch (error) {
setTxPending(false);
setAddLiquidityErrorMessage(t('errorInTx'));
}
ReactGA.event({
category: 'Liquidity',
action: 'Add',
label: [
currencies[Field.CURRENCY_A]?.symbol,
currencies[Field.CURRENCY_B]?.symbol,
].join('/'),
});
}),
)
.catch((error) => {
setAttemptingTxn(false);
setAddLiquidityErrorMessage(t('txRejected'));
// we only care if the error is something _other_ than the user rejected the tx
if (error?.code !== 4001) {
console.error(error);
}
});
};
const connectWallet = () => {
if (ethereum && !isSupportedNetwork(ethereum)) {
addMaticToMetamask();
} else {
toggleWalletModal();
}
};
const handleDismissConfirmation = useCallback(() => {
setShowConfirm(false);
// if there was a tx hash, we want to clear the input
if (txHash) {
onFieldAInput('');
}
setTxHash('');
}, [onFieldAInput, txHash]);
const buttonText = useMemo(() => {
if (account) {
return error ?? t('supply');
} else if (ethereum && !isSupportedNetwork(ethereum)) {
return t('switchPolygon');
}
return t('connectWallet');
}, [account, ethereum, error, t]);
const modalHeader = () => {
return (
<Box>
<Box mt={10} mb={3} display='flex' justifyContent='center'>
<DoubleCurrencyLogo
currency0={currencies[Field.CURRENCY_A]}
currency1={currencies[Field.CURRENCY_B]}
size={48}
/>
</Box>
<Box mb={6} color={palette.text.primary} textAlign='center'>
<Typography variant='h6'>
{t('supplyingTokens', liquidityTokenData)}
<br />
{t('receiveLPTokens', {
amount: formatTokenAmount(liquidityMinted),
symbolA: currencies[Field.CURRENCY_A]?.symbol,
symbolB: currencies[Field.CURRENCY_B]?.symbol,
})}
</Typography>
</Box>
<Box mb={3} color={palette.text.secondary} textAlign='center'>
<Typography variant='body2'>
{t('outputEstimated', { slippage: allowedSlippage / 100 })}
</Typography>
</Box>
<Box className={classes.swapButtonWrapper}>
<Button onClick={onAddLiquidity}>{t('confirmSupply')}</Button>
</Box>
</Box>
);
};
return (
<Box>
{showConfirm && (
<TransactionConfirmationModal
isOpen={showConfirm}
onDismiss={handleDismissConfirmation}
attemptingTxn={attemptingTxn}
txPending={txPending}
hash={txHash}
content={() =>
addLiquidityErrorMessage ? (
<TransactionErrorContent
onDismiss={handleDismissConfirmation}
message={addLiquidityErrorMessage}
/>
) : (
<ConfirmationModalContent
title={t('supplyingliquidity')}
onDismiss={handleDismissConfirmation}
content={modalHeader}
/>
)
}
pendingText={pendingText}
modalContent={
txPending ? t('submittedTxLiquidity') : t('successAddedliquidity')
}
/>
)}
<CurrencyInput
id='add-liquidity-input-tokena'
title={`${t('token')} 1:`}
currency={currencies[Field.CURRENCY_A]}
showHalfButton={Boolean(maxAmounts[Field.CURRENCY_A])}
showMaxButton={!atMaxAmounts[Field.CURRENCY_A]}
onMax={() =>
onFieldAInput(maxAmounts[Field.CURRENCY_A]?.toExact() ?? '')
}
onHalf={() =>
onFieldAInput(
maxAmounts[Field.CURRENCY_A]
? (Number(maxAmounts[Field.CURRENCY_A]?.toExact()) / 2).toString()
: '',
)
}
handleCurrencySelect={handleCurrencyASelect}
amount={formattedAmounts[Field.CURRENCY_A]}
setAmount={onFieldAInput}
bgColor={currencyBg}
/>
<Box className={classes.exchangeSwap}>
<AddLiquidityIcon />
</Box>
<CurrencyInput
id='add-liquidity-input-tokenb'
title={`${t('token')} 2:`}
showHalfButton={Boolean(maxAmounts[Field.CURRENCY_B])}
currency={currencies[Field.CURRENCY_B]}
showMaxButton={!atMaxAmounts[Field.CURRENCY_B]}
onHalf={() =>
onFieldBInput(
maxAmounts[Field.CURRENCY_B]
? (Number(maxAmounts[Field.CURRENCY_B]?.toExact()) / 2).toString()
: '',
)
}
onMax={() =>
onFieldBInput(maxAmounts[Field.CURRENCY_B]?.toExact() ?? '')
}
handleCurrencySelect={handleCurrencyBSelect}
amount={formattedAmounts[Field.CURRENCY_B]}
setAmount={onFieldBInput}
bgColor={currencyBg}
/>
{currencies[Field.CURRENCY_A] &&
currencies[Field.CURRENCY_B] &&
pairState !== PairState.INVALID &&
price && (
<Box my={2}>
<Box className={classes.swapPrice}>
<Typography variant='body2'>
1 {currencies[Field.CURRENCY_A]?.symbol} ={' '}
{price.toSignificant(3)} {currencies[Field.CURRENCY_B]?.symbol}{' '}
</Typography>
<Typography variant='body2'>
1 {currencies[Field.CURRENCY_B]?.symbol} ={' '}
{price.invert().toSignificant(3)}{' '}
{currencies[Field.CURRENCY_A]?.symbol}{' '}
</Typography>
</Box>
<Box className={classes.swapPrice}>
<Typography variant='body2'>{t('yourPoolShare')}:</Typography>
<Typography variant='body2'>
{poolTokenPercentage
? poolTokenPercentage.toSignificant(6) + '%'
: '-'}
</Typography>
</Box>
<Box className={classes.swapPrice}>
<Typography variant='body2'>{t('lpTokenReceived')}:</Typography>
<Typography variant='body2'>
{formatTokenAmount(userPoolBalance)} {t('lpTokens')}
</Typography>
</Box>
</Box>
)}
<Box className={classes.swapButtonWrapper}>
{(approvalA === ApprovalState.NOT_APPROVED ||
approvalA === ApprovalState.PENDING ||
approvalB === ApprovalState.NOT_APPROVED ||
approvalB === ApprovalState.PENDING) &&
!error && (
<Box className={classes.approveButtons}>
{approvalA !== ApprovalState.APPROVED && (
<Box
width={approvalB !== ApprovalState.APPROVED ? '48%' : '100%'}
>
<Button
onClick={async () => {
setApprovingA(true);
try {
await approveACallback();
setApprovingA(false);
} catch (e) {
setApprovingA(false);
}
}}
disabled={approvingA || approvalA === ApprovalState.PENDING}
>
{approvalA === ApprovalState.PENDING
? `${t('approving')} ${
currencies[Field.CURRENCY_A]?.symbol
}`
: `${t('approve')} ${
currencies[Field.CURRENCY_A]?.symbol
}`}
</Button>
</Box>
)}
{approvalB !== ApprovalState.APPROVED && (
<Box
width={approvalA !== ApprovalState.APPROVED ? '48%' : '100%'}
>
<Button
onClick={async () => {
setApprovingB(true);
try {
await approveBCallback();
setApprovingB(false);
} catch (e) {
setApprovingB(false);
}
}}
disabled={approvingB || approvalB === ApprovalState.PENDING}
>
{approvalB === ApprovalState.PENDING
? `${t('approving')} ${
currencies[Field.CURRENCY_B]?.symbol
}`
: `${t('approve')} ${
currencies[Field.CURRENCY_B]?.symbol
}`}
</Button>
</Box>
)}
</Box>
)}
<Button
disabled={
Boolean(account) &&
(Boolean(error) ||
approvalA !== ApprovalState.APPROVED ||
approvalB !== ApprovalState.APPROVED)
}
onClick={account ? onAdd : connectWallet}
>
{buttonText}
</Button>
</Box>
</Box>
);
}
Example #7
Source File: StakeQuickModal.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
StakeQuickModal: React.FC<StakeQuickModalProps> = ({ open, onClose }) => {
const classes = useStyles();
const { palette } = useTheme();
const [attempting, setAttempting] = useState(false);
const { account } = useActiveWeb3React();
const addTransaction = useTransactionAdder();
const finalizedTransaction = useTransactionFinalizer();
const quickBalance = useCurrencyBalance(
account ?? undefined,
returnTokenFromKey('QUICK'),
);
const userLiquidityUnstaked = useTokenBalance(
account ?? undefined,
returnTokenFromKey('QUICK'),
);
const [typedValue, setTypedValue] = useState('');
const [stakePercent, setStakePercent] = useState(0);
const [approving, setApproving] = useState(false);
const { parsedAmount, error } = useDerivedLairInfo(
typedValue,
returnTokenFromKey('QUICK'),
userLiquidityUnstaked,
);
const lairContract = useLairContract();
const [approval, approveCallback] = useApproveCallback(
parsedAmount,
GlobalConst.addresses.LAIR_ADDRESS,
);
const onAttemptToApprove = async () => {
if (!lairContract) throw new Error('missing dependencies');
const liquidityAmount = parsedAmount;
if (!liquidityAmount) throw new Error('missing liquidity amount');
return approveCallback();
};
const onStake = async () => {
setAttempting(true);
if (lairContract && parsedAmount) {
if (approval === ApprovalState.APPROVED) {
try {
const response: TransactionResponse = await lairContract.enter(
`0x${parsedAmount.raw.toString(16)}`,
{
gasLimit: 350000,
},
);
addTransaction(response, {
summary: `Stake QUICK`,
});
const receipt = await response.wait();
finalizedTransaction(receipt, {
summary: `Deposit dQUICK`,
});
setAttempting(false);
setStakePercent(0);
setTypedValue('');
} catch (err) {
setAttempting(false);
}
} else {
setAttempting(false);
throw new Error(
'Attempting to stake without approval or a signature. Please contact support.',
);
}
}
};
return (
<CustomModal open={open} onClose={onClose}>
<Box paddingX={3} paddingY={4}>
<Box display='flex' alignItems='center' justifyContent='space-between'>
<Typography variant='h5'>Stake QUICK</Typography>
<CloseIcon style={{ cursor: 'pointer' }} onClick={onClose} />
</Box>
<Box
mt={3}
bgcolor={palette.background.default}
border='1px solid rgba(105, 108, 128, 0.12)'
borderRadius='10px'
padding='16px'
>
<Box
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body2'>QUICK</Typography>
<Typography variant='body2'>
Balance: {formatTokenAmount(quickBalance)}
</Typography>
</Box>
<Box mt={2} display='flex' alignItems='center'>
<NumericalInput
placeholder='0'
value={typedValue}
fontSize={28}
onUserInput={(value) => {
const totalBalance = quickBalance
? Number(quickBalance.toExact())
: 0;
setTypedValue(value);
setStakePercent(
totalBalance > 0 ? (Number(value) / totalBalance) * 100 : 0,
);
}}
/>
<Typography
variant='caption'
style={{
color: palette.primary.main,
fontWeight: 'bold',
cursor: 'pointer',
}}
onClick={() => {
setTypedValue(quickBalance ? quickBalance.toExact() : '0');
setStakePercent(100);
}}
>
MAX
</Typography>
</Box>
<Box display='flex' alignItems='center'>
<Box flex={1} mr={2} mt={0.5}>
<ColoredSlider
min={1}
max={100}
step={1}
value={stakePercent}
onChange={(evt: any, value) => {
setStakePercent(value as number);
setTypedValue(
quickBalance
? stakePercent < 100
? (
(Number(quickBalance.toExact()) * stakePercent) /
100
).toString()
: quickBalance.toExact()
: '0',
);
}}
/>
</Box>
<Typography variant='body2'>
{Math.min(stakePercent, 100).toLocaleString()}%
</Typography>
</Box>
</Box>
<Box
mt={3}
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Button
className={classes.stakeButton}
disabled={approving || approval !== ApprovalState.NOT_APPROVED}
onClick={async () => {
setApproving(true);
try {
await onAttemptToApprove();
setApproving(false);
} catch (e) {
setApproving(false);
}
}}
>
{approving ? 'Approving...' : 'Approve'}
</Button>
<Button
className={classes.stakeButton}
disabled={
!!error || attempting || approval !== ApprovalState.APPROVED
}
onClick={onStake}
>
{attempting ? 'Staking...' : 'Stake'}
</Button>
</Box>
</Box>
</CustomModal>
);
}
Example #8
Source File: ConvertQUICKPage.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
ConvertQUICKPage: React.FC = () => {
const classes = useStyles();
const { t } = useTranslation();
const { account, library } = useActiveWeb3React();
const [quickAmount, setQUICKAmount] = useState('');
const [quickV2Amount, setQUICKV2Amount] = useState('');
const [approving, setApproving] = useState(false);
const [attemptConverting, setAttemptConverting] = useState(false);
const [showConfirm, setShowConfirm] = useState(false);
const [txPending, setTxPending] = useState(false);
const [txHash, setTxHash] = useState('');
const [txError, setTxError] = useState('');
const quickToken = returnTokenFromKey('QUICK');
const quickBalance = useTokenBalance(account ?? undefined, quickToken);
const quickConvertContract = useQUICKConversionContract();
const parsedAmount = tryParseAmount(quickAmount, quickToken);
const [approval, approveCallback] = useApproveCallback(
parsedAmount,
quickConvertContract?.address,
);
const quickConvertingText = t('convertingQUICKtoQUICKV2', {
quickAmount,
quickV2Amount,
});
const quickConvertedText = t('convertedQUICKtoQUICKV2', {
quickAmount,
quickV2Amount,
});
const txSubmittedQuickConvertText = t('submittedTxQUICKConvert', {
quickAmount,
quickV2Amount,
});
const successQuickConvertedText = t('successConvertedQUICKtoQUICKV2', {
quickAmount,
quickV2Amount,
});
const isInsufficientQUICK =
Number(quickAmount) > Number(quickBalance?.toExact() ?? 0);
const buttonText = useMemo(() => {
if (!quickAmount || !Number(quickAmount)) {
return t('enterAmount');
} else if (approval !== ApprovalState.APPROVED) {
return t('approve');
} else if (isInsufficientQUICK) {
return t('insufficientBalance');
} else {
return t('convert');
}
}, [isInsufficientQUICK, quickAmount, t, approval]);
const addTransaction = useTransactionAdder();
const finalizedTransaction = useTransactionFinalizer();
const handleDismissConfirmation = () => {
setShowConfirm(false);
};
const attemptToApprove = async () => {
setApproving(true);
try {
await approveCallback();
setApproving(false);
} catch (e) {
setApproving(false);
}
};
const convertQUICK = async () => {
if (quickConvertContract && library && parsedAmount) {
setAttemptConverting(true);
setShowConfirm(true);
await quickConvertContract
.quickToQuickX(parsedAmount.raw.toString(), {
gasLimit: 300000,
})
.then(async (response: TransactionResponse) => {
setAttemptConverting(false);
setTxPending(true);
setTxError('');
setTxHash('');
addTransaction(response, {
summary: quickConvertingText,
});
try {
const tx = await response.wait();
finalizedTransaction(tx, {
summary: quickConvertedText,
});
setTxPending(false);
setTxHash(tx.transactionHash);
} catch (err) {
setTxPending(false);
setTxError(t('errorInTx'));
}
})
.catch(() => {
setAttemptConverting(false);
setTxPending(false);
setTxHash('');
setTxError(t('txRejected'));
});
}
};
return (
<Box width='100%' maxWidth={488} id='convertQUICKPage'>
<Typography variant='h4'>{t('convert')} QUICK</Typography>
<Box className={classes.wrapper}>
<Box display='flex' alignItems='center' mb={3}>
<Box className={classes.iconWrapper}>
<img src={QUICKIcon} alt='QUICK' />
</Box>
<Typography variant='h6'>QUICK(OLD)</Typography>
<Box mx={1.5} className={classes.convertArrow}>
<ArrowForward />
</Box>
<Box className={classes.iconWrapper}>
<QUICKV2Icon />
</Box>
<Typography variant='h6'>QUICK(NEW)</Typography>
</Box>
<Typography variant='body2' color='textSecondary'>
<Trans i18nKey='convertQuick'>
Convert your QUICK(OLD) to QUICK(NEW). Read more about QUICK token
split{' '}
<a
href='https://quickswap-layer2.medium.com/you-voted-for-a-1-1000-token-split-to-make-quick-more-appealing-9c25c2a2dd7e'
rel='noreferrer'
target='_blank'
>
here
</a>
</Trans>
</Typography>
<Box className={classes.conversionRate}>
<Typography variant='caption'>
{t('conversionRate')}: 1 QUICK(OLD) ={' '}
{GlobalConst.utils.QUICK_CONVERSION_RATE} QUICK(NEW)
</Typography>
</Box>
<Box mt={4} mb={2}>
<Typography variant='body2' color='textSecondary'>
{t('yourbalance')}: {formatTokenAmount(quickBalance)}
</Typography>
<Box
className={cx(
classes.currencyInput,
isInsufficientQUICK && classes.errorInput,
)}
>
<NumericalInput
placeholder='0.00'
value={quickAmount}
fontSize={18}
onUserInput={(value) => {
const digits =
value.indexOf('.') > -1 ? value.split('.')[1].length : 0;
let fixedVal = value;
if (digits > quickToken.decimals) {
fixedVal = Number(value).toFixed(quickToken.decimals);
}
setQUICKAmount(fixedVal);
setQUICKV2Amount(
(
Number(fixedVal) * GlobalConst.utils.QUICK_CONVERSION_RATE
).toLocaleString('fullwide', {
useGrouping: false,
maximumFractionDigits: quickToken.decimals,
}),
);
}}
/>
<Box
mr={1}
className={classes.maxButton}
onClick={() => {
if (quickBalance) {
setQUICKAmount(quickBalance.toExact());
setQUICKV2Amount(
(
Number(quickBalance.toExact()) *
GlobalConst.utils.QUICK_CONVERSION_RATE
).toString(),
);
}
}}
>
{t('max')}
</Box>
<Typography variant='h6'>QUICK(OLD)</Typography>
</Box>
{isInsufficientQUICK && (
<Typography variant='body2' className={classes.errorText}>
{t('insufficientBalance', { symbol: 'QUICK' })}
</Typography>
)}
</Box>
<Box ml={2} className={classes.convertArrow}>
<ArrowDownward />
</Box>
<Box mt={2} mb={4}>
<Typography variant='body2' color='textSecondary'>
{t('youwillreceive')}:
</Typography>
<Box className={classes.currencyInput}>
<NumericalInput
placeholder='0.00'
value={quickV2Amount}
fontSize={18}
onUserInput={(value) => {
setQUICKV2Amount(value);
const quickAmount = (
Number(value) / GlobalConst.utils.QUICK_CONVERSION_RATE
).toLocaleString('fullwide', {
useGrouping: false,
maximumFractionDigits: quickToken.decimals,
});
setQUICKAmount(quickAmount);
}}
/>
<Typography variant='h6'>QUICK(NEW)</Typography>
</Box>
</Box>
<Box display='flex' justifyContent='center'>
<Button
disabled={
approving ||
attemptConverting ||
isInsufficientQUICK ||
!quickAmount ||
!Number(quickAmount)
}
className={classes.convertButton}
onClick={() => {
if (approval === ApprovalState.APPROVED) {
convertQUICK();
} else {
attemptToApprove();
}
}}
>
{buttonText}
</Button>
</Box>
</Box>
{showConfirm && (
<TransactionConfirmationModal
isOpen={showConfirm}
onDismiss={handleDismissConfirmation}
attemptingTxn={attemptConverting}
txPending={txPending}
hash={txHash}
content={() =>
txError ? (
<TransactionErrorContent
onDismiss={handleDismissConfirmation}
message={txError}
/>
) : (
<ConfirmationModalContent
title={t('convertingQUICK')}
onDismiss={handleDismissConfirmation}
content={() => (
<Box textAlign='center'>
<Box mt={6} mb={5}>
<CircularProgress size={80} />
</Box>
<Typography variant='body1'>
{quickConvertingText}
</Typography>
</Box>
)}
/>
)
}
pendingText={quickConvertingText}
modalContent={
txPending ? txSubmittedQuickConvertText : successQuickConvertedText
}
/>
)}
</Box>
);
}
Example #9
Source File: DragonsLair.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
DragonsLair: React.FC = () => {
const classes = useStyles();
const { palette } = useTheme();
const quickPrice = useUSDCPriceToken(returnTokenFromKey('QUICK'));
const dQUICKPrice = useUSDCPriceToken(returnTokenFromKey('DQUICK'));
const dQUICKtoQUICK = dQUICKPrice / quickPrice;
const QUICKtodQUICK = quickPrice / dQUICKPrice;
const [isQUICKRate, setIsQUICKRate] = useState(false);
const [openStakeModal, setOpenStakeModal] = useState(false);
const [openUnstakeModal, setOpenUnstakeModal] = useState(false);
const lairInfo = useLairInfo();
const APY = useLairDQUICKAPY(lairInfo);
return (
<Box position='relative' zIndex={3}>
{openStakeModal && (
<StakeQuickModal
open={openStakeModal}
onClose={() => setOpenStakeModal(false)}
/>
)}
{openUnstakeModal && (
<UnstakeQuickModal
open={openUnstakeModal}
onClose={() => setOpenUnstakeModal(false)}
/>
)}
<Box display='flex'>
<CurrencyLogo currency={returnTokenFromKey('QUICK')} size='32px' />
<Box ml={1.5}>
<Typography
variant='body2'
style={{ color: palette.text.primary, lineHeight: 1 }}
>
QUICK
</Typography>
<Typography variant='caption' style={{ color: palette.text.hint }}>
Single Stake — Auto compounding
</Typography>
</Box>
</Box>
<Box display='flex' justifyContent='space-between' mt={1.5}>
<Typography variant='body2'>Total QUICK</Typography>
<Typography variant='body2'>
{lairInfo
? lairInfo.totalQuickBalance.toFixed(2, {
groupSeparator: ',',
})
: 0}
</Typography>
</Box>
<Box display='flex' justifyContent='space-between' mt={1.5}>
<Typography variant='body2'>TVL:</Typography>
<Typography variant='body2'>
$
{(
Number(lairInfo.totalQuickBalance.toExact()) * quickPrice
).toLocaleString()}
</Typography>
</Box>
<Box display='flex' justifyContent='space-between' mt={1.5}>
<Typography variant='body2'>APY</Typography>
<Typography variant='body2' style={{ color: palette.success.main }}>
{APY}%
</Typography>
</Box>
<Box display='flex' justifyContent='space-between' mt={1.5}>
<Typography variant='body2'>Your Deposits</Typography>
<Typography variant='body2'>
{formatTokenAmount(lairInfo.QUICKBalance)}
</Typography>
</Box>
<Box
mt={2.5}
width={1}
height='40px'
display='flex'
alignItems='center'
justifyContent='center'
borderRadius={10}
border={`1px solid ${palette.secondary.light}`}
>
<CurrencyLogo currency={returnTokenFromKey('QUICK')} />
<Typography variant='body2' style={{ margin: '0 8px' }}>
{isQUICKRate ? 1 : dQUICKtoQUICK.toLocaleString()} QUICK =
</Typography>
<CurrencyLogo currency={returnTokenFromKey('QUICK')} />
<Typography variant='body2' style={{ margin: '0 8px' }}>
{isQUICKRate ? QUICKtodQUICK.toLocaleString() : 1} dQUICK
</Typography>
<PriceExchangeIcon
style={{ cursor: 'pointer' }}
onClick={() => setIsQUICKRate(!isQUICKRate)}
/>
</Box>
<Box
className={classes.stakeButton}
bgcolor={palette.primary.main}
onClick={() => setOpenStakeModal(true)}
>
<Typography variant='body2'>Stake</Typography>
</Box>
<Box
className={classes.stakeButton}
bgcolor='transparent'
onClick={() => setOpenUnstakeModal(true)}
>
<Typography variant='body2'>Unstake</Typography>
</Box>
<Box mt={3} textAlign='center'>
<Typography
variant='caption'
style={{ color: palette.text.secondary, fontWeight: 500 }}
>
⭐️ When you unstake, the contract will automatically claim QUICK on
your behalf.
</Typography>
</Box>
</Box>
);
}
Example #10
Source File: hooks.ts From interface-v2 with GNU General Public License v3.0 | 4 votes |
// gets the dual rewards staking info from the network for the active chain id
export function useDualStakingInfo(
pairToFilterBy?: Pair | null,
startIndex?: number,
endIndex?: number,
filter?: { search: string; isStaked: boolean },
): DualStakingInfo[] {
const { chainId, account } = useActiveWeb3React();
const info = useMemo(
() =>
chainId
? returnDualStakingInfo()
[chainId]?.slice(startIndex, endIndex)
?.filter((stakingRewardInfo) =>
pairToFilterBy === undefined || pairToFilterBy === null
? getSearchFiltered(
stakingRewardInfo,
filter ? filter.search : '',
)
: pairToFilterBy.involvesToken(stakingRewardInfo.tokens[0]) &&
pairToFilterBy.involvesToken(stakingRewardInfo.tokens[1]),
) ?? []
: [],
[chainId, pairToFilterBy, startIndex, endIndex, filter],
);
const uni = chainId ? GlobalValue.tokens.UNI[chainId] : undefined;
const rewardsAddresses = useMemo(
() => info.map(({ stakingRewardAddress }) => stakingRewardAddress),
[info],
);
// const pairAddresses = useMemo(() => info.map(({ pair }) => pair), [info]);
// useEffect(() => {
// getDualBulkPairData(pairAddresses);
// }, [pairAddresses]);
const accountArg = useMemo(() => [account ?? undefined], [account]);
// get all the info from the staking rewards contracts
const balances = useMultipleContractSingleData(
rewardsAddresses,
STAKING_DUAL_REWARDS_INTERFACE,
'balanceOf',
accountArg,
);
const earnedAAmounts = useMultipleContractSingleData(
rewardsAddresses,
STAKING_DUAL_REWARDS_INTERFACE,
'earnedA',
accountArg,
);
const earnedBAmounts = useMultipleContractSingleData(
rewardsAddresses,
STAKING_DUAL_REWARDS_INTERFACE,
'earnedB',
accountArg,
);
const totalSupplies = useMultipleContractSingleData(
rewardsAddresses,
STAKING_DUAL_REWARDS_INTERFACE,
'totalSupply',
);
const rewardRatesA = useMultipleContractSingleData(
rewardsAddresses,
STAKING_DUAL_REWARDS_INTERFACE,
'rewardRateA',
undefined,
NEVER_RELOAD,
);
const rewardRatesB = useMultipleContractSingleData(
rewardsAddresses,
STAKING_DUAL_REWARDS_INTERFACE,
'rewardRateB',
undefined,
NEVER_RELOAD,
);
const baseTokens = info.map((item) => {
const unwrappedCurrency = unwrappedToken(item.baseToken);
const empty = unwrappedToken(returnTokenFromKey('EMPTY'));
return unwrappedCurrency === empty ? item.tokens[0] : item.baseToken;
});
const usdPrices = useUSDCPrices(baseTokens);
const totalSupplys = useTotalSupplys(
info.map((item) => getFarmLPToken(item)),
);
const stakingPairs = usePairs(info.map((item) => item.tokens));
const rewardTokenAPrices = useUSDCPricesToken(
info.map((item) => item.rewardTokenA),
);
const rewardTokenBPrices = useUSDCPricesToken(
info.map((item) => item.rewardTokenB),
);
return useMemo(() => {
if (!chainId || !uni) return [];
return rewardsAddresses.reduce<DualStakingInfo[]>(
(memo, rewardsAddress, index) => {
// these two are dependent on account
const balanceState = balances[index];
const earnedAAmountState = earnedAAmounts[index];
const earnedBAmountState = earnedBAmounts[index];
// these get fetched regardless of account
const totalSupplyState = totalSupplies[index];
const rewardRateAState = rewardRatesA[index];
const rewardRateBState = rewardRatesB[index];
const stakingInfo = info[index];
const rewardTokenAPrice = rewardTokenAPrices[index];
const rewardTokenBPrice = rewardTokenBPrices[index];
if (
// these may be undefined if not logged in
!balanceState?.loading &&
!earnedAAmountState?.loading &&
!earnedBAmountState?.loading &&
// always need these
totalSupplyState &&
!totalSupplyState.loading &&
rewardRateAState &&
!rewardRateAState.loading &&
rewardRateBState &&
!rewardRateBState.loading
) {
const rateA = web3.utils.toWei(stakingInfo.rateA.toString());
const rateB = web3.utils.toWei(stakingInfo.rateB.toString());
const stakedAmount = initTokenAmountFromCallResult(
getFarmLPToken(stakingInfo),
balanceState,
);
const totalStakedAmount = initTokenAmountFromCallResult(
getFarmLPToken(stakingInfo),
totalSupplyState,
);
const totalRewardRateA = new TokenAmount(uni, JSBI.BigInt(rateA));
const totalRewardRateB = new TokenAmount(uni, JSBI.BigInt(rateB));
//const pair = info[index].pair.toLowerCase();
//const fees = (pairData && pairData[pair] ? pairData[pair].oneDayVolumeUSD * 0.0025: 0);
const totalRewardRateA01 = initTokenAmountFromCallResult(
uni,
rewardRateAState,
);
const totalRewardRateB01 = initTokenAmountFromCallResult(
uni,
rewardRateBState,
);
const getHypotheticalRewardRate = (
stakedAmount?: TokenAmount,
totalStakedAmount?: TokenAmount,
totalRewardRate?: TokenAmount,
): TokenAmount | undefined => {
if (!stakedAmount || !totalStakedAmount || !totalRewardRate) return;
return new TokenAmount(
uni,
JSBI.greaterThan(totalStakedAmount.raw, JSBI.BigInt(0))
? JSBI.divide(
JSBI.multiply(totalRewardRate.raw, stakedAmount.raw),
totalStakedAmount.raw,
)
: JSBI.BigInt(0),
);
};
const individualRewardRateA = getHypotheticalRewardRate(
stakedAmount,
totalStakedAmount,
totalRewardRateA01,
);
const individualRewardRateB = getHypotheticalRewardRate(
stakedAmount,
totalStakedAmount,
totalRewardRateB01,
);
const { oneDayFee, accountFee } = getStakingFees(
stakingInfo,
balanceState,
totalSupplyState,
);
let valueOfTotalStakedAmountInBaseToken: TokenAmount | undefined;
const [, stakingTokenPair] = stakingPairs[index];
const totalSupply = totalSupplys[index];
const usdPrice = usdPrices[index];
if (
totalSupply &&
stakingTokenPair &&
baseTokens[index] &&
totalStakedAmount
) {
// take the total amount of LP tokens staked, multiply by ETH value of all LP tokens, divide by all LP tokens
valueOfTotalStakedAmountInBaseToken = new TokenAmount(
baseTokens[index],
JSBI.divide(
JSBI.multiply(
JSBI.multiply(
totalStakedAmount.raw,
stakingTokenPair.reserveOf(baseTokens[index]).raw,
),
JSBI.BigInt(2), // this is b/c the value of LP shares are ~double the value of the WETH they entitle owner to
),
totalSupply.raw,
),
);
}
const valueOfTotalStakedAmountInUSDC =
valueOfTotalStakedAmountInBaseToken &&
usdPrice?.quote(valueOfTotalStakedAmountInBaseToken);
const tvl = valueOfTotalStakedAmountInUSDC
? valueOfTotalStakedAmountInUSDC.toExact()
: valueOfTotalStakedAmountInBaseToken?.toExact();
const perMonthReturnInRewards =
((stakingInfo.rateA * rewardTokenAPrice +
stakingInfo.rateB * rewardTokenBPrice) *
(getDaysCurrentYear() / 12)) /
Number(valueOfTotalStakedAmountInUSDC?.toExact());
memo.push({
stakingRewardAddress: rewardsAddress,
tokens: stakingInfo.tokens,
ended: stakingInfo.ended,
name: stakingInfo.name,
lp: stakingInfo.lp,
earnedAmountA: initTokenAmountFromCallResult(
uni,
earnedAAmountState,
),
earnedAmountB: initTokenAmountFromCallResult(
uni,
earnedBAmountState,
),
rewardRateA: individualRewardRateA,
rewardRateB: individualRewardRateB,
totalRewardRateA: totalRewardRateA,
totalRewardRateB: totalRewardRateB,
stakedAmount: stakedAmount,
totalStakedAmount: totalStakedAmount,
getHypotheticalRewardRate,
baseToken: stakingInfo.baseToken,
pair: stakingInfo.pair,
rateA: stakingInfo.rateA,
rateB: stakingInfo.rateB,
rewardTokenA: stakingInfo.rewardTokenA,
rewardTokenB: stakingInfo.rewardTokenB,
rewardTokenBBase: stakingInfo.rewardTokenBBase,
rewardTokenAPrice,
rewardTokenBPrice,
tvl,
perMonthReturnInRewards,
totalSupply,
usdPrice,
stakingTokenPair,
oneDayFee,
accountFee,
});
}
return memo;
},
[],
);
}, [
balances,
chainId,
earnedAAmounts,
earnedBAmounts,
info,
rewardsAddresses,
totalSupplies,
uni,
rewardRatesA,
rewardRatesB,
baseTokens,
totalSupplys,
usdPrices,
stakingPairs,
rewardTokenAPrices,
rewardTokenBPrices,
]).filter((stakingInfo) =>
filter && filter.isStaked
? stakingInfo.stakedAmount && stakingInfo.stakedAmount.greaterThan('0')
: true,
);
}
Example #11
Source File: hooks.ts From interface-v2 with GNU General Public License v3.0 | 4 votes |
// gets the staking info from the network for the active chain id
export function useStakingInfo(
pairToFilterBy?: Pair | null,
startIndex?: number,
endIndex?: number,
filter?: { search: string; isStaked: boolean },
): StakingInfo[] {
const { chainId, account } = useActiveWeb3React();
const info = useMemo(
() =>
chainId
? returnStakingInfo()
[chainId]?.slice(startIndex, endIndex)
?.filter((stakingRewardInfo) =>
pairToFilterBy === undefined || pairToFilterBy === null
? getSearchFiltered(
stakingRewardInfo,
filter ? filter.search : '',
)
: pairToFilterBy.involvesToken(stakingRewardInfo.tokens[0]) &&
pairToFilterBy.involvesToken(stakingRewardInfo.tokens[1]),
) ?? []
: [],
[chainId, pairToFilterBy, startIndex, endIndex, filter],
);
const uni = chainId ? GlobalValue.tokens.UNI[chainId] : undefined;
const rewardsAddresses = useMemo(
() => info.map(({ stakingRewardAddress }) => stakingRewardAddress),
[info],
);
// const pairAddresses = useMemo(() => info.map(({ pair }) => pair), [info]);
// useEffect(() => {
// getBulkPairData(allPairAddress);
// }, [allPairAddress]);
const accountArg = useMemo(() => [account ?? undefined], [account]);
// get all the info from the staking rewards contracts
const balances = useMultipleContractSingleData(
rewardsAddresses,
STAKING_REWARDS_INTERFACE,
'balanceOf',
accountArg,
);
const earnedAmounts = useMultipleContractSingleData(
rewardsAddresses,
STAKING_REWARDS_INTERFACE,
'earned',
accountArg,
);
const totalSupplies = useMultipleContractSingleData(
rewardsAddresses,
STAKING_REWARDS_INTERFACE,
'totalSupply',
);
const rewardRates = useMultipleContractSingleData(
rewardsAddresses,
STAKING_REWARDS_INTERFACE,
'rewardRate',
undefined,
NEVER_RELOAD,
);
const baseTokens = info.map((item) => {
const unwrappedCurrency = unwrappedToken(item.baseToken);
const empty = unwrappedToken(returnTokenFromKey('EMPTY'));
return unwrappedCurrency === empty ? item.tokens[0] : item.baseToken;
});
const rewardTokens = info.map((item) => item.rewardToken);
const usdPrices = useUSDCPrices(baseTokens);
const usdPricesRewardTokens = useUSDCPricesToken(rewardTokens);
const totalSupplys = useTotalSupplys(
info.map((item) => {
const lp = item.lp;
const dummyPair = new Pair(
new TokenAmount(item.tokens[0], '0'),
new TokenAmount(item.tokens[1], '0'),
);
return lp && lp !== ''
? new Token(137, lp, 18, 'SLP', 'Staked LP')
: dummyPair.liquidityToken;
}),
);
const stakingPairs = usePairs(info.map((item) => item.tokens));
return useMemo(() => {
if (!chainId || !uni) return [];
return rewardsAddresses.reduce<StakingInfo[]>(
(memo, rewardsAddress, index) => {
// these two are dependent on account
const balanceState = balances[index];
const earnedAmountState = earnedAmounts[index];
// these get fetched regardless of account
const totalSupplyState = totalSupplies[index];
const rewardRateState = rewardRates[index];
const stakingInfo = info[index];
const rewardTokenPrice = usdPricesRewardTokens[index];
if (
// these may be undefined if not logged in
!balanceState?.loading &&
!earnedAmountState?.loading &&
// always need these
totalSupplyState &&
!totalSupplyState.loading &&
rewardRateState &&
!rewardRateState.loading
) {
// get the LP token
const tokens = stakingInfo.tokens;
const dummyPair = new Pair(
new TokenAmount(tokens[0], '0'),
new TokenAmount(tokens[1], '0'),
);
// check for account, if no account set to 0
const lp = stakingInfo.lp;
const rate = web3.utils.toWei(stakingInfo.rate.toString());
const stakedAmount = initTokenAmountFromCallResult(
getFarmLPToken(stakingInfo),
balanceState,
);
const totalStakedAmount = initTokenAmountFromCallResult(
getFarmLPToken(stakingInfo),
totalSupplyState,
);
const totalRewardRate = new TokenAmount(uni, JSBI.BigInt(rate));
//const pair = info[index].pair.toLowerCase();
//const fees = (pairData && pairData[pair] ? pairData[pair].oneDayVolumeUSD * 0.0025: 0);
const totalRewardRate01 = initTokenAmountFromCallResult(
uni,
rewardRateState,
);
const getHypotheticalRewardRate = (
stakedAmount?: TokenAmount,
totalStakedAmount?: TokenAmount,
totalRewardRate?: TokenAmount,
): TokenAmount | undefined => {
if (!stakedAmount || !totalStakedAmount || !totalRewardRate) return;
return new TokenAmount(
uni,
JSBI.greaterThan(totalStakedAmount.raw, JSBI.BigInt(0))
? JSBI.divide(
JSBI.multiply(totalRewardRate.raw, stakedAmount.raw),
totalStakedAmount.raw,
)
: JSBI.BigInt(0),
);
};
const individualRewardRate = getHypotheticalRewardRate(
stakedAmount,
totalStakedAmount,
totalRewardRate01,
);
const { oneYearFeeAPY, oneDayFee, accountFee } = getStakingFees(
stakingInfo,
balanceState,
totalSupplyState,
);
let valueOfTotalStakedAmountInBaseToken: TokenAmount | undefined;
const [, stakingTokenPair] = stakingPairs[index];
const totalSupply = totalSupplys[index];
const usdPrice = usdPrices[index];
if (
totalSupply &&
stakingTokenPair &&
baseTokens[index] &&
totalStakedAmount
) {
// take the total amount of LP tokens staked, multiply by ETH value of all LP tokens, divide by all LP tokens
valueOfTotalStakedAmountInBaseToken = new TokenAmount(
baseTokens[index],
JSBI.divide(
JSBI.multiply(
JSBI.multiply(
totalStakedAmount.raw,
stakingTokenPair.reserveOf(baseTokens[index]).raw,
),
JSBI.BigInt(2), // this is b/c the value of LP shares are ~double the value of the WETH they entitle owner to
),
totalSupply.raw,
),
);
}
const valueOfTotalStakedAmountInUSDC =
valueOfTotalStakedAmountInBaseToken &&
usdPrice?.quote(valueOfTotalStakedAmountInBaseToken);
const tvl = valueOfTotalStakedAmountInUSDC
? valueOfTotalStakedAmountInUSDC.toExact()
: valueOfTotalStakedAmountInBaseToken?.toExact();
const perMonthReturnInRewards =
(Number(stakingInfo.rate) *
rewardTokenPrice *
(getDaysCurrentYear() / 12)) /
Number(valueOfTotalStakedAmountInUSDC?.toExact());
memo.push({
stakingRewardAddress: rewardsAddress,
tokens: stakingInfo.tokens,
ended: stakingInfo.ended,
name: stakingInfo.name,
lp: stakingInfo.lp,
rewardToken: stakingInfo.rewardToken,
rewardTokenPrice,
earnedAmount: initTokenAmountFromCallResult(uni, earnedAmountState),
rewardRate: individualRewardRate,
totalRewardRate: totalRewardRate,
stakedAmount: stakedAmount,
totalStakedAmount: totalStakedAmount,
getHypotheticalRewardRate,
baseToken: stakingInfo.baseToken,
pair: stakingInfo.pair,
rate: stakingInfo.rate,
oneYearFeeAPY: oneYearFeeAPY,
oneDayFee,
accountFee,
tvl,
perMonthReturnInRewards,
valueOfTotalStakedAmountInBaseToken,
usdPrice,
stakingTokenPair,
totalSupply,
});
}
return memo;
},
[],
);
}, [
balances,
chainId,
earnedAmounts,
info,
rewardsAddresses,
totalSupplies,
uni,
rewardRates,
usdPricesRewardTokens,
baseTokens,
totalSupplys,
usdPrices,
stakingPairs,
]).filter((stakingInfo) =>
filter && filter.isStaked
? stakingInfo.stakedAmount && stakingInfo.stakedAmount.greaterThan('0')
: true,
);
}
Example #12
Source File: useUSDCPrice.ts From interface-v2 with GNU General Public License v3.0 | 4 votes |
/**
* Returns the price in USDC of the input currency
* @param currency currency to compute the USDC price of
*/
export default function useUSDCPrice(currency?: Currency): Price | undefined {
const { chainId } = useActiveWeb3React();
let wrapped = wrappedCurrency(currency, chainId);
const internalWrapped = wrapped;
if (wrapped?.equals(returnTokenFromKey('CXETH'))) {
wrapped = wrappedCurrency(returnTokenFromKey('ETHER'), chainId);
}
const tokenPairs: [Currency | undefined, Currency | undefined][] = useMemo(
() => [
[
chainId && wrapped && currencyEquals(WETH[chainId], wrapped)
? undefined
: wrapped,
chainId ? WETH[chainId] : undefined,
],
[
wrapped?.equals(returnTokenFromKey('QUICK')) ? undefined : wrapped,
chainId === ChainId.MATIC ? returnTokenFromKey('QUICK') : undefined,
],
[
wrapped?.equals(returnTokenFromKey('USDC')) ? undefined : wrapped,
chainId === ChainId.MATIC ? returnTokenFromKey('USDC') : undefined,
],
[
wrapped?.equals(returnTokenFromKey('USDT')) ? undefined : wrapped,
chainId === ChainId.MATIC ? returnTokenFromKey('USDT') : undefined,
],
[
wrapped?.equals(returnTokenFromKey('DAI')) ? undefined : wrapped,
chainId === ChainId.MATIC ? returnTokenFromKey('DAI') : undefined,
],
[
chainId ? WETH[chainId] : undefined,
chainId === ChainId.MATIC ? returnTokenFromKey('USDC') : undefined,
],
[
chainId === ChainId.MATIC ? returnTokenFromKey('QUICK') : undefined,
chainId === ChainId.MATIC ? returnTokenFromKey('USDC') : undefined,
],
],
[chainId, wrapped],
);
const [
[ethPairState, ethPair],
[quickPairState, quickPair],
[usdcPairState, usdcPair],
[usdtPairState, usdtPair],
[daiPairState, daiPair],
[usdcEthPairState, usdcEthPair],
[usdcQuickPairState, usdcQuickPair],
] = usePairs(tokenPairs);
return useMemo(() => {
if (!currency || !wrapped || !chainId) {
return undefined;
}
// handle weth/eth
if (wrapped.equals(WETH[chainId])) {
if (usdcPair) {
const price = usdcPair.priceOf(WETH[chainId]);
return new Price(
currency,
returnTokenFromKey('USDC'),
price.denominator,
price.numerator,
);
} else {
return undefined;
}
}
// handle usdc
if (wrapped.equals(returnTokenFromKey('USDC'))) {
return new Price(
returnTokenFromKey('USDC'),
returnTokenFromKey('USDC'),
'1',
'1',
);
}
if (wrapped.equals(returnTokenFromKey('USDT'))) {
return new Price(
returnTokenFromKey('USDT'),
returnTokenFromKey('USDT'),
'1',
'1',
);
}
if (wrapped.equals(returnTokenFromKey('DAI'))) {
return new Price(
returnTokenFromKey('DAI'),
returnTokenFromKey('DAI'),
'1',
'1',
);
}
if (wrapped.equals(returnTokenFromKey('FRAX'))) {
return new Price(
returnTokenFromKey('FRAX'),
returnTokenFromKey('FRAX'),
'1',
'1',
);
}
if (wrapped.equals(returnTokenFromKey('MI'))) {
return new Price(
returnTokenFromKey('MI'),
returnTokenFromKey('MI'),
'1',
'1',
);
}
const ethPairETHAmount = ethPair?.reserveOf(WETH[chainId]);
const ethPairETHUSDCValue: JSBI =
ethPairETHAmount && usdcEthPair
? usdcEthPair.priceOf(WETH[chainId]).quote(ethPairETHAmount).raw
: JSBI.BigInt(0);
// all other tokens
// first try the usdc pair
if (
usdcPairState === PairState.EXISTS &&
usdcPair &&
usdcPair
.reserveOf(returnTokenFromKey('USDC'))
.greaterThan(ethPairETHUSDCValue)
) {
const price = usdcPair.priceOf(wrapped);
if (internalWrapped?.equals(returnTokenFromKey('CXETH'))) {
return new Price(
returnTokenFromKey('CXETH'),
returnTokenFromKey('USDC'),
price.denominator,
price.numerator,
);
}
return new Price(
currency,
returnTokenFromKey('USDC'),
price.denominator,
price.numerator,
);
}
if (
usdtPairState === PairState.EXISTS &&
usdtPair &&
usdtPair
.reserveOf(returnTokenFromKey('USDT'))
.greaterThan(ethPairETHUSDCValue)
) {
const price = usdtPair.priceOf(wrapped);
return new Price(
currency,
returnTokenFromKey('USDT'),
price.denominator,
price.numerator,
);
}
if (
daiPairState === PairState.EXISTS &&
daiPair &&
daiPair
.reserveOf(returnTokenFromKey('DAI'))
.greaterThan(ethPairETHUSDCValue)
) {
const price = daiPair.priceOf(wrapped);
return new Price(
currency,
returnTokenFromKey('DAI'),
price.denominator,
price.numerator,
);
}
if (
ethPairState === PairState.EXISTS &&
ethPair &&
usdcEthPairState === PairState.EXISTS &&
usdcEthPair
) {
if (
usdcEthPair.reserveOf(returnTokenFromKey('USDC')).greaterThan('0') &&
ethPair.reserveOf(WETH[chainId]).greaterThan('1')
) {
const ethUsdcPrice = usdcEthPair.priceOf(returnTokenFromKey('USDC'));
const currencyEthPrice = ethPair.priceOf(WETH[chainId]);
const usdcPrice = ethUsdcPrice.multiply(currencyEthPrice).invert();
return new Price(
currency,
returnTokenFromKey('USDC'),
usdcPrice.denominator,
usdcPrice.numerator,
);
}
}
if (
quickPairState === PairState.EXISTS &&
quickPair &&
usdcQuickPairState === PairState.EXISTS &&
usdcQuickPair
) {
if (
usdcQuickPair.reserveOf(returnTokenFromKey('USDC')).greaterThan('0') &&
quickPair.reserveOf(returnTokenFromKey('QUICK')).greaterThan('5')
) {
const quickUsdcPrice = usdcQuickPair.priceOf(
returnTokenFromKey('USDC'),
);
const currencyQuickPrice = quickPair.priceOf(
returnTokenFromKey('QUICK'),
);
const usdcPrice = quickUsdcPrice.multiply(currencyQuickPrice).invert();
return new Price(
currency,
returnTokenFromKey('USDC'),
usdcPrice.denominator,
usdcPrice.numerator,
);
}
}
return undefined;
}, [
currency,
wrapped,
chainId,
ethPair,
usdcEthPair,
usdcPairState,
usdcPair,
usdtPairState,
usdtPair,
daiPairState,
daiPair,
ethPairState,
usdcEthPairState,
quickPairState,
quickPair,
usdcQuickPairState,
usdcQuickPair,
internalWrapped,
]);
}
Example #13
Source File: useUSDCPrice.ts From interface-v2 with GNU General Public License v3.0 | 4 votes |
export function useUSDCPrices(currencies: Currency[]): (Price | undefined)[] {
const { chainId } = useActiveWeb3React();
const wrappedCurrencies = currencies.map((currency) => {
let wrapped = wrappedCurrency(currency, chainId);
if (wrapped?.equals(returnTokenFromKey('CXETH'))) {
wrapped = wrappedCurrency(returnTokenFromKey('ETHER'), chainId);
}
return wrapped;
});
const tokenPairs: [Currency | undefined, Currency | undefined][] = [];
wrappedCurrencies.forEach((wrapped, ind) => {
tokenPairs.push([
chainId && wrapped && currencyEquals(WETH[chainId], wrapped)
? undefined
: currencies[ind],
chainId ? WETH[chainId] : undefined,
]);
tokenPairs.push([
wrapped?.equals(returnTokenFromKey('QUICK')) ? undefined : wrapped,
chainId === ChainId.MATIC ? returnTokenFromKey('QUICK') : undefined,
]);
tokenPairs.push([
wrapped?.equals(returnTokenFromKey('USDC')) ? undefined : wrapped,
chainId === ChainId.MATIC ? returnTokenFromKey('USDC') : undefined,
]);
tokenPairs.push([
wrapped?.equals(returnTokenFromKey('USDT')) ? undefined : wrapped,
chainId === ChainId.MATIC ? returnTokenFromKey('USDT') : undefined,
]);
tokenPairs.push([
wrapped?.equals(returnTokenFromKey('DAI')) ? undefined : wrapped,
chainId === ChainId.MATIC ? returnTokenFromKey('DAI') : undefined,
]);
tokenPairs.push([
chainId ? WETH[chainId] : undefined,
chainId === ChainId.MATIC ? returnTokenFromKey('USDC') : undefined,
]);
tokenPairs.push([
chainId ? returnTokenFromKey('QUICK') : undefined,
chainId === ChainId.MATIC ? returnTokenFromKey('USDC') : undefined,
]);
});
const pairs = usePairs(tokenPairs);
const remainPairs = currencies.map((_, index) => {
return pairs.slice(7 * index, 7 * (index + 1));
});
return currencies.map((currency, index) => {
const [
[ethPairState, ethPair],
[quickPairState, quickPair],
[usdcPairState, usdcPair],
[usdtPairState, usdtPair],
[daiPairState, daiPair],
[usdcEthPairState, usdcEthPair],
[usdcQuickPairState, usdcQuickPair],
] = remainPairs[index];
const wrapped = wrappedCurrencies[index];
const internalWrapped = wrappedCurrency(currency, chainId);
if (!wrapped || !chainId) {
return undefined;
}
if (wrapped.equals(WETH[chainId])) {
if (usdcPair) {
const price = usdcPair.priceOf(WETH[chainId]);
return new Price(
currency,
returnTokenFromKey('USDC'),
price.denominator,
price.numerator,
);
} else {
return undefined;
}
}
// handle usdc
if (wrapped.equals(returnTokenFromKey('USDC'))) {
return new Price(
returnTokenFromKey('USDC'),
returnTokenFromKey('USDC'),
'1',
'1',
);
}
if (wrapped.equals(returnTokenFromKey('USDT'))) {
return new Price(
returnTokenFromKey('USDT'),
returnTokenFromKey('USDT'),
'1',
'1',
);
}
if (wrapped.equals(returnTokenFromKey('DAI'))) {
return new Price(
returnTokenFromKey('DAI'),
returnTokenFromKey('DAI'),
'1',
'1',
);
}
if (wrapped.equals(returnTokenFromKey('FRAX'))) {
return new Price(
returnTokenFromKey('FRAX'),
returnTokenFromKey('FRAX'),
'1',
'1',
);
}
if (wrapped.equals(returnTokenFromKey('MI'))) {
return new Price(
returnTokenFromKey('MI'),
returnTokenFromKey('MI'),
'1',
'1',
);
}
const ethPairETHAmount = ethPair?.reserveOf(WETH[chainId]);
const ethPairETHUSDCValue: JSBI =
ethPairETHAmount && usdcEthPair
? usdcEthPair.priceOf(WETH[chainId]).quote(ethPairETHAmount).raw
: JSBI.BigInt(0);
// all other tokens
// first try the usdc pair
if (
usdcPairState === PairState.EXISTS &&
usdcPair &&
usdcPair
.reserveOf(returnTokenFromKey('USDC'))
.greaterThan(ethPairETHUSDCValue)
) {
const price = usdcPair.priceOf(wrapped);
if (internalWrapped?.equals(returnTokenFromKey('CXETH'))) {
return new Price(
returnTokenFromKey('CXETH'),
returnTokenFromKey('USDC'),
price.denominator,
price.numerator,
);
}
return new Price(
currency,
returnTokenFromKey('USDC'),
price.denominator,
price.numerator,
);
}
if (
usdtPairState === PairState.EXISTS &&
usdtPair &&
usdtPair
.reserveOf(returnTokenFromKey('USDT'))
.greaterThan(ethPairETHUSDCValue)
) {
const price = usdtPair.priceOf(wrapped);
return new Price(
currency,
returnTokenFromKey('USDT'),
price.denominator,
price.numerator,
);
}
if (
daiPairState === PairState.EXISTS &&
daiPair &&
daiPair
.reserveOf(returnTokenFromKey('DAI'))
.greaterThan(ethPairETHUSDCValue)
) {
const price = daiPair.priceOf(wrapped);
return new Price(
currency,
returnTokenFromKey('DAI'),
price.denominator,
price.numerator,
);
}
if (
ethPairState === PairState.EXISTS &&
ethPair &&
usdcEthPairState === PairState.EXISTS &&
usdcEthPair
) {
if (
usdcEthPair.reserveOf(returnTokenFromKey('USDC')).greaterThan('0') &&
ethPair.reserveOf(WETH[chainId]).greaterThan('1')
) {
const ethUsdcPrice = usdcEthPair.priceOf(returnTokenFromKey('USDC'));
const currencyEthPrice = ethPair.priceOf(WETH[chainId]);
const usdcPrice = ethUsdcPrice.multiply(currencyEthPrice).invert();
return new Price(
currency,
returnTokenFromKey('USDC'),
usdcPrice.denominator,
usdcPrice.numerator,
);
}
}
if (
quickPairState === PairState.EXISTS &&
quickPair &&
usdcQuickPairState === PairState.EXISTS &&
usdcQuickPair
) {
if (
usdcQuickPair.reserveOf(returnTokenFromKey('USDC')).greaterThan('0') &&
quickPair.reserveOf(returnTokenFromKey('QUICK')).greaterThan('5')
) {
const quickUsdcPrice = usdcQuickPair.priceOf(
returnTokenFromKey('USDC'),
);
const currencyQuickPrice = quickPair.priceOf(
returnTokenFromKey('QUICK'),
);
const usdcPrice = quickUsdcPrice.multiply(currencyQuickPrice).invert();
return new Price(
currency,
returnTokenFromKey('USDC'),
usdcPrice.denominator,
usdcPrice.numerator,
);
}
}
return undefined;
});
}