Skip to content
This repository has been archived by the owner on Sep 4, 2021. It is now read-only.

feat: l2 trading rewards #426

Draft
wants to merge 4 commits into
base: l2
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions constants/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ export const QUERY_KEYS = {
walletAddress,
networkId,
],
AvailableL2TradingRewards: (walletAddress: string, networkId: NetworkId) => [
'trades',
'availableL2TradingRewards',
walletAddress,
networkId,
],
},
SystemStatus: {
IsUpgrading: ['systemStatus', 'isUpgrading'],
Expand Down
6 changes: 4 additions & 2 deletions containers/L2Gas/L2Gas.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useState, useEffect, useMemo } from 'react';
import { ethers } from 'ethers';
import { createContainer } from 'unstated-next';
import { useRecoilValue } from 'recoil';
import Connector from 'containers/Connector';
Expand Down Expand Up @@ -38,7 +39,7 @@ const MakeContainer = () => {
const loadBalance = async () => {
try {
const balance = await wETHContract.balanceOf(address);
if (isMounted) setBalance(toBigNumber(balance.toString()).div(1e18));
if (isMounted) setBalance(toBigNumber(ethers.utils.formatEther(balance)));
} catch (e) {
console.error(e);
}
Expand All @@ -48,7 +49,7 @@ const MakeContainer = () => {
const transferEvent = wETHContract.filters.Transfer();
const onBalanceChange = async (from: string, to: string) => {
if (from === address || to === address) {
if (isMounted) setBalance(await wETHContract.balanceOf(address));
loadBalance();
}
};

Expand All @@ -60,6 +61,7 @@ const MakeContainer = () => {

loadBalance();
subscribe();

return () => {
unsubs.forEach((unsub) => unsub());
};
Expand Down
13 changes: 9 additions & 4 deletions pages/exchange/[[...market]].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ const ExchangePage = () => {
footerCard,
combinedPriceChartCard,
combinedMarketDetailsCard,

toggleIsShowingSingleChart,
isShowingSingleChart,
wideWidth,
l2TradingIncentiveCard,
} = useExchange({
showPriceCard: true,
showMarketDetailsCard: true,
Expand Down Expand Up @@ -96,16 +96,17 @@ const ExchangePage = () => {
</SwapCurrenciesButton>
</SwapCurrenciesButtonContainer>

<PageWidthContainer>
<TopCards>
<DesktopCardsContainer>
<LeftCardContainer data-testid="left-side">{quoteCurrencyCard}</LeftCardContainer>
<RightCardContainer data-testid="right-side">
{baseCurrencyCard}
</RightCardContainer>
</DesktopCardsContainer>
</PageWidthContainer>

<PageWidthContainer>{footerCard}</PageWidthContainer>
{footerCard}
{l2TradingIncentiveCard}
</TopCards>

<AnimateSharedLayout>
{chartsToggler}
Expand Down Expand Up @@ -346,4 +347,8 @@ const ChartsTogglerText = styled.div<{ active: boolean }>`
color: ${(props) => (props.active ? props.theme.colors.white : props.theme.colors.silver)};
`;

const TopCards = styled(PageWidthContainer)`
margin-bottom: 18px;
`;

export default ExchangePage;
41 changes: 41 additions & 0 deletions queries/trades/useAvailableL2TradingRewardsQuery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { QueryConfig, useQuery } from 'react-query';
import synthetix from 'lib/synthetix';

import QUERY_KEYS from 'constants/queryKeys';
import { useRecoilValue } from 'recoil';
import { isWalletConnectedState, networkState, walletAddressState } from 'store/wallet';
import { appReadyState } from 'store/app';
import BigNumber from 'bignumber.js';
import { toBigNumber } from 'utils/formatters/number';

type Ret = BigNumber;

const useAvailableL2TradingRewardsQuery = (options?: QueryConfig<Ret>) => {
const isAppReady = useRecoilValue(appReadyState);
const isWalletConnected = useRecoilValue(isWalletConnectedState);
const walletAddress = useRecoilValue(walletAddressState);
const network = useRecoilValue(networkState);

return useQuery<Ret>(
QUERY_KEYS.Trades.AvailableL2TradingRewards(walletAddress ?? '', network?.id!),
async () => {
const {
contracts: { TradingRewards },
utils,
} = synthetix.js!;
const currentPeriod = await TradingRewards.getCurrentPeriod();
console.log(currentPeriod.toNumber());
const rewards = await TradingRewards.getAvailableRewardsForAccountForPeriod(
walletAddress,
currentPeriod
);
return toBigNumber(utils.formatEther(rewards));
},
{
enabled: isAppReady && isWalletConnected,
...options,
}
);
};

export default useAvailableL2TradingRewardsQuery;
218 changes: 218 additions & 0 deletions sections/dashboard/TrendingSynths/L2TradingRewards.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import { FC, useMemo, useState } from 'react';
import styled from 'styled-components';
import { useTranslation } from 'react-i18next';
import { Svg } from 'react-optimized-image';
import { useRecoilValue } from 'recoil';
import Tippy from '@tippyjs/react';

import useSelectedPriceCurrency from 'hooks/useSelectedPriceCurrency';

import { CRYPTO_CURRENCY_MAP, SYNTHS_MAP } from 'constants/currency';
import { NO_VALUE, ESTIMATE_VALUE } from 'constants/placeholder';

import Button from 'components/Button';

import InfoIcon from 'assets/svg/app/info.svg';

import { CardTitle } from 'sections/dashboard/common';

import { FlexDivCol, FlexDivRowCentered, numericValueCSS } from 'styles/common';

import useAvailableL2TradingRewardsQuery from 'queries/trades/useAvailableL2TradingRewardsQuery';
import useEthGasPriceQuery from 'queries/network/useEthGasPriceQuery';
import useExchangeRatesQuery from 'queries/rates/useExchangeRatesQuery';

import { formatCryptoCurrency, formatCurrency, zeroBN } from 'utils/formatters/number';
import { getExchangeRatesForCurrencies } from 'utils/currencies';
import { getTransactionPrice } from 'utils/network';

import { gasSpeedState } from 'store/wallet';

const L2TradingRewards: FC = () => {
const { t } = useTranslation();

const { selectedPriceCurrency } = useSelectedPriceCurrency();

const ethGasPriceQuery = useEthGasPriceQuery();
const exchangeRatesQuery = useExchangeRatesQuery();

const exchangeRates = exchangeRatesQuery.isSuccess ? exchangeRatesQuery.data ?? null : null;
const gasPrices = ethGasPriceQuery.data;
const [gasLimit] = useState<number | null>(null);
const ethPriceRate = useMemo(
() => getExchangeRatesForCurrencies(exchangeRates, SYNTHS_MAP.sETH, selectedPriceCurrency.name),
[exchangeRates, selectedPriceCurrency.name]
);
const gasSpeed = useRecoilValue(gasSpeedState);
const gasPrice = gasPrices ? gasPrices[gasSpeed] : null;
const transactionFee = useMemo(() => getTransactionPrice(gasPrice, gasLimit, ethPriceRate), [
gasPrice,
gasLimit,
ethPriceRate,
]);

const rewardsQuery = useAvailableL2TradingRewardsQuery();
const rewards = rewardsQuery.data ?? zeroBN;
const canClaimRewards = !rewards.isZero();
const onClaimRewards = () => {};

const gasPriceItem = (
<span data-testid="gas-price">
{ESTIMATE_VALUE} {gasPrice}
</span>
);

return (
<Container>
<Heading>
{t('l2-trading-incentives.dashboard.title')} <Svg src={InfoIcon} />
</Heading>

<RewardsCard>
<FlexDivCol>
<Title>{t('l2-trading-incentives.dashboard.potential-rewards')}</Title>
<Amount>200 SNX</Amount>
</FlexDivCol>
</RewardsCard>

<RewardsCard>
<FlexDivCol>
<Title>{t('l2-trading-incentives.dashboard.claimable-rewards')}</Title>
<Amount>
{formatCryptoCurrency(rewards, {
currencyKey: CRYPTO_CURRENCY_MAP.SNX,
})}
</Amount>
</FlexDivCol>

<ClaimRewardsButton
variant="primary"
isRounded={true}
disabled={!canClaimRewards}
onClick={onClaimRewards}
size="lg"
data-testid="submit-order"
>
{t('l2-trading-incentives.dashboard.claim')}
</ClaimRewardsButton>
</RewardsCard>

<LineItem>
<LineItemLabel>{t('l2-trading-incentives.dashboard.epoch')}</LineItemLabel>
<LineItemValue>07:14:55</LineItemValue>
</LineItem>
<LineItem>
<LineItemLabel>{t('exchange.summary-info.gas-price-gwei')}</LineItemLabel>
<LineItemValue>
{gasPrice == null ? (
NO_VALUE
) : transactionFee == null ? (
gasPriceItem
) : (
<GasPriceCostTooltip
content={
<span>
{formatCurrency(selectedPriceCurrency.name, transactionFee, {
sign: selectedPriceCurrency.sign,
})}
</span>
}
arrow={false}
>
<GasPriceItem>
{gasPriceItem}
<Svg src={InfoIcon} />
</GasPriceItem>
</GasPriceCostTooltip>
)}
</LineItemValue>
</LineItem>
</Container>
);
};

export default L2TradingRewards;

const Container = styled.div`
margin-bottom: 16px;
`;

const RewardsCard = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
padding: 9px 16px;
background: ${(props) => props.theme.colors.navy};
border-radius: 4px;
margin: 8px 0;
`;

const Title = styled.div`
font-size: 12px;
color: ${(props) => props.theme.colors.silver};
`;

const Amount = styled.div`
font-size: 16px;
font-family: ${(props) => props.theme.fonts.bold};
color: ${(props) => props.theme.colors.white};
`;

const Heading = styled(CardTitle)`
display: flex;
align-items: center;
grid-gap: 5px;
`;

const ClaimRewardsButton = styled(Button)`
width: 64px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
font-size: 12px;
`;

const LineItem = styled(FlexDivRowCentered)`
border-bottom: 0.5px solid ${(props) => props.theme.colors.navy};
height: 40px;
`;

const LineItemLabel = styled.div`
text-transform: capitalize;
color: ${(props) => props.theme.colors.blueberry};
`;

const LineItemValue = styled.div`
color: ${(props) => props.theme.colors.white};
${numericValueCSS};
`;

export const GasPriceTooltip = styled(Tippy)`
background: ${(props) => props.theme.colors.elderberry};
border: 0.5px solid ${(props) => props.theme.colors.navy};
border-radius: 4px;
width: 120px;
.tippy-content {
padding: 0;
}
`;

export const GasPriceCostTooltip = styled(GasPriceTooltip)`
width: auto;
font-size: 12px;
.tippy-content {
padding: 5px;
font-family: ${(props) => props.theme.fonts.mono};
}
`;

export const GasPriceItem = styled.span`
display: inline-flex;
align-items: center;
cursor: pointer;
svg {
margin-left: 5px;
}
`;
10 changes: 7 additions & 3 deletions sections/dashboard/TrendingSynths/TrendingSynths.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FC, useMemo } from 'react';
import styled from 'styled-components';
import { useTranslation } from 'react-i18next';
import { useRecoilState } from 'recoil';
import { useRecoilState, useRecoilValue } from 'recoil';
import { useQueryCache } from 'react-query';

import synthetix, { Synth } from 'lib/synthetix';
Expand All @@ -19,10 +19,12 @@ import SynthRow from './SynthRow';
import { numericSort, toCurrencyKeyMap } from './utils';
import { SYNTH_SORT_OPTIONS, SynthSort } from './constants';
import { trendingSynthsOptionState } from 'store/ui';
import L2TradingRewards from './L2TradingRewards';
import { isL2State } from 'store/wallet';

const TrendingSynths: FC = () => {
const { t } = useTranslation();

const isL2 = useRecoilValue(isL2State);
const [currentSynthSort, setCurrentSynthSort] = useRecoilState(trendingSynthsOptionState);

const queryCache = useQueryCache();
Expand Down Expand Up @@ -69,6 +71,8 @@ const TrendingSynths: FC = () => {
return (
<>
<Container>
{!isL2 ? null : <L2TradingRewards />}

<TitleSortContainer>
<CardTitle>{t('dashboard.trending')}</CardTitle>
<TrendingSortSelect
Expand Down Expand Up @@ -101,7 +105,7 @@ const Container = styled.div`
`;

const TitleSortContainer = styled(FlexDivRowCentered)`
margin-top: -10px;
/* margin-top: -10px; */
`;

const Rows = styled.div`
Expand Down
Loading