Commit e06142e2 authored by lynn's avatar lynn Committed by GitHub

feat: implement other swap events part 1 (#4151)

* init commit

* fix prettier errors

* check node env in vercel

* add shouldLogImpression to TraceEvent
parent 1f763a1c
...@@ -8,6 +8,7 @@ type TraceEventProps = { ...@@ -8,6 +8,7 @@ type TraceEventProps = {
events: Event[] events: Event[]
name: EventName name: EventName
properties?: Record<string, unknown> properties?: Record<string, unknown>
shouldLogImpression?: boolean
} & ITraceContext } & ITraceContext
/** /**
...@@ -19,7 +20,7 @@ type TraceEventProps = { ...@@ -19,7 +20,7 @@ type TraceEventProps = {
* </TraceEvent> * </TraceEvent>
*/ */
export const TraceEvent = memo((props: PropsWithChildren<TraceEventProps>) => { export const TraceEvent = memo((props: PropsWithChildren<TraceEventProps>) => {
const { name, properties, events, children, ...traceProps } = props const { shouldLogImpression, name, properties, events, children, ...traceProps } = props
return ( return (
<Trace {...traceProps}> <Trace {...traceProps}>
...@@ -31,7 +32,10 @@ export const TraceEvent = memo((props: PropsWithChildren<TraceEventProps>) => { ...@@ -31,7 +32,10 @@ export const TraceEvent = memo((props: PropsWithChildren<TraceEventProps>) => {
} }
// For each child, augment event handlers defined in `events` with event tracing. // For each child, augment event handlers defined in `events` with event tracing.
return cloneElement(child, getEventHandlers(child, traceContext, events, name, properties)) return cloneElement(
child,
getEventHandlers(child, traceContext, events, name, properties, shouldLogImpression)
)
}) })
} }
</TraceContext.Consumer> </TraceContext.Consumer>
...@@ -50,7 +54,8 @@ function getEventHandlers( ...@@ -50,7 +54,8 @@ function getEventHandlers(
traceContext: ITraceContext, traceContext: ITraceContext,
events: Event[], events: Event[],
name: EventName, name: EventName,
properties?: Record<string, unknown> properties?: Record<string, unknown>,
shouldLogImpression = true
) { ) {
const eventHandlers: Partial<Record<Event, (e: SyntheticEvent<Element, Event>) => void>> = {} const eventHandlers: Partial<Record<Event, (e: SyntheticEvent<Element, Event>) => void>> = {}
...@@ -61,7 +66,7 @@ function getEventHandlers( ...@@ -61,7 +66,7 @@ function getEventHandlers(
child.props[event]?.apply(child, args) child.props[event]?.apply(child, args)
// augment handler with analytics logging // augment handler with analytics logging
sendAnalyticsEvent(name, { ...traceContext, ...properties, action: event }) if (shouldLogImpression) sendAnalyticsEvent(name, { ...traceContext, ...properties, action: event })
} }
} }
......
...@@ -7,7 +7,11 @@ ...@@ -7,7 +7,11 @@
export enum EventName { export enum EventName {
CONNECT_WALLET_BUTTON_CLICKED = 'Connect Wallet Button Clicked', CONNECT_WALLET_BUTTON_CLICKED = 'Connect Wallet Button Clicked',
PAGE_VIEWED = 'Page Viewed', PAGE_VIEWED = 'Page Viewed',
SWAP_AUTOROUTER_VISUALIZATION_EXPANDED = 'Swap Autorouter Visualization Expanded',
SWAP_DETAILS_EXPANDED = 'Swap Details Expanded',
SWAP_MAX_TOKEN_AMOUNT_SELECTED = 'Swap Max Token Amount Selected',
SWAP_SUBMITTED = 'Swap Submitted', SWAP_SUBMITTED = 'Swap Submitted',
SWAP_TOKENS_REVERSED = 'Swap Tokens Reversed',
TOKEN_IMPORTED = 'Token Imported', TOKEN_IMPORTED = 'Token Imported',
TOKEN_SELECTED = 'Token Selected', TOKEN_SELECTED = 'Token Selected',
TOKEN_SELECTOR_OPENED = 'Token Selector Opened', TOKEN_SELECTOR_OPENED = 'Token Selector Opened',
...@@ -45,7 +49,7 @@ export const enum SectionName { ...@@ -45,7 +49,7 @@ export const enum SectionName {
/** Known modals for analytics purposes. */ /** Known modals for analytics purposes. */
export const enum ModalName { export const enum ModalName {
SWAP = 'swap-modal', CONFIRM_SWAP = 'confirm-swap-modal',
TOKEN_SELECTOR = 'token-selector-modal', TOKEN_SELECTOR = 'token-selector-modal',
// alphabetize additional modal names. // alphabetize additional modal names.
} }
...@@ -55,11 +59,15 @@ export const enum ModalName { ...@@ -55,11 +59,15 @@ export const enum ModalName {
* Use to identify low-level components given a TraceContext * Use to identify low-level components given a TraceContext
*/ */
export const enum ElementName { export const enum ElementName {
AUTOROUTER_VISUALIZATION_ROW = 'expandable-autorouter-visualization-row',
COMMON_BASES_CURRENCY_BUTTON = 'common-bases-currency-button', COMMON_BASES_CURRENCY_BUTTON = 'common-bases-currency-button',
CONFIRM_SWAP_BUTTON = 'confirm-swap-or-send', CONFIRM_SWAP_BUTTON = 'confirm-swap-or-send',
CONNECT_WALLET_BUTTON = 'connect-wallet-button', CONNECT_WALLET_BUTTON = 'connect-wallet-button',
IMPORT_TOKEN_BUTTON = 'import-token-button', IMPORT_TOKEN_BUTTON = 'import-token-button',
MAX_TOKEN_AMOUNT_BUTTON = 'max-token-amount-button',
SWAP_BUTTON = 'swap-button', SWAP_BUTTON = 'swap-button',
SWAP_DETAILS_DROPDOWN = 'swap-details-dropdown',
SWAP_TOKENS_REVERSE_ARROW_BUTTON = 'swap-tokens-reverse-arrow-button',
TOKEN_SELECTOR_ROW = 'token-selector-row', TOKEN_SELECTOR_ROW = 'token-selector-row',
WALLET_TYPE_OPTION = 'wallet-type-option', WALLET_TYPE_OPTION = 'wallet-type-option',
// alphabetize additional element names. // alphabetize additional element names.
......
...@@ -2,6 +2,8 @@ import { Trans } from '@lingui/macro' ...@@ -2,6 +2,8 @@ import { Trans } from '@lingui/macro'
import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core' import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk' import { Pair } from '@uniswap/v2-sdk'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'components/AmplitudeAnalytics/constants'
import { TraceEvent } from 'components/AmplitudeAnalytics/TraceEvent'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled' import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled'
import { isSupportedChain } from 'constants/chains' import { isSupportedChain } from 'constants/chains'
...@@ -311,9 +313,15 @@ export default function CurrencyInputPanel({ ...@@ -311,9 +313,15 @@ export default function CurrencyInputPanel({
) : null} ) : null}
</ThemedText.Body> </ThemedText.Body>
{showMaxButton && selectedCurrencyBalance ? ( {showMaxButton && selectedCurrencyBalance ? (
<StyledBalanceMax onClick={onMax}> <TraceEvent
<Trans>MAX</Trans> events={[Event.onClick]}
</StyledBalanceMax> name={EventName.SWAP_MAX_TOKEN_AMOUNT_SELECTED}
element={ElementName.MAX_TOKEN_AMOUNT_BUTTON}
>
<StyledBalanceMax onClick={onMax}>
<Trans>MAX</Trans>
</StyledBalanceMax>
</TraceEvent>
) : null} ) : null}
</RowFixed> </RowFixed>
) : ( ) : (
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Trade } from '@uniswap/router-sdk' import { Trade } from '@uniswap/router-sdk'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core' import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { ModalName } from 'components/AmplitudeAnalytics/constants'
import { Trace } from 'components/AmplitudeAnalytics/Trace'
import { ReactNode, useCallback, useMemo } from 'react' import { ReactNode, useCallback, useMemo } from 'react'
import { InterfaceTrade } from 'state/routing/types' import { InterfaceTrade } from 'state/routing/types'
import { tradeMeaningfullyDiffers } from 'utils/tradeMeaningFullyDiffer' import { tradeMeaningfullyDiffers } from 'utils/tradeMeaningFullyDiffer'
...@@ -89,14 +91,16 @@ export default function ConfirmSwapModal({ ...@@ -89,14 +91,16 @@ export default function ConfirmSwapModal({
) )
return ( return (
<TransactionConfirmationModal <Trace modal={ModalName.CONFIRM_SWAP} shouldLogImpression={isOpen}>
isOpen={isOpen} <TransactionConfirmationModal
onDismiss={onDismiss} isOpen={isOpen}
attemptingTxn={attemptingTxn} onDismiss={onDismiss}
hash={txHash} attemptingTxn={attemptingTxn}
content={confirmationContent} hash={txHash}
pendingText={pendingText} content={confirmationContent}
currencyToAdd={trade?.outputAmount.currency} pendingText={pendingText}
/> currencyToAdd={trade?.outputAmount.currency}
/>
</Trace>
) )
} }
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core' import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'components/AmplitudeAnalytics/constants'
import { TraceEvent } from 'components/AmplitudeAnalytics/TraceEvent'
import AnimatedDropdown from 'components/AnimatedDropdown' import AnimatedDropdown from 'components/AnimatedDropdown'
import Card, { OutlineCard } from 'components/Card' import Card, { OutlineCard } from 'components/Card'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
...@@ -133,69 +135,76 @@ export default function SwapDetailsDropdown({ ...@@ -133,69 +135,76 @@ export default function SwapDetailsDropdown({
return ( return (
<Wrapper> <Wrapper>
<AutoColumn gap={'8px'} style={{ width: '100%', marginBottom: '-8px' }}> <AutoColumn gap={'8px'} style={{ width: '100%', marginBottom: '-8px' }}>
<StyledHeaderRow onClick={() => setShowDetails(!showDetails)} disabled={!trade} open={showDetails}> <TraceEvent
<RowFixed style={{ position: 'relative' }}> events={[Event.onClick]}
{loading || syncing ? ( name={EventName.SWAP_DETAILS_EXPANDED}
<StyledPolling> element={ElementName.SWAP_DETAILS_DROPDOWN}
<StyledPollingDot> shouldLogImpression={!showDetails}
<Spinner /> >
</StyledPollingDot> <StyledHeaderRow onClick={() => setShowDetails(!showDetails)} disabled={!trade} open={showDetails}>
</StyledPolling> <RowFixed style={{ position: 'relative' }}>
) : ( {loading || syncing ? (
<HideSmall> <StyledPolling>
<MouseoverTooltipContent <StyledPollingDot>
wrap={false} <Spinner />
content={ </StyledPollingDot>
<ResponsiveTooltipContainer origin="top right" style={{ padding: '0' }}> </StyledPolling>
<Card padding="12px"> ) : (
<AdvancedSwapDetails <HideSmall>
trade={trade} <MouseoverTooltipContent
allowedSlippage={allowedSlippage} wrap={false}
syncing={syncing} content={
hideInfoTooltips={true} <ResponsiveTooltipContainer origin="top right" style={{ padding: '0' }}>
/> <Card padding="12px">
</Card> <AdvancedSwapDetails
</ResponsiveTooltipContainer> trade={trade}
} allowedSlippage={allowedSlippage}
placement="bottom" syncing={syncing}
hideInfoTooltips={true}
/>
</Card>
</ResponsiveTooltipContainer>
}
placement="bottom"
disableHover={showDetails}
>
<StyledInfoIcon color={trade ? theme.deprecated_text3 : theme.deprecated_bg3} />
</MouseoverTooltipContent>
</HideSmall>
)}
{trade ? (
<LoadingOpacityContainer $loading={syncing}>
<TradePrice
price={trade.executionPrice}
showInverted={showInverted}
setShowInverted={setShowInverted}
/>
</LoadingOpacityContainer>
) : loading || syncing ? (
<ThemedText.Main fontSize={14}>
<Trans>Fetching best price...</Trans>
</ThemedText.Main>
) : null}
</RowFixed>
<RowFixed>
{!trade?.gasUseEstimateUSD ||
showDetails ||
!chainId ||
!SUPPORTED_GAS_ESTIMATE_CHAIN_IDS.includes(chainId) ? null : (
<GasEstimateBadge
trade={trade}
loading={syncing || loading}
showRoute={!showDetails}
disableHover={showDetails} disableHover={showDetails}
>
<StyledInfoIcon color={trade ? theme.deprecated_text3 : theme.deprecated_bg3} />
</MouseoverTooltipContent>
</HideSmall>
)}
{trade ? (
<LoadingOpacityContainer $loading={syncing}>
<TradePrice
price={trade.executionPrice}
showInverted={showInverted}
setShowInverted={setShowInverted}
/> />
</LoadingOpacityContainer> )}
) : loading || syncing ? ( <RotatingArrow
<ThemedText.Main fontSize={14}> stroke={trade ? theme.deprecated_text3 : theme.deprecated_bg3}
<Trans>Fetching best price...</Trans> open={Boolean(trade && showDetails)}
</ThemedText.Main>
) : null}
</RowFixed>
<RowFixed>
{!trade?.gasUseEstimateUSD ||
showDetails ||
!chainId ||
!SUPPORTED_GAS_ESTIMATE_CHAIN_IDS.includes(chainId) ? null : (
<GasEstimateBadge
trade={trade}
loading={syncing || loading}
showRoute={!showDetails}
disableHover={showDetails}
/> />
)} </RowFixed>
<RotatingArrow </StyledHeaderRow>
stroke={trade ? theme.deprecated_text3 : theme.deprecated_bg3} </TraceEvent>
open={Boolean(trade && showDetails)}
/>
</RowFixed>
</StyledHeaderRow>
<AnimatedDropdown open={showDetails}> <AnimatedDropdown open={showDetails}>
<AutoColumn gap={'8px'} style={{ padding: '0', paddingBottom: '8px' }}> <AutoColumn gap={'8px'} style={{ padding: '0', paddingBottom: '8px' }}>
{trade ? ( {trade ? (
......
...@@ -4,6 +4,8 @@ import { Currency, Percent, TradeType } from '@uniswap/sdk-core' ...@@ -4,6 +4,8 @@ import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk' import { Pair } from '@uniswap/v2-sdk'
import { FeeAmount } from '@uniswap/v3-sdk' import { FeeAmount } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'components/AmplitudeAnalytics/constants'
import { TraceEvent } from 'components/AmplitudeAnalytics/TraceEvent'
import AnimatedDropdown from 'components/AnimatedDropdown' import AnimatedDropdown from 'components/AnimatedDropdown'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import { LoadingRows } from 'components/Loader/styled' import { LoadingRows } from 'components/Loader/styled'
...@@ -62,13 +64,20 @@ export default memo(function SwapRoute({ trade, syncing, fixedOpen = false, ...r ...@@ -62,13 +64,20 @@ export default memo(function SwapRoute({ trade, syncing, fixedOpen = false, ...r
return ( return (
<Wrapper {...rest} darkMode={darkMode} fixedOpen={fixedOpen}> <Wrapper {...rest} darkMode={darkMode} fixedOpen={fixedOpen}>
<RowBetween onClick={() => setOpen(!open)}> <TraceEvent
<AutoRow gap="4px" width="auto"> events={[Event.onClick]}
<AutoRouterLogo /> name={EventName.SWAP_AUTOROUTER_VISUALIZATION_EXPANDED}
<AutoRouterLabel /> element={ElementName.AUTOROUTER_VISUALIZATION_ROW}
</AutoRow> shouldLogImpression={!open}
{fixedOpen ? null : <OpenCloseIcon open={open} />} >
</RowBetween> <RowBetween onClick={() => setOpen(!open)}>
<AutoRow gap="4px" width="auto">
<AutoRouterLogo />
<AutoRouterLabel />
</AutoRow>
{fixedOpen ? null : <OpenCloseIcon open={open} />}
</RowBetween>
</TraceEvent>
<AnimatedDropdown open={open || fixedOpen}> <AnimatedDropdown open={open || fixedOpen}>
<AutoRow gap="4px" width="auto" style={{ paddingTop: '12px', margin: 0 }}> <AutoRow gap="4px" width="auto" style={{ paddingTop: '12px', margin: 0 }}>
{syncing ? ( {syncing ? (
......
...@@ -463,18 +463,24 @@ export default function Swap() { ...@@ -463,18 +463,24 @@ export default function Swap() {
/> />
</Trace> </Trace>
<ArrowWrapper clickable={isSupportedChain(chainId)}> <ArrowWrapper clickable={isSupportedChain(chainId)}>
<ArrowDown <TraceEvent
size="16" events={[Event.onClick]}
onClick={() => { name={EventName.SWAP_TOKENS_REVERSED}
setApprovalSubmitted(false) // reset 2 step UI for approvals element={ElementName.SWAP_TOKENS_REVERSE_ARROW_BUTTON}
onSwitchTokens() >
}} <ArrowDown
color={ size="16"
currencies[Field.INPUT] && currencies[Field.OUTPUT] onClick={() => {
? theme.deprecated_text1 setApprovalSubmitted(false) // reset 2 step UI for approvals
: theme.deprecated_text3 onSwitchTokens()
} }}
/> color={
currencies[Field.INPUT] && currencies[Field.OUTPUT]
? theme.deprecated_text1
: theme.deprecated_text3
}
/>
</TraceEvent>
</ArrowWrapper> </ArrowWrapper>
<Trace section={SectionName.CURRENCY_OUTPUT_PANEL}> <Trace section={SectionName.CURRENCY_OUTPUT_PANEL}>
<CurrencyInputPanel <CurrencyInputPanel
......
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