This repository has been archived by the owner on Jun 24, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* CoW subsidy modal + sub components * force commit * [CoW Subsidy] Connect modal and add comp to swap mod (#2551) * revert !account test check * add cow subsidy modal type to state * add component to swapmod * use AutoRow * [Cow Subsidy] - Get user's (v)COW balance fn + tests (#2557) * create discount utl fn & tests * move constants to file closer to subsidy code * minor changes to SubsidyTable * fix broken path * PR comments - ease up logic and data * [CoW Subsidy] - Highlight current subsidy relative to CoW balance and show correct discount on SwapMod (#2558) * add selected tier styling to table * change return of util * pass tier (mock) to modal * more serious hook impl. * change type to subsidy and use hook * fix test * use atom units for better math - simpler for..of loop - format table units down * better tests and fix logic * type change and minor logic lean * fix test tier with lt change * lt inclusive in loop * fix typo * dont show empty container * hide balance on !account
- Loading branch information
Showing
13 changed files
with
399 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import styled from 'styled-components/macro' | ||
import { Trans } from '@lingui/macro' | ||
|
||
import { AMOUNT_PRECISION } from 'constants/index' | ||
import { ClaimSummaryTitle, ClaimTotal, ClaimSummary as ClaimSummaryWrapper } from 'pages/Claim/styled' | ||
import { formatMax, formatSmartLocaleAware } from 'utils/format' | ||
import CowProtocolLogo from 'components/CowProtocolLogo' | ||
import { CowSubsidyInfoProps } from 'components/CowSubsidyModal' | ||
|
||
const Wrapper = styled(ClaimSummaryWrapper)` | ||
border-radius: 100px; | ||
` | ||
|
||
type CowBalanceProps = Omit<CowSubsidyInfoProps, 'subsidy'> & { | ||
title?: string | ||
} | ||
|
||
const CowBalance = ({ balance, title }: CowBalanceProps) => { | ||
return ( | ||
<Wrapper> | ||
<CowProtocolLogo size={100} /> | ||
|
||
{title && ( | ||
<ClaimSummaryTitle> | ||
<Trans>{title}</Trans> | ||
</ClaimSummaryTitle> | ||
)} | ||
|
||
<div> | ||
<ClaimTotal> | ||
<b>Your combined balance</b> | ||
<p title={`${balance ? formatMax(balance, balance.currency.decimals) : '0'} vCOW`}> | ||
{' '} | ||
{formatSmartLocaleAware(balance, AMOUNT_PRECISION) || '0'} (v)COW | ||
</p> | ||
</ClaimTotal> | ||
</div> | ||
</Wrapper> | ||
) | ||
} | ||
|
||
export default CowBalance |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import styled from 'styled-components/macro' | ||
import { formatSmartLocaleAware } from 'utils/format' | ||
import { ClaimTr } from 'pages/Claim/ClaimsTable' | ||
import { COW_SUBSIDY_DATA } from './constants' | ||
import { CowSubsidy } from '.' | ||
import { transparentize } from 'polished' | ||
import { FlyoutRowActiveIndicator } from '../Header/NetworkSelector' | ||
|
||
import { BigNumber } from 'bignumber.js' | ||
import { formatUnits } from '@ethersproject/units' | ||
import { V_COW } from 'constants/tokens' | ||
import { SupportedChainId } from 'constants/chains' | ||
|
||
const StyledSubsidyTable = styled.table` | ||
width: 100%; | ||
` | ||
|
||
const SubsidyTr = styled(ClaimTr)<{ selected?: boolean }>` | ||
position: relative; | ||
${({ selected, theme }) => | ||
selected && | ||
` | ||
background: ${transparentize(0.7, theme.primary1)}; | ||
> td { | ||
border: 1.2px solid ${theme.primary1}; | ||
color: ${theme.primary1}; | ||
font-weight: 500; | ||
> ${FlyoutRowActiveIndicator} { | ||
position: absolute; | ||
left: 8%; | ||
background-color: ${theme.primary1}; | ||
box-shadow: 0px 0px 8px ${transparentize(0.3, theme.primary1)}; | ||
} | ||
&:first-child { | ||
border-right: none; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
} | ||
&:last-child { | ||
border-left: none; | ||
} | ||
} | ||
`} | ||
> th { | ||
font-weight: 300; | ||
} | ||
> td, | ||
th { | ||
padding: 10px; | ||
text-align: center; | ||
} | ||
` | ||
|
||
const COW_DECIMALS = V_COW[SupportedChainId.MAINNET].decimals | ||
|
||
function SubsidyTable({ discount }: CowSubsidy) { | ||
return ( | ||
<StyledSubsidyTable> | ||
<thead> | ||
<SubsidyTr> | ||
<th>(v)COW balance</th> | ||
<th>Fee discount</th> | ||
</SubsidyTr> | ||
</thead> | ||
<tbody> | ||
{/* DATA IS IN ATOMS */} | ||
{COW_SUBSIDY_DATA.map(([threshold, thresholdDiscount], i) => { | ||
const selected = discount === thresholdDiscount | ||
const formattedThreshold = new BigNumber(formatUnits(threshold, COW_DECIMALS)) | ||
|
||
return ( | ||
<SubsidyTr key={i} selected={selected}> | ||
<td> | ||
{selected && <FlyoutRowActiveIndicator active />} | ||
<span>{i && '>' + formatSmartLocaleAware(formattedThreshold)}</span> | ||
</td> | ||
<td>{thresholdDiscount}%</td> | ||
</SubsidyTr> | ||
) | ||
})} | ||
</tbody> | ||
</StyledSubsidyTable> | ||
) | ||
} | ||
|
||
export default SubsidyTable |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// used in modal and popover | ||
export const SUBSIDY_INFO_MESSAGE = 'As a (v)COW token holder you will be eligible for a fee discount.' | ||
export const COW_SUBSIDY_DATA: [string, number][] = [ | ||
['0', 0], | ||
// 100 | ||
['100000000000000000000', 10], | ||
// 1000 | ||
['1000000000000000000000', 15], | ||
// 10000 | ||
['10000000000000000000000', 25], | ||
// 100000 | ||
['100000000000000000000000', 35], | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { useCallback } from 'react' | ||
import { CurrencyAmount, Currency } from '@uniswap/sdk-core' | ||
import { | ||
ConfirmationModalContent, | ||
ConfirmationModalContentProps, | ||
ConfirmationModalProps, | ||
} from 'components/TransactionConfirmationModal' | ||
import { useActiveWeb3React } from 'hooks/web3' | ||
import { GpModal } from 'components/Modal' | ||
import { AutoColumn } from 'components/SearchModal/CommonBases' | ||
import { Text } from 'rebass' | ||
|
||
import Row from 'components/Row' | ||
import { ExternalLink } from 'components/Link' | ||
|
||
import CowBalance from '../CowBalance' | ||
import SubsidyTable from './SubsidyTable' | ||
import { SUBSIDY_INFO_MESSAGE } from './constants' | ||
|
||
import useCowBalanceAndSubsidy from 'hooks/useCowBalanceAndSubsidy' | ||
|
||
export type CowSubsidy = { tier: number; discount: number } | ||
export interface CowSubsidyInfoProps { | ||
account?: string | ||
balance?: CurrencyAmount<Currency> | ||
subsidy: CowSubsidy | ||
} | ||
|
||
const CowSubsidyInfo = ({ account, balance, subsidy }: CowSubsidyInfoProps) => ( | ||
<AutoColumn style={{ marginTop: 20, padding: '2rem 0' }} gap="24px" justify="center"> | ||
<Text fontWeight={500} fontSize={16} style={{ textAlign: 'center', width: '85%', wordBreak: 'break-word' }}> | ||
{SUBSIDY_INFO_MESSAGE} | ||
</Text> | ||
{/* VCOW LOGO */} | ||
{account && <CowBalance account={account} balance={balance} />} | ||
<SubsidyTable {...subsidy} /> | ||
</AutoColumn> | ||
) | ||
|
||
export default function CowSubsidyModal({ | ||
isOpen, | ||
onDismiss, | ||
...restProps | ||
}: Pick<ConfirmationModalProps, 'isOpen'> & Omit<ConfirmationModalContentProps, 'title' | 'topContent'>) { | ||
const { account, chainId } = useActiveWeb3React() | ||
|
||
// TODO: update with latest code | ||
const { subsidy, balance } = useCowBalanceAndSubsidy() | ||
|
||
const TopContent = useCallback( | ||
() => <CowSubsidyInfo account={account ?? undefined} balance={balance} subsidy={subsidy} />, | ||
[account, balance, subsidy] | ||
) | ||
|
||
const BottomContent = useCallback( | ||
() => ( | ||
<Row style={{ justifyContent: 'center' }}> | ||
{/* TODO: incoming blogpost URL */} | ||
<ExternalLink href="/#/">Read more about the tokenomics</ExternalLink> | ||
</Row> | ||
), | ||
[] | ||
) | ||
|
||
if (!chainId) return null | ||
|
||
return ( | ||
<GpModal isOpen={isOpen} onDismiss={onDismiss} maxHeight={90}> | ||
<ConfirmationModalContent | ||
{...restProps} | ||
title="CoWmunity fees discount" | ||
onDismiss={onDismiss} | ||
topContent={TopContent} | ||
bottomContent={BottomContent} | ||
/> | ||
</GpModal> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/** | ||
* @jest-environment ./custom-test-env.js | ||
*/ | ||
import { BigNumber } from 'bignumber.js' | ||
import { formatUnits } from '@ethersproject/units' | ||
import { getDiscountFromBalance } from './utils' | ||
|
||
const BALANCES_IN_TIER = [ | ||
{ balance: '0', tier: 0 }, | ||
{ balance: '100000000000000000', tier: 0 }, // 0.1 | ||
{ balance: '99990000000000000000', tier: 0 }, // 99.99 | ||
{ balance: '100000000000000000000', tier: 1 }, // 100 | ||
{ balance: '100001000000000000000', tier: 1 }, // 100.001 | ||
{ balance: '1500000000000000000000', tier: 2 }, // 1500 | ||
{ balance: '11000000000000000000000', tier: 3 }, // 11000 | ||
{ balance: '174330000000000000000000', tier: 4 }, // 174330 | ||
] | ||
|
||
const INCORRECT_BALANCES_IN_TIER = [ | ||
{ balance: '0', tier: 2 }, | ||
{ balance: '100000000000000000', tier: 4 }, // 0.1 | ||
{ balance: '99990000000000000000', tier: 2 }, // 99.99 | ||
{ balance: '100000000000000000000', tier: 2 }, // 100 | ||
{ balance: '150000000000000000000', tier: 0 }, // 150 | ||
{ balance: '1500000000000000000000', tier: 4 }, // 1500 | ||
{ balance: '174330000000000000000000', tier: 3 }, // 174330 | ||
] | ||
|
||
describe('FEE DISCOUNT TIERS', () => { | ||
describe('CORRECT DISCOUNTS', () => { | ||
BALANCES_IN_TIER.forEach(({ balance, tier }) => { | ||
it(`USER BALANCE: [${formatUnits(balance, 18)}] equals TIER ${tier}`, () => { | ||
const BALANCE_BN = new BigNumber(balance) | ||
|
||
expect(getDiscountFromBalance(BALANCE_BN).tier).toEqual(tier) | ||
}) | ||
}) | ||
}) | ||
describe('INCORRECT DISCOUNTS', () => { | ||
INCORRECT_BALANCES_IN_TIER.forEach(({ balance, tier }) => { | ||
it(`USER BALANCE: [${formatUnits(balance, 18)}] does NOT equal TIER ${tier}`, () => { | ||
const BALANCE_BN = new BigNumber(balance) | ||
expect(getDiscountFromBalance(BALANCE_BN).tier).not.toEqual(tier) | ||
}) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { BigNumber } from 'bignumber.js' | ||
import { COW_SUBSIDY_DATA } from './constants' | ||
|
||
const SLICED_DATA = COW_SUBSIDY_DATA.slice(1) | ||
|
||
export function getDiscountFromBalance(balanceAtomsBn: BigNumber) { | ||
let tier = 0 | ||
let [, discount] = COW_SUBSIDY_DATA[tier] | ||
// Here we use a sliced verison of our data without index 0 (0 amt tier) | ||
// because loop-wise a balance less than or equal to 0 and 100 (indices 0 and 1, respectively) are the same | ||
for (const [threshold, thresholdDiscount] of SLICED_DATA) { | ||
// Increase our tier number only if we're not at the end of our list | ||
// Is balance less than or equal to threshold? | ||
// return our subsidy information | ||
const thresholdBn = new BigNumber(threshold) | ||
if (balanceAtomsBn.lt(thresholdBn)) return { discount, tier } | ||
|
||
// Else assign the current discount as the threshold and iterate one tier | ||
discount = thresholdDiscount | ||
tier++ | ||
} | ||
|
||
return { discount, tier } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { useMemo } from 'react' | ||
import { CurrencyAmount } from '@uniswap/sdk-core' | ||
import { BigNumber } from 'bignumber.js' | ||
import { parseUnits } from '@ethersproject/units' | ||
|
||
import { getDiscountFromBalance } from 'components/CowSubsidyModal/utils' | ||
import { SupportedChainId } from 'constants/chains' | ||
import { V_COW } from 'constants/tokens' | ||
import { useActiveWeb3React } from '.' | ||
|
||
// TODO: get real balance | ||
const MOCK_BALANCE = CurrencyAmount.fromRawAmount( | ||
V_COW[SupportedChainId.RINKEBY], | ||
parseUnits('111100.97', V_COW[SupportedChainId.MAINNET].decimals).toString() | ||
) | ||
export default function useCowBalanceAndSubsidy() { | ||
const { chainId } = useActiveWeb3React() | ||
|
||
// TODO: vcow and cow balance from @nenadV91 | ||
/* const vCow = */ chainId ? V_COW[chainId] : undefined | ||
const balance = MOCK_BALANCE // useTotalCowBalance(account || undefined, vCow) | ||
|
||
return useMemo(() => { | ||
const balanceBn = new BigNumber(balance.quotient.toString()) | ||
return { subsidy: getDiscountFromBalance(balanceBn), balance } | ||
}, [balance]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.