Commit abe6bf50 authored by Justin Domingue's avatar Justin Domingue Committed by GitHub

feat: extend privacy and terms (#2623)

* initial iteration

* add logging

* added hook

* polish

* remove unused import

* add hash

* addressed pr feedback

* remove autorouter icon

* use firebase store

* style

* adjust recat ga

* log remove liquidity

* update copy

* addressed pr feedback

* addressed pr feedback

* prevent privacy content from dismissing modal

* make top-level key origin

* use hostname

* restore trm
parent 36cfe627
...@@ -2,3 +2,4 @@ REACT_APP_INFURA_KEY="099fc58e0de9451d80b18d7c74caa7c1" ...@@ -2,3 +2,4 @@ REACT_APP_INFURA_KEY="099fc58e0de9451d80b18d7c74caa7c1"
REACT_APP_PORTIS_ID="c0e2bf01-4b08-4fd5-ac7b-8e26b58cd236" REACT_APP_PORTIS_ID="c0e2bf01-4b08-4fd5-ac7b-8e26b58cd236"
REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF" REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF"
REACT_APP_GOOGLE_ANALYTICS_ID="UA-128182339-4" REACT_APP_GOOGLE_ANALYTICS_ID="UA-128182339-4"
REACT_APP_FIREBASE_KEY="AIzaSyBcZWwTcTJHj_R6ipZcrJkXdq05PuX0Rs0"
// eslint-disable-next-line no-restricted-imports // eslint-disable-next-line no-restricted-imports
import { t } from '@lingui/macro' import { t, Trans } from '@lingui/macro'
import { Trans } from '@lingui/macro' import { PrivacyPolicyModal } from 'components/PrivacyPolicy'
import { CHAIN_INFO, L2_CHAIN_IDS, SupportedChainId } from 'constants/chains' import { CHAIN_INFO, L2_CHAIN_IDS, SupportedChainId } from 'constants/chains'
import { LOCALE_LABEL, SUPPORTED_LOCALES, SupportedLocale } from 'constants/locales' import { LOCALE_LABEL, SUPPORTED_LOCALES, SupportedLocale } from 'constants/locales'
import { useActiveLocale } from 'hooks/useActiveLocale' import { useActiveLocale } from 'hooks/useActiveLocale'
import { useLocationLinkProps } from 'hooks/useLocationLinkProps' import { useLocationLinkProps } from 'hooks/useLocationLinkProps'
import React, { useEffect, useRef, useState } from 'react' import React, { useEffect, useRef, useState } from 'react'
import { BookOpen, Check, ChevronLeft, Code, Globe, Info, MessageCircle, Moon, PieChart, Sun } from 'react-feather' import {
BookOpen,
Check,
ChevronLeft,
Code,
FileText,
Globe,
Info,
MessageCircle,
Moon,
PieChart,
Sun,
} from 'react-feather'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { useDarkModeManager } from 'state/user/hooks' import { useDarkModeManager } from 'state/user/hooks'
import styled, { css } from 'styled-components/macro' import styled, { css } from 'styled-components/macro'
...@@ -202,8 +214,9 @@ export default function Menu() { ...@@ -202,8 +214,9 @@ export default function Menu() {
const node = useRef<HTMLDivElement>() const node = useRef<HTMLDivElement>()
const open = useModalOpen(ApplicationModal.MENU) const open = useModalOpen(ApplicationModal.MENU)
const toggle = useToggleModal(ApplicationModal.MENU) const toggleMenu = useToggleModal(ApplicationModal.MENU)
useOnClickOutside(node, open ? toggle : undefined) useOnClickOutside(node, open ? toggleMenu : undefined)
const togglePrivacyPolicy = useToggleModal(ApplicationModal.PRIVACY_POLICY)
const openClaimModal = useToggleModal(ApplicationModal.ADDRESS_CLAIM) const openClaimModal = useToggleModal(ApplicationModal.ADDRESS_CLAIM)
const showUNIClaimOption = Boolean(!!account && !!chainId && !L2_CHAIN_IDS.includes(chainId)) const showUNIClaimOption = Boolean(!!account && !!chainId && !L2_CHAIN_IDS.includes(chainId))
const { infoLink } = CHAIN_INFO[chainId ? chainId : SupportedChainId.MAINNET] const { infoLink } = CHAIN_INFO[chainId ? chainId : SupportedChainId.MAINNET]
...@@ -217,9 +230,10 @@ export default function Menu() { ...@@ -217,9 +230,10 @@ export default function Menu() {
}, [open]) }, [open])
return ( return (
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30451 <>
{/* // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30451 */}
<StyledMenu ref={node as any}> <StyledMenu ref={node as any}>
<StyledMenuButton onClick={toggle} aria-label={t`Menu`}> <StyledMenuButton onClick={toggleMenu} aria-label={t`Menu`}>
<StyledMenuIcon /> <StyledMenuIcon />
</StyledMenuButton> </StyledMenuButton>
...@@ -272,6 +286,12 @@ export default function Menu() { ...@@ -272,6 +286,12 @@ export default function Menu() {
<div>{darkMode ? <Trans>Light Theme</Trans> : <Trans>Dark Theme</Trans>}</div> <div>{darkMode ? <Trans>Light Theme</Trans> : <Trans>Dark Theme</Trans>}</div>
{darkMode ? <Moon opacity={0.6} size={16} /> : <Sun opacity={0.6} size={16} />} {darkMode ? <Moon opacity={0.6} size={16} /> : <Sun opacity={0.6} size={16} />}
</ToggleMenuItem> </ToggleMenuItem>
<ToggleMenuItem onClick={() => togglePrivacyPolicy()}>
<div>
<Trans>Legal & Privacy</Trans>
</div>
<FileText opacity={0.6} size={16} />
</ToggleMenuItem>
{showUNIClaimOption && ( {showUNIClaimOption && (
<UNIbutton <UNIbutton
onClick={openClaimModal} onClick={openClaimModal}
...@@ -288,6 +308,8 @@ export default function Menu() { ...@@ -288,6 +308,8 @@ export default function Menu() {
} }
})()} })()}
</StyledMenu> </StyledMenu>
<PrivacyPolicyModal />
</>
) )
} }
......
import { Trans } from '@lingui/macro'
import Card, { DarkGreyCard } from 'components/Card'
import { AutoRow, RowBetween } from 'components/Row'
import { useEffect, useRef } from 'react'
import { ArrowDown, Info, X } from 'react-feather'
import ReactGA from 'react-ga'
import styled from 'styled-components/macro'
import { ExternalLink, TYPE } from 'theme'
import { isMobile } from 'utils/userAgent'
import { useModalOpen, useTogglePrivacyPolicy } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { AutoColumn } from '../Column'
import Modal from '../Modal'
const Wrapper = styled.div`
max-height: 70vh;
overflow: auto;
padding: 0 1rem;
`
const StyledExternalCard = styled(Card)`
background-color: ${({ theme }) => theme.primary5};
padding: 0.5rem;
width: 100%;
:hover,
:focus,
:active {
background-color: ${({ theme }) => theme.primary4};
}
`
const HoverText = styled.div`
text-decoration: none;
color: ${({ theme }) => theme.text1};
display: flex;
align-items: center;
:hover {
cursor: pointer;
}
`
const StyledLinkOut = styled(ArrowDown)`
transform: rotate(230deg);
`
const EXTERNAL_APIS = [
{
name: 'Auto Router',
description: <Trans>The app fetches the optimal trade route from a Uniswap Labs server.</Trans>,
},
{
name: 'Infura',
description: <Trans>The app fetches on-chain data and constructs contract calls with an Infura API.</Trans>,
},
{
name: 'TRM Labs',
description: (
<Trans>
The app securely collects your wallet address and shares it with TRM Labs Inc. for risk and compliance reasons.
</Trans>
),
},
{
name: 'Google Analytics',
description: <Trans>The app logs anonymized usage statistics in order to improve over time.</Trans>,
},
{
name: 'The Graph',
description: <Trans>The app fetches blockchain data from The Graph’s hosted service.</Trans>,
},
]
export function PrivacyPolicyModal() {
const node = useRef<HTMLDivElement>()
const open = useModalOpen(ApplicationModal.PRIVACY_POLICY)
const toggle = useTogglePrivacyPolicy()
useEffect(() => {
if (!open) return
ReactGA.event({
category: 'Modal',
action: 'Show Legal',
})
}, [open])
return (
<Modal isOpen={open} onDismiss={() => toggle()}>
<AutoColumn gap="12px" ref={node as any}>
<RowBetween padding="1rem 1rem 0.5rem 1rem">
<TYPE.mediumHeader>
<Trans>Legal & Privacy</Trans>
</TYPE.mediumHeader>
<HoverText onClick={() => toggle()}>
<X size={24} />
</HoverText>
</RowBetween>
<PrivacyPolicy />
</AutoColumn>
</Modal>
)
}
export function PrivacyPolicy() {
return (
<Wrapper
draggable="true"
onTouchMove={(e) => {
// prevent modal gesture handler from dismissing modal when content is scrolling
if (isMobile) {
e.stopPropagation()
}
}}
>
<AutoColumn gap="16px">
<AutoColumn gap="8px" style={{ width: '100%' }}>
<StyledExternalCard>
<ExternalLink href={'https://uniswap.org/terms-of-service'}>
<RowBetween>
<AutoRow gap="4px">
<Info size={20} />
<TYPE.main fontSize={14} color={'primaryText1'}>
<Trans>Uniswap Labs&apos; Terms of Service</Trans>
</TYPE.main>
</AutoRow>
<StyledLinkOut size={20} />
</RowBetween>
</ExternalLink>
</StyledExternalCard>
<StyledExternalCard>
<ExternalLink href={'https://uniswap.org/disclaimer/'}>
<RowBetween>
<AutoRow gap="4px">
<Info size={20} />
<TYPE.main fontSize={14} color={'primaryText1'}>
<Trans>Protocol Disclaimer</Trans>
</TYPE.main>
</AutoRow>
<StyledLinkOut size={20} />
</RowBetween>
</ExternalLink>
</StyledExternalCard>
</AutoColumn>
<TYPE.main fontSize={14}>
<Trans>This app uses the following third-party APIs:</Trans>
</TYPE.main>
<AutoColumn gap="12px">
{EXTERNAL_APIS.map(({ name, description }, i) => (
<DarkGreyCard key={i}>
<AutoColumn gap="8px">
<AutoRow gap="4px">
<Info size={18} />
<TYPE.main fontSize={14} color={'text1'}>
{name}
</TYPE.main>
</AutoRow>
<TYPE.main fontSize={14}>{description}</TYPE.main>
</AutoColumn>
</DarkGreyCard>
))}
<div />
</AutoColumn>
</AutoColumn>
</Wrapper>
)
}
...@@ -2,9 +2,12 @@ import { Trans } from '@lingui/macro' ...@@ -2,9 +2,12 @@ import { Trans } from '@lingui/macro'
import { AbstractConnector } from '@web3-react/abstract-connector' import { AbstractConnector } from '@web3-react/abstract-connector'
import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core' import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core'
import { WalletConnectConnector } from '@web3-react/walletconnect-connector' import { WalletConnectConnector } from '@web3-react/walletconnect-connector'
import { AutoRow } from 'components/Row' import { AutoColumn } from 'components/Column'
import { PrivacyPolicy } from 'components/PrivacyPolicy'
import Row, { AutoRow, RowBetween } from 'components/Row'
import { useMonitoringEventCallback } from 'hooks/useMonitoringEventCallback'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { ArrowLeft } from 'react-feather' import { ArrowLeft, ArrowRight, Info } from 'react-feather'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
...@@ -19,7 +22,7 @@ import { ApplicationModal } from '../../state/application/reducer' ...@@ -19,7 +22,7 @@ import { ApplicationModal } from '../../state/application/reducer'
import { ExternalLink, TYPE } from '../../theme' import { ExternalLink, TYPE } from '../../theme'
import { isMobile } from '../../utils/userAgent' import { isMobile } from '../../utils/userAgent'
import AccountDetails from '../AccountDetails' import AccountDetails from '../AccountDetails'
import { LightCard } from '../Card' import Card, { LightCard } from '../Card'
import Modal from '../Modal' import Modal from '../Modal'
import Option from './Option' import Option from './Option'
import PendingView from './PendingView' import PendingView from './PendingView'
...@@ -106,11 +109,22 @@ const HoverText = styled.div` ...@@ -106,11 +109,22 @@ const HoverText = styled.div`
} }
` `
const LinkCard = styled(Card)`
background-color: ${({ theme }) => theme.primary1};
color: ${({ theme }) => theme.white};
:hover {
cursor: pointer;
filter: brightness(0.9);
}
`
const WALLET_VIEWS = { const WALLET_VIEWS = {
OPTIONS: 'options', OPTIONS: 'options',
OPTIONS_SECONDARY: 'options_secondary', OPTIONS_SECONDARY: 'options_secondary',
ACCOUNT: 'account', ACCOUNT: 'account',
PENDING: 'pending', PENDING: 'pending',
LEGAL: 'legal',
} }
export default function WalletModal({ export default function WalletModal({
...@@ -126,6 +140,7 @@ export default function WalletModal({ ...@@ -126,6 +140,7 @@ export default function WalletModal({
const { active, account, connector, activate, error } = useWeb3React() const { active, account, connector, activate, error } = useWeb3React()
const [walletView, setWalletView] = useState(WALLET_VIEWS.ACCOUNT) const [walletView, setWalletView] = useState(WALLET_VIEWS.ACCOUNT)
const previousWalletView = usePrevious(walletView)
const [pendingWallet, setPendingWallet] = useState<AbstractConnector | undefined>() const [pendingWallet, setPendingWallet] = useState<AbstractConnector | undefined>()
...@@ -136,6 +151,8 @@ export default function WalletModal({ ...@@ -136,6 +151,8 @@ export default function WalletModal({
const previousAccount = usePrevious(account) const previousAccount = usePrevious(account)
const logMonitoringEvent = useMonitoringEventCallback()
// close on connection, when logged out before // close on connection, when logged out before
useEffect(() => { useEffect(() => {
if (account && !previousAccount && walletModalOpen) { if (account && !previousAccount && walletModalOpen) {
...@@ -183,7 +200,12 @@ export default function WalletModal({ ...@@ -183,7 +200,12 @@ export default function WalletModal({
} }
connector && connector &&
activate(connector, undefined, true).catch((error) => { activate(connector, undefined, true)
.then(async () => {
const walletAddress = await connector.getAccount()
logMonitoringEvent('wallet connected', { walletAddress })
})
.catch((error) => {
if (error instanceof UnsupportedChainIdError) { if (error instanceof UnsupportedChainIdError) {
activate(connector) // a little janky...can't use setError because the connector isn't set activate(connector) // a little janky...can't use setError because the connector isn't set
} else { } else {
...@@ -307,6 +329,27 @@ export default function WalletModal({ ...@@ -307,6 +329,27 @@ export default function WalletModal({
</UpperSection> </UpperSection>
) )
} }
if (walletView === WALLET_VIEWS.LEGAL) {
return (
<UpperSection>
<HeaderRow>
<HoverText
onClick={() => {
setWalletView(previousWalletView ?? WALLET_VIEWS.ACCOUNT)
}}
>
<ArrowLeft />
</HoverText>
<Row justify="center">
<TYPE.mediumHeader>
<Trans>Legal & Privacy</Trans>
</TYPE.mediumHeader>
</Row>
</HeaderRow>
<PrivacyPolicy />
</UpperSection>
)
}
if (account && walletView === WALLET_VIEWS.ACCOUNT) { if (account && walletView === WALLET_VIEWS.ACCOUNT) {
return ( return (
<AccountDetails <AccountDetails
...@@ -337,24 +380,36 @@ export default function WalletModal({ ...@@ -337,24 +380,36 @@ export default function WalletModal({
) : ( ) : (
<HeaderRow> <HeaderRow>
<HoverText> <HoverText>
<Trans>Connect to a wallet</Trans> <Trans>Connect a wallet</Trans>
</HoverText> </HoverText>
</HeaderRow> </HeaderRow>
)} )}
<ContentWrapper> <ContentWrapper>
<LightCard style={{ marginBottom: '16px' }}> <AutoColumn gap="16px">
<LightCard>
<AutoRow style={{ flexWrap: 'nowrap' }}> <AutoRow style={{ flexWrap: 'nowrap' }}>
<TYPE.black fontSize={14}> <TYPE.black fontSize={14}>
<Trans> <Trans>
By connecting a wallet, you agree to Uniswap Labs’{' '} By connecting a wallet, you agree to Uniswap Labs’{' '}
<ExternalLink href="https://uniswap.org/terms-of-service/">Terms of Service</ExternalLink> and <ExternalLink href="https://uniswap.org/terms-of-service/">Terms of Service</ExternalLink> and
acknowledge that you have read and understand the{' '} acknowledge that you have read and understand the Uniswap{' '}
<ExternalLink href="https://uniswap.org/disclaimer/">Uniswap protocol disclaimer</ExternalLink>. <ExternalLink href="https://uniswap.org/disclaimer/">Protocol Disclaimer</ExternalLink>.
</Trans> </Trans>
</TYPE.black> </TYPE.black>
</AutoRow> </AutoRow>
</LightCard> </LightCard>
<LinkCard padding=".5rem" $borderRadius=".75rem" onClick={() => setWalletView(WALLET_VIEWS.LEGAL)}>
<RowBetween>
<AutoRow gap="4px">
<Info size={20} />
<TYPE.white fontSize={14}>
<Trans>How this app uses APIs</Trans>
</TYPE.white>
</AutoRow>
<ArrowRight size={16} />
</RowBetween>
</LinkCard>
{walletView === WALLET_VIEWS.PENDING ? ( {walletView === WALLET_VIEWS.PENDING ? (
<PendingView <PendingView
connector={pendingWallet} connector={pendingWallet}
...@@ -365,6 +420,7 @@ export default function WalletModal({ ...@@ -365,6 +420,7 @@ export default function WalletModal({
) : ( ) : (
<OptionGrid>{getOptions()}</OptionGrid> <OptionGrid>{getOptions()}</OptionGrid>
)} )}
</AutoColumn>
</ContentWrapper> </ContentWrapper>
</UpperSection> </UpperSection>
) )
......
...@@ -212,7 +212,7 @@ function Web3StatusInner() { ...@@ -212,7 +212,7 @@ function Web3StatusInner() {
return ( return (
<Web3StatusConnect id="connect-wallet" onClick={toggleWalletModal} faded={!account}> <Web3StatusConnect id="connect-wallet" onClick={toggleWalletModal} faded={!account}>
<Text> <Text>
<Trans>Connect to a wallet</Trans> <Trans>Connect Wallet</Trans>
</Text> </Text>
</Web3StatusConnect> </Web3StatusConnect>
) )
......
import { initializeApp } from 'firebase/app'
import { getDatabase, push, ref } from 'firebase/database'
import { useCallback } from 'react'
import { useActiveWeb3React } from './web3'
type MonitoringEvent =
| 'wallet connected'
| 'swap'
| 'add liquidity/v3'
| 'add liquidity/v2'
| 'remove liquidity/v3'
| 'remove liquidity/v2'
const FIREBASE_API_KEY = process.env.REACT_APP_FIREBASE_KEY
const firebaseEnabled = typeof FIREBASE_API_KEY !== 'undefined'
initializeFirebase()
export function useMonitoringEventCallback() {
const { account, chainId } = useActiveWeb3React()
return useCallback(
async function log(
type: MonitoringEvent,
{ hash, walletAddress = account }: { hash?: string; walletAddress?: typeof account }
) {
if (!firebaseEnabled) return
const db = getDatabase()
if (!walletAddress) {
console.debug('Wallet address required to log monitoring events.')
return
}
try {
push(ref(db, 'trm'), {
chainId,
origin: location.origin,
signedTransactionHash: hash ?? 'n/a',
timestamp: Date.now(),
type,
walletAddress,
})
} catch (e) {
console.debug('Error adding document: ', e)
}
},
[account, chainId]
)
}
function initializeFirebase() {
if (!firebaseEnabled) return
initializeApp({
apiKey: process.env.REACT_APP_FIREBASE_KEY,
authDomain: 'interface-monitoring.firebaseapp.com',
databaseURL: 'https://interface-monitoring-default-rtdb.firebaseio.com',
projectId: 'interface-monitoring',
storageBucket: 'interface-monitoring.appspot.com',
messagingSenderId: '968187720053',
appId: '1:968187720053:web:acedf72dce629d470be33c',
})
}
...@@ -5,6 +5,7 @@ import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' ...@@ -5,6 +5,7 @@ import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { FeeAmount, NonfungiblePositionManager } from '@uniswap/v3-sdk' import { FeeAmount, NonfungiblePositionManager } from '@uniswap/v3-sdk'
import DowntimeWarning from 'components/DowntimeWarning' import DowntimeWarning from 'components/DowntimeWarning'
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter' import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
import { useMonitoringEventCallback } from 'hooks/useMonitoringEventCallback'
import { useCallback, useContext, useEffect, useState } from 'react' import { useCallback, useContext, useEffect, useState } from 'react'
import { AlertTriangle } from 'react-feather' import { AlertTriangle } from 'react-feather'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
...@@ -89,6 +90,8 @@ export default function AddLiquidity({ ...@@ -89,6 +90,8 @@ export default function AddLiquidity({
const addTransaction = useTransactionAdder() const addTransaction = useTransactionAdder()
const positionManager = useV3NFTPositionManagerContract() const positionManager = useV3NFTPositionManagerContract()
const logMonitoringEvent = useMonitoringEventCallback()
// check for existing position if tokenId in url // check for existing position if tokenId in url
const { position: existingPositionDetails, loading: positionLoading } = useV3PositionFromTokenId( const { position: existingPositionDetails, loading: positionLoading } = useV3PositionFromTokenId(
tokenId ? BigNumber.from(tokenId) : undefined tokenId ? BigNumber.from(tokenId) : undefined
...@@ -345,6 +348,7 @@ export default function AddLiquidity({ ...@@ -345,6 +348,7 @@ export default function AddLiquidity({
action: 'Add', action: 'Add',
label: [currencies[Field.CURRENCY_A]?.symbol, currencies[Field.CURRENCY_B]?.symbol].join('/'), label: [currencies[Field.CURRENCY_A]?.symbol, currencies[Field.CURRENCY_B]?.symbol].join('/'),
}) })
logMonitoringEvent('add liquidity/v3', { hash: response.hash })
}) })
}) })
.catch((error) => { .catch((error) => {
......
...@@ -4,6 +4,7 @@ import { Trans } from '@lingui/macro' ...@@ -4,6 +4,7 @@ import { Trans } from '@lingui/macro'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter' import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
import { SwitchLocaleLink } from 'components/SwitchLocaleLink' import { SwitchLocaleLink } from 'components/SwitchLocaleLink'
import { useMonitoringEventCallback } from 'hooks/useMonitoringEventCallback'
import { useCallback, useContext, useState } from 'react' import { useCallback, useContext, useState } from 'react'
import { Plus } from 'react-feather' import { Plus } from 'react-feather'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
...@@ -56,6 +57,8 @@ export default function AddLiquidity({ ...@@ -56,6 +57,8 @@ export default function AddLiquidity({
const { account, chainId, library } = useActiveWeb3React() const { account, chainId, library } = useActiveWeb3React()
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
const logMonitoringEvent = useMonitoringEventCallback()
const currencyA = useCurrency(currencyIdA) const currencyA = useCurrency(currencyIdA)
const currencyB = useCurrency(currencyIdB) const currencyB = useCurrency(currencyIdB)
...@@ -203,6 +206,7 @@ export default function AddLiquidity({ ...@@ -203,6 +206,7 @@ export default function AddLiquidity({
action: 'Add', action: 'Add',
label: [currencies[Field.CURRENCY_A]?.symbol, currencies[Field.CURRENCY_B]?.symbol].join('/'), label: [currencies[Field.CURRENCY_A]?.symbol, currencies[Field.CURRENCY_B]?.symbol].join('/'),
}) })
logMonitoringEvent('add liquidity/v2', { hash: response.hash })
}) })
) )
.catch((error) => { .catch((error) => {
......
...@@ -19,6 +19,7 @@ import Toggle from 'components/Toggle' ...@@ -19,6 +19,7 @@ import Toggle from 'components/Toggle'
import { SupportedChainId } from 'constants/chains' import { SupportedChainId } from 'constants/chains'
import { useV3NFTPositionManagerContract } from 'hooks/useContract' import { useV3NFTPositionManagerContract } from 'hooks/useContract'
import useDebouncedChangeHandler from 'hooks/useDebouncedChangeHandler' import useDebouncedChangeHandler from 'hooks/useDebouncedChangeHandler'
import { useMonitoringEventCallback } from 'hooks/useMonitoringEventCallback'
import useTheme from 'hooks/useTheme' import useTheme from 'hooks/useTheme'
import useTransactionDeadline from 'hooks/useTransactionDeadline' import useTransactionDeadline from 'hooks/useTransactionDeadline'
import { useV3PositionFromTokenId } from 'hooks/useV3Positions' import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
...@@ -68,6 +69,8 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { ...@@ -68,6 +69,8 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
const theme = useTheme() const theme = useTheme()
const { account, chainId, library } = useActiveWeb3React() const { account, chainId, library } = useActiveWeb3React()
const logMonitoringEvent = useMonitoringEventCallback()
// flag for receiving WETH // flag for receiving WETH
const [receiveWETH, setReceiveWETH] = useState(false) const [receiveWETH, setReceiveWETH] = useState(false)
...@@ -152,6 +155,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { ...@@ -152,6 +155,7 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
action: 'RemoveV3', action: 'RemoveV3',
label: [liquidityValue0.currency.symbol, liquidityValue1.currency.symbol].join('/'), label: [liquidityValue0.currency.symbol, liquidityValue1.currency.symbol].join('/'),
}) })
logMonitoringEvent('remove liquidity/v3', { hash: response.hash })
setTxnHash(response.hash) setTxnHash(response.hash)
setAttemptingTxn(false) setAttemptingTxn(false)
addTransaction(response, { addTransaction(response, {
...@@ -168,20 +172,21 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { ...@@ -168,20 +172,21 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
console.error(error) console.error(error)
}) })
}, [ }, [
tokenId, positionManager,
liquidityValue0, liquidityValue0,
liquidityValue1, liquidityValue1,
deadline, deadline,
allowedSlippage,
account, account,
addTransaction,
positionManager,
chainId, chainId,
feeValue0, feeValue0,
feeValue1, feeValue1,
library,
liquidityPercentage,
positionSDK, positionSDK,
liquidityPercentage,
library,
tokenId,
allowedSlippage,
logMonitoringEvent,
addTransaction,
]) ])
const handleDismissConfirmation = useCallback(() => { const handleDismissConfirmation = useCallback(() => {
......
...@@ -3,6 +3,7 @@ import { Contract } from '@ethersproject/contracts' ...@@ -3,6 +3,7 @@ import { Contract } from '@ethersproject/contracts'
import { TransactionResponse } from '@ethersproject/providers' import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, Percent } from '@uniswap/sdk-core' import { Currency, Percent } from '@uniswap/sdk-core'
import { useMonitoringEventCallback } from 'hooks/useMonitoringEventCallback'
import { useCallback, useContext, useMemo, useState } from 'react' import { useCallback, useContext, useMemo, useState } from 'react'
import { ArrowDown, Plus } from 'react-feather' import { ArrowDown, Plus } from 'react-feather'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
...@@ -57,6 +58,8 @@ export default function RemoveLiquidity({ ...@@ -57,6 +58,8 @@ export default function RemoveLiquidity({
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
const logMonitoringEvent = useMonitoringEventCallback()
// toggle wallet when disconnected // toggle wallet when disconnected
const toggleWalletModal = useWalletModalToggle() const toggleWalletModal = useWalletModalToggle()
...@@ -280,6 +283,7 @@ export default function RemoveLiquidity({ ...@@ -280,6 +283,7 @@ export default function RemoveLiquidity({
action: 'Remove', action: 'Remove',
label: [currencyA.symbol, currencyB.symbol].join('/'), label: [currencyA.symbol, currencyB.symbol].join('/'),
}) })
logMonitoringEvent('remove liquidity/v2', { hash: response.hash })
}) })
.catch((error: Error) => { .catch((error: Error) => {
setAttemptingTxn(false) setAttemptingTxn(false)
......
...@@ -10,6 +10,7 @@ import SwapRoute from 'components/swap/SwapRoute' ...@@ -10,6 +10,7 @@ import SwapRoute from 'components/swap/SwapRoute'
import TradePrice from 'components/swap/TradePrice' import TradePrice from 'components/swap/TradePrice'
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter' import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
import { MouseoverTooltip, MouseoverTooltipContent } from 'components/Tooltip' import { MouseoverTooltip, MouseoverTooltipContent } from 'components/Tooltip'
import { useMonitoringEventCallback } from 'hooks/useMonitoringEventCallback'
import JSBI from 'jsbi' import JSBI from 'jsbi'
import { useCallback, useContext, useEffect, useMemo, useState } from 'react' import { useCallback, useContext, useEffect, useMemo, useState } from 'react'
import { ArrowDown, CheckCircle, HelpCircle, Info } from 'react-feather' import { ArrowDown, CheckCircle, HelpCircle, Info } from 'react-feather'
...@@ -80,6 +81,8 @@ export default function Swap({ history }: RouteComponentProps) { ...@@ -80,6 +81,8 @@ export default function Swap({ history }: RouteComponentProps) {
const { account } = useActiveWeb3React() const { account } = useActiveWeb3React()
const loadedUrlParams = useDefaultsFromURLSearch() const loadedUrlParams = useDefaultsFromURLSearch()
const logMonitoringEvent = useMonitoringEventCallback()
// token warning stuff // token warning stuff
const [loadedInputCurrency, loadedOutputCurrency] = [ const [loadedInputCurrency, loadedOutputCurrency] = [
useCurrency(loadedUrlParams?.inputCurrencyId), useCurrency(loadedUrlParams?.inputCurrencyId),
...@@ -285,6 +288,7 @@ export default function Swap({ history }: RouteComponentProps) { ...@@ -285,6 +288,7 @@ export default function Swap({ history }: RouteComponentProps) {
'MH', 'MH',
].join('/'), ].join('/'),
}) })
logMonitoringEvent('swap', { hash })
}) })
.catch((error) => { .catch((error) => {
setSwapState({ setSwapState({
...@@ -295,7 +299,17 @@ export default function Swap({ history }: RouteComponentProps) { ...@@ -295,7 +299,17 @@ export default function Swap({ history }: RouteComponentProps) {
txHash: undefined, txHash: undefined,
}) })
}) })
}, [swapCallback, priceImpact, tradeToConfirm, showConfirm, recipient, recipientAddress, account, trade]) }, [
swapCallback,
priceImpact,
tradeToConfirm,
showConfirm,
recipient,
recipientAddress,
account,
trade,
logMonitoringEvent,
])
// errors // errors
const [showInverted, setShowInverted] = useState<boolean>(false) const [showInverted, setShowInverted] = useState<boolean>(false)
......
...@@ -51,6 +51,10 @@ export function useToggleVoteModal(): () => void { ...@@ -51,6 +51,10 @@ export function useToggleVoteModal(): () => void {
return useToggleModal(ApplicationModal.VOTE) return useToggleModal(ApplicationModal.VOTE)
} }
export function useTogglePrivacyPolicy(): () => void {
return useToggleModal(ApplicationModal.PRIVACY_POLICY)
}
// returns a function that allows adding a popup // returns a function that allows adding a popup
export function useAddPopup(): (content: PopupContent, key?: string, removeAfterMs?: number) => void { export function useAddPopup(): (content: PopupContent, key?: string, removeAfterMs?: number) => void {
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
......
...@@ -18,6 +18,7 @@ export enum ApplicationModal { ...@@ -18,6 +18,7 @@ export enum ApplicationModal {
VOTE, VOTE,
POOL_OVERVIEW_OPTIONS, POOL_OVERVIEW_OPTIONS,
NETWORK_SELECTOR, NETWORK_SELECTOR,
PRIVACY_POLICY,
} }
type PopupList = Array<{ key: string; show: boolean; content: PopupContent; removeAfterMs: number | null }> type PopupList = Array<{ key: string; show: boolean; content: PopupContent; removeAfterMs: number | null }>
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment