Commit f5df2fed authored by Danny Daniil's avatar Danny Daniil Committed by GitHub

feat: de-148- Analytics package integration (#5093)

* integrate analytics sdk

* roll back vscode

* remove dup imports

* use dummy api key and url from env

* update analytics sdk for optional init

* yarn deduped

* update documentation

* add analytics events package

* getBrowser from analytics events

* remove token banner

* add origin app

* replace local analytics

* upgrade events version

* events 1.0.4

* remove importToken
parent 5e7f6333
import { createContext, memo, PropsWithChildren, useContext, useEffect, useMemo } from 'react'
import { sendAnalyticsEvent } from '.'
import { ElementName, EventName, ModalName, PageName, SectionName } from './constants'
export interface ITraceContext {
// Highest order context: eg Swap or Explore.
page?: PageName
// Enclosed section name. For contexts with modals, refers to the
// section of the page from which the user triggered the modal.
section?: SectionName
modal?: ModalName
// Element name mostly used to identify events sources
// Does not need to be unique given the higher order page and section.
element?: ElementName
}
export const TraceContext = createContext<ITraceContext>({})
export function useTrace(trace?: ITraceContext): ITraceContext {
const parentTrace = useContext(TraceContext)
return useMemo(() => ({ ...parentTrace, ...trace }), [parentTrace, trace])
}
type TraceProps = {
shouldLogImpression?: boolean // whether to log impression on mount
name?: EventName
properties?: Record<string, unknown>
} & ITraceContext
/**
* Sends an analytics event on mount (if shouldLogImpression is set),
* and propagates the context to child traces.
*/
export const Trace = memo(
({
shouldLogImpression,
name,
children,
page,
section,
modal,
element,
properties,
}: PropsWithChildren<TraceProps>) => {
const parentTrace = useTrace()
const combinedProps = useMemo(
() => ({
...parentTrace,
...Object.fromEntries(Object.entries({ page, section, modal, element }).filter(([_, v]) => v !== undefined)),
}),
[element, parentTrace, page, modal, section]
)
useEffect(() => {
if (shouldLogImpression) {
const commitHash = process.env.REACT_APP_GIT_COMMIT_HASH
sendAnalyticsEvent(name ?? EventName.PAGE_VIEWED, {
...combinedProps,
...properties,
git_commit_hash: commitHash,
})
}
// Impressions should only be logged on mount.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
return <TraceContext.Provider value={combinedProps}>{children}</TraceContext.Provider>
}
)
Trace.displayName = 'Trace'
import { Children, cloneElement, isValidElement, memo, PropsWithChildren, SyntheticEvent } from 'react'
import { sendAnalyticsEvent } from '.'
import { Event, EventName } from './constants'
import { ITraceContext, Trace, TraceContext } from './Trace'
type TraceEventProps = {
events: Event[]
name: EventName
properties?: Record<string, unknown>
shouldLogImpression?: boolean
} & ITraceContext
/**
* Analytics instrumentation component that wraps event callbacks with logging logic.
*
* @example
* <TraceEvent events={[Event.onClick]} element={ElementName.SWAP_BUTTON}>
* <Button onClick={() => console.log('clicked')}>Click me</Button>
* </TraceEvent>
*/
export const TraceEvent = memo((props: PropsWithChildren<TraceEventProps>) => {
const { shouldLogImpression, name, properties, events, children, ...traceProps } = props
return (
<Trace {...traceProps}>
<TraceContext.Consumer>
{(traceContext) =>
Children.map(children, (child) => {
if (!isValidElement(child)) {
return child
}
// For each child, augment event handlers defined in `events` with event tracing.
return cloneElement(
child,
getEventHandlers(child, traceContext, events, name, properties, shouldLogImpression)
)
})
}
</TraceContext.Consumer>
</Trace>
)
})
TraceEvent.displayName = 'TraceEvent'
/**
* Given a set of child element and event props, returns a spreadable
* object of the event handlers augmented with analytics logging.
*/
function getEventHandlers(
child: React.ReactElement,
traceContext: ITraceContext,
events: Event[],
name: EventName,
properties?: Record<string, unknown>,
shouldLogImpression = true
) {
const eventHandlers: Partial<Record<Event, (e: SyntheticEvent<Element, Event>) => void>> = {}
for (const event of events) {
eventHandlers[event] = (eventHandlerArgs: unknown) => {
// call child event handler with original arguments, must be in array
const args = Array.isArray(eventHandlerArgs) ? eventHandlerArgs : [eventHandlerArgs]
child.props[event]?.apply(child, args)
// augment handler with analytics logging
if (shouldLogImpression) sendAnalyticsEvent(name, { ...traceContext, ...properties, action: event })
}
}
// return a spreadable event handler object
return eventHandlers
}
/**
* Event names that can occur in this application.
*
* Subject to change as new features are added and new events are defined
* and logged.
*/
export enum EventName {
APP_LOADED = 'Application Loaded',
APPROVE_TOKEN_TXN_SUBMITTED = 'Approve Token Transaction Submitted',
CONNECT_WALLET_BUTTON_CLICKED = 'Connect Wallet Button Clicked',
EXPLORE_BANNER_CLICKED = 'Explore Banner Clicked',
EXPLORE_SEARCH_SELECTED = 'Explore Search Selected',
EXPLORE_TOKEN_ROW_CLICKED = 'Explore Token Row Clicked',
PAGE_VIEWED = 'Page Viewed',
NAVBAR_RESULT_SELECTED = 'Navbar Result Selected',
NAVBAR_SEARCH_SELECTED = 'Navbar Search Selected',
NAVBAR_SEARCH_EXITED = 'Navbar Search Exited',
NFT_ACTIVITY_SELECTED = 'NFT Activity Selected',
NFT_BUY_ADDED = 'NFT Buy Bag Added',
NFT_BUY_BAG_CHANGED = 'NFT Buy Bag Changed',
NFT_BUY_BAG_PAY = 'NFT Buy Bag Pay Clicked',
NFT_BUY_BAG_REFUNDED = 'NFT Buy Bag Refunded',
NFT_BUY_BAG_SIGNED = 'NFT Buy Bag Signed',
NFT_BUY_BAG_SUCCEEDED = 'NFT Buy Bag Succeeded',
NFT_FILTER_OPENED = 'NFT Collection Filter Opened',
NFT_FILTER_SELECTED = 'NFT Filter Selected',
NFT_LISTING_SIGNED = 'NFT Listing Signed',
NFT_LISTING_COMPLETED = 'NFT Listing Success',
NFT_SELL_ITEM_ADDED = 'NFT Sell Item Added',
NFT_SELL_SELECTED = 'NFT Sell Selected',
NFT_SELL_START_LISTING = 'NFT Sell Start Listing',
NFT_TRENDING_ROW_SELECTED = 'Trending Row Selected',
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_PRICE_UPDATE_ACKNOWLEDGED = 'Swap Price Update Acknowledged',
SWAP_QUOTE_RECEIVED = 'Swap Quote Received',
SWAP_SIGNED = 'Swap Signed',
SWAP_SUBMITTED_BUTTON_CLICKED = 'Swap Submit Button Clicked',
SWAP_TOKENS_REVERSED = 'Swap Tokens Reversed',
SWAP_TRANSACTION_COMPLETED = 'Swap Transaction Completed',
TOKEN_IMPORTED = 'Token Imported',
TOKEN_SELECTED = 'Token Selected',
TOKEN_SELECTOR_OPENED = 'Token Selector Opened',
WALLET_CONNECT_TXN_COMPLETED = 'Wallet Connect Transaction Completed',
WALLET_SELECTED = 'Wallet Selected',
WEB_VITALS = 'Web Vitals',
WRAP_TOKEN_TXN_INVALIDATED = 'Wrap Token Transaction Invalidated',
WRAP_TOKEN_TXN_SUBMITTED = 'Wrap Token Transaction Submitted',
// alphabetize additional event names.
}
export enum CUSTOM_USER_PROPERTIES {
ALL_WALLET_ADDRESSES_CONNECTED = 'all_wallet_addresses_connected',
ALL_WALLET_CHAIN_IDS = 'all_wallet_chain_ids',
USER_AGENT = 'user_agent',
BROWSER = 'browser',
DARK_MODE = 'is_dark_mode',
EXPERT_MODE = 'is_expert_mode',
SCREEN_RESOLUTION_HEIGHT = 'screen_resolution_height',
SCREEN_RESOLUTION_WIDTH = 'screen_resolution_width',
WALLET_ADDRESS = 'wallet_address',
WALLET_TYPE = 'wallet_type',
}
export enum BROWSER {
FIREFOX = 'Mozilla Firefox',
SAMSUNG = 'Samsung Internet',
OPERA = 'Opera',
INTERNET_EXPLORER = 'Microsoft Internet Explorer',
EDGE = 'Microsoft Edge (Legacy)',
EDGE_CHROMIUM = 'Microsoft Edge (Chromium)',
CHROME = 'Google Chrome or Chromium',
SAFARI = 'Apple Safari',
BRAVE = 'Brave',
UNKNOWN = 'unknown',
}
export enum WALLET_CONNECTION_RESULT {
SUCCEEDED = 'Succeeded',
FAILED = 'Failed',
}
export enum SWAP_PRICE_UPDATE_USER_RESPONSE {
ACCEPTED = 'Accepted',
REJECTED = 'Rejected',
}
/**
* Known pages in the app. Highest order context.
*/
export enum PageName {
NFT_COLLECTION_PAGE = 'nft-collection-page',
NFT_DETAILS_PAGE = 'nft-details-page',
NFT_EXPLORE_PAGE = 'nft-explore-page',
NFT_PROFILE_PAGE = 'nft-profile-page',
TOKEN_DETAILS_PAGE = 'token-details',
TOKENS_PAGE = 'tokens-page',
POOL_PAGE = 'pool-page',
SWAP_PAGE = 'swap-page',
VOTE_PAGE = 'vote-page',
// alphabetize additional page names.
}
/**
* Sections. Disambiguates low-level elements that may share a name.
* eg a `back` button in a modal will have the same `element`,
* but a different `section`.
*/
export enum SectionName {
CURRENCY_INPUT_PANEL = 'swap-currency-input',
CURRENCY_OUTPUT_PANEL = 'swap-currency-output',
NAVBAR_SEARCH = 'Navbar Search',
WIDGET = 'widget',
// alphabetize additional section names.
}
/** Known modals for analytics purposes. */
export enum ModalName {
CONFIRM_SWAP = 'confirm-swap-modal',
NFT_LISTING = 'nft-listing-modal',
NFT_TX_COMPLETE = 'nft-tx-complete-modal',
TOKEN_SELECTOR = 'token-selector-modal',
// alphabetize additional modal names.
}
/**
* Known element names for analytics purposes.
* Use to identify low-level components given a TraceContext
*/
export enum ElementName {
AUTOROUTER_VISUALIZATION_ROW = 'expandable-autorouter-visualization-row',
COMMON_BASES_CURRENCY_BUTTON = 'common-bases-currency-button',
CONFIRM_SWAP_BUTTON = 'confirm-swap-or-send',
CONNECT_WALLET_BUTTON = 'connect-wallet-button',
EXPLORE_BANNER = 'explore-banner',
EXPLORE_SEARCH_INPUT = 'explore_search_input',
IMPORT_TOKEN_BUTTON = 'import-token-button',
MAX_TOKEN_AMOUNT_BUTTON = 'max-token-amount-button',
NAVBAR_SEARCH_INPUT = 'navbar-search-input',
NFT_ACTIVITY_TAB = 'nft-activity-tab',
NFT_BUY_BAG_PAY_BUTTON = 'nft-buy-bag-pay-button',
NFT_FILTER_BUTTON = 'nft-filter-button',
NFT_FILTER_OPTION = 'nft-filter-option',
NFT_TRENDING_ROW = 'nft-trending-row',
PRICE_UPDATE_ACCEPT_BUTTON = 'price-update-accept-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',
WALLET_TYPE_OPTION = 'wallet-type-option',
// alphabetize additional element names.
}
/**
* Known events that trigger callbacks.
* @example
* <TraceEvent events={[Event.onClick]} element={name}>
*/
export enum Event {
onClick = 'onClick',
onFocus = 'onFocus',
onKeyPress = 'onKeyPress',
onSelect = 'onSelect',
// alphabetize additional events.
}
/** Known navbar search result types */
export enum NavBarSearchTypes {
COLLECTION_SUGGESTION = 'collection-suggestion',
COLLECTION_TRENDING = 'collection-trending',
RECENT_SEARCH = 'recent',
TOKEN_SUGGESTION = 'token-suggestion',
TOKEN_TRENDING = 'token-trending',
}
/**
* Known Filter Types for NFTs
*/
export enum FilterTypes {
MARKETPLACE = 'Marketplace',
PRICE_RANGE = 'Price Range',
TRAIT = 'Trait',
}
import { Identify, identify, init, track } from '@amplitude/analytics-browser'
import { isProductionEnv } from 'utils/env'
const DUMMY_KEY = '00000000000000000000000000000000'
const PROXY_URL = process.env.REACT_APP_AMPLITUDE_PROXY_URL
/**
* Initializes Amplitude SDK and configures it to send events to a Uniswap reverse proxy,
* which relays to events to relevant Amplitude endpoints. You must be a
* member of the organization on Amplitude to view logged events.
*/
export function initializeAnalytics() {
if (typeof PROXY_URL === 'undefined') {
console.error('REACT_APP_AMPLITUDE_PROXY_URL is undefined, Amplitude analytics will not run.')
return
}
init(
DUMMY_KEY,
/* userId= */ undefined, // User ID should be undefined to let Amplitude default to Device ID
/* options= */
{
// Configure the SDK to work with alternate endpoint
serverUrl: PROXY_URL,
// Disable tracking of private user information by Amplitude
trackingOptions: {
ipAddress: false,
carrier: false,
city: false,
region: false,
dma: false, // designated market area
},
}
)
}
/** Sends an event to Amplitude. */
export function sendAnalyticsEvent(eventName: string, eventProperties?: Record<string, unknown>) {
if (!PROXY_URL) {
console.log(`[analytics(${eventName})]: ${JSON.stringify(eventProperties)}`)
return
}
track(eventName, { ...eventProperties, origin })
}
type Value = string | number | boolean | string[] | number[]
/**
* Class that exposes methods to mutate the User Model's properties in
* Amplitude that represents the current session's user.
*
* See https://help.amplitude.com/hc/en-us/articles/115002380567-User-properties-and-event-properties
* for details.
*/
class UserModel {
private log(method: string, ...parameters: unknown[]) {
console.debug(`[amplitude(Identify)]: ${method}(${parameters})`)
}
private call(mutate: (event: Identify) => Identify) {
if (!isProductionEnv()) {
const log = (_: Identify, method: string) => this.log.bind(this, method)
mutate(new Proxy(new Identify(), { get: log }))
return
}
identify(mutate(new Identify()))
}
set(key: string, value: Value) {
this.call((event) => event.set(key, value))
}
setOnce(key: string, value: Value) {
this.call((event) => event.setOnce(key, value))
}
add(key: string, value: number) {
this.call((event) => event.add(key, value))
}
postInsert(key: string, value: string | number) {
this.call((event) => event.postInsert(key, value))
}
remove(key: string, value: string | number) {
this.call((event) => event.remove(key, value))
}
}
export const user = new UserModel()
import { Trans } from '@lingui/macro'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import { AutoColumn } from 'components/Column'
import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled'
import { isSupportedChain } from 'constants/chains'
......@@ -325,7 +325,7 @@ export default function SwapCurrencyInputPanel({
</ThemedText.DeprecatedBody>
{showMaxButton && selectedCurrencyBalance ? (
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.SWAP_MAX_TOKEN_AMOUNT_SELECTED}
element={ElementName.MAX_TOKEN_AMOUNT_BUTTON}
>
......
import { Trans } from '@lingui/macro'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import { AutoColumn } from 'components/Column'
import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled'
import { isSupportedChain } from 'constants/chains'
......@@ -314,7 +314,7 @@ export default function CurrencyInputPanel({
</ThemedText.DeprecatedBody>
{showMaxButton && selectedCurrencyBalance ? (
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.SWAP_MAX_TOKEN_AMOUNT_SELECTED}
element={ElementName.MAX_TOKEN_AMOUNT_BUTTON}
>
......
// eslint-disable-next-line no-restricted-imports
import { t } from '@lingui/macro'
import { sendAnalyticsEvent } from 'analytics'
import { ElementName, Event, EventName, SectionName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { useTrace } from 'analytics/Trace'
import { TraceEvent } from 'analytics/TraceEvent'
import { sendAnalyticsEvent, Trace, TraceEvent, useTrace } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName, SectionName } from '@uniswap/analytics-events'
import clsx from 'clsx'
import { NftVariant, useNftFlag } from 'featureFlags/flags/nft'
import useDebounce from 'hooks/useDebounce'
......@@ -140,7 +137,7 @@ export const SearchBar = () => {
</Box>
</Box>
<TraceEvent
events={[Event.onFocus]}
events={[BrowserEvent.onFocus]}
name={EventName.NAVBAR_SEARCH_SELECTED}
element={ElementName.NAVBAR_SEARCH_INPUT}
properties={{ ...trace }}
......
import { Trans } from '@lingui/macro'
import { NavBarSearchTypes, SectionName } from 'analytics/constants'
import { useTrace } from 'analytics/Trace'
import { useTrace } from '@uniswap/analytics'
import { NavBarSearchTypes, SectionName } from '@uniswap/analytics-events'
import { NftVariant, useNftFlag } from 'featureFlags/flags/nft'
import { useIsNftPage } from 'hooks/useIsNftPage'
import { Box } from 'nft/components/Box'
......
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName } from '@uniswap/analytics-events'
import { useWeb3React } from '@web3-react/core'
import { sendAnalyticsEvent } from 'analytics'
import { EventName } from 'analytics/constants'
import clsx from 'clsx'
import { L2NetworkLogo, LogoContainer } from 'components/Tokens/TokenTable/TokenRow'
import TokenSafetyIcon from 'components/TokenSafety/TokenSafetyIcon'
......
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { Currency } from '@uniswap/sdk-core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import { getTokenAddress } from 'analytics/utils'
import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo'
import { AutoRow } from 'components/Row'
import { COMMON_BASES } from 'constants/routing'
import { useTokenInfoFromActiveList } from 'hooks/useTokenInfoFromActiveList'
import { getTokenAddress } from 'lib/utils/analytics'
import { Text } from 'rebass'
import styled from 'styled-components/macro'
import { currencyId } from 'utils/currencyId'
......@@ -69,7 +69,7 @@ export default function CommonBases({
return (
<TraceEvent
events={[Event.onClick, Event.onKeyPress]}
events={[BrowserEvent.onClick, BrowserEvent.onKeyPress]}
name={EventName.TOKEN_SELECTED}
properties={formatAnalyticsEventProperties(currency, searchQuery, isAddressSearch)}
element={ElementName.COMMON_BASES_CURRENCY_BUTTON}
......
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import TokenSafetyIcon from 'components/TokenSafety/TokenSafetyIcon'
import { checkWarning } from 'constants/tokenSafety'
import { CSSProperties, MutableRefObject, useCallback, useMemo } from 'react'
......@@ -133,7 +133,7 @@ export function CurrencyRow({
// only show add or remove buttons if not on selected list
return (
<TraceEvent
events={[Event.onClick, Event.onKeyPress]}
events={[BrowserEvent.onClick, BrowserEvent.onKeyPress]}
name={EventName.TOKEN_SELECTED}
properties={{ is_imported_by_user: customAdded, ...eventProperties }}
element={ElementName.TOKEN_SELECTOR_ROW}
......
// eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro'
import { Trace } from '@uniswap/analytics'
import { EventName, ModalName } from '@uniswap/analytics-events'
import { Currency, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { EventName, ModalName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { sendEvent } from 'components/analytics'
import useDebounce from 'hooks/useDebounce'
import { useOnClickOutside } from 'hooks/useOnClickOutside'
......
import { Trans } from '@lingui/macro'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { formatToDecimal } from 'analytics/utils'
import CurrencyLogo from 'components/CurrencyLogo'
import { NATIVE_CHAIN_ID } from 'constants/tokens'
import { CHAIN_ID_TO_BACKEND_NAME } from 'graphql/data/util'
import { useStablecoinValue } from 'hooks/useStablecoinPrice'
import useCurrencyBalance from 'lib/hooks/useCurrencyBalance'
import { formatToDecimal } from 'lib/utils/analytics'
import { useMemo } from 'react'
import styled from 'styled-components/macro'
import { StyledInternalLink } from 'theme'
......
import { Trans } from '@lingui/macro'
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { Currency, NativeCurrency, Token } from '@uniswap/sdk-core'
import { PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import CurrencyLogo from 'components/CurrencyLogo'
import { AboutSection } from 'components/Tokens/TokenDetails/About'
import AddressSection from 'components/Tokens/TokenDetails/AddressSection'
......
import { Trans } from '@lingui/macro'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import searchIcon from 'assets/svg/search.svg'
import xIcon from 'assets/svg/x.svg'
import useDebounce from 'hooks/useDebounce'
......@@ -79,7 +79,7 @@ export default function SearchBar() {
<Trans
render={({ translation }) => (
<TraceEvent
events={[Event.onFocus]}
events={[BrowserEvent.onFocus]}
name={EventName.EXPLORE_SEARCH_SELECTED}
element={ElementName.EXPLORE_SEARCH_INPUT}
>
......
import { Trans } from '@lingui/macro'
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName } from '@uniswap/analytics-events'
import { ParentSize } from '@visx/responsive'
import { sendAnalyticsEvent } from 'analytics'
import { EventName } from 'analytics/constants'
import SparklineChart from 'components/Charts/SparklineChart'
import CurrencyLogo from 'components/CurrencyLogo'
import { getChainInfo } from 'constants/chainInfo'
......
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import React from 'react'
import { Check } from 'react-feather'
import styled from 'styled-components/macro'
......@@ -115,7 +115,7 @@ export default function Option({
}) {
const content = (
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.WALLET_SELECTED}
properties={{ wallet_type: header }}
element={ElementName.WALLET_TYPE_OPTION}
......
import { Trans } from '@lingui/macro'
import { sendAnalyticsEvent, user } from '@uniswap/analytics'
import { CustomUserProperties, EventName, WalletConnectionResult } from '@uniswap/analytics-events'
import { useWeb3React } from '@web3-react/core'
import { Connector } from '@web3-react/types'
import { sendAnalyticsEvent, user } from 'analytics'
import { CUSTOM_USER_PROPERTIES, EventName, WALLET_CONNECTION_RESULT } from 'analytics/constants'
import { sendEvent } from 'components/analytics'
import { AutoColumn } from 'components/Column'
import { AutoRow } from 'components/Row'
......@@ -126,17 +126,17 @@ const sendAnalyticsEventAndUserInfo = (
isReconnect: boolean
) => {
sendAnalyticsEvent(EventName.WALLET_CONNECT_TXN_COMPLETED, {
result: WALLET_CONNECTION_RESULT.SUCCEEDED,
result: WalletConnectionResult.SUCCEEDED,
wallet_address: account,
wallet_type: walletType,
is_reconnect: isReconnect,
})
user.set(CUSTOM_USER_PROPERTIES.WALLET_ADDRESS, account)
user.set(CUSTOM_USER_PROPERTIES.WALLET_TYPE, walletType)
user.set(CustomUserProperties.WALLET_ADDRESS, account)
user.set(CustomUserProperties.WALLET_TYPE, walletType)
if (chainId) {
user.postInsert(CUSTOM_USER_PROPERTIES.ALL_WALLET_CHAIN_IDS, chainId)
user.postInsert(CustomUserProperties.ALL_WALLET_CHAIN_IDS, chainId)
}
user.postInsert(CUSTOM_USER_PROPERTIES.ALL_WALLET_ADDRESSES_CONNECTED, account)
user.postInsert(CustomUserProperties.ALL_WALLET_ADDRESSES_CONNECTED, account)
}
export default function WalletModal({
......@@ -232,7 +232,7 @@ export default function WalletModal({
dispatch(updateConnectionError({ connectionType, error: error.message }))
sendAnalyticsEvent(EventName.WALLET_CONNECT_TXN_COMPLETED, {
result: WALLET_CONNECTION_RESULT.FAILED,
result: WalletConnectionResult.FAILED,
wallet_type: getConnectionName(connectionType, getIsMetaMask()),
})
}
......
import { Trans } from '@lingui/macro'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import { IconWrapper } from 'components/Identicon/StatusIcon'
import WalletDropdown from 'components/WalletDropdown'
import { getConnection } from 'connection/utils'
......@@ -265,7 +265,7 @@ function Web3StatusInner() {
}
return (
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.CONNECT_WALLET_BUTTON_CLICKED}
properties={{ received_swap_quote: validSwapQuote }}
element={ElementName.CONNECT_WALLET_BUTTON}
......
import { sendAnalyticsEvent, useTrace } from '@uniswap/analytics'
import { EventName, SectionName, SwapPriceUpdateUserResponse } from '@uniswap/analytics-events'
import { Trade } from '@uniswap/router-sdk'
import { Currency, TradeType } from '@uniswap/sdk-core'
import {
......@@ -8,9 +10,7 @@ import {
SwapWidgetSkeleton,
} from '@uniswap/widgets'
import { useWeb3React } from '@web3-react/core'
import { sendAnalyticsEvent } from 'analytics'
import { EventName, SectionName, SWAP_PRICE_UPDATE_USER_RESPONSE } from 'analytics/constants'
import { useTrace } from 'analytics/Trace'
import { useActiveLocale } from 'hooks/useActiveLocale'
import {
formatPercentInBasisPointsNumber,
formatSwapQuoteReceivedEventProperties,
......@@ -18,8 +18,7 @@ import {
getDurationFromDateMilliseconds,
getPriceUpdateBasisPoints,
getTokenAddress,
} from 'analytics/utils'
import { useActiveLocale } from 'hooks/useActiveLocale'
} from 'lib/utils/analytics'
import { useCallback, useState } from 'react'
import { useIsDarkMode } from 'state/user/hooks'
import { DARK_THEME, LIGHT_THEME } from 'theme/widget'
......@@ -94,7 +93,7 @@ export default function Widget({ token, onTokenChange, onReviewSwapClick }: Widg
(stale: Trade<Currency, Currency, TradeType>, update: Trade<Currency, Currency, TradeType>) => {
const eventProperties = {
chain_id: update.inputAmount.currency.chainId,
response: SWAP_PRICE_UPDATE_USER_RESPONSE.ACCEPTED,
response: SwapPriceUpdateUserResponse.ACCEPTED,
token_in_symbol: update.inputAmount.currency.symbol,
token_out_symbol: update.outputAmount.currency.symbol,
price_update_basis_points: getPriceUpdateBasisPoints(stale.executionPrice, update.executionPrice),
......
import { sendAnalyticsEvent, useTrace } from '@uniswap/analytics'
import { EventName, SectionName } from '@uniswap/analytics-events'
import { Currency, Field, SwapController, SwapEventHandlers, TradeType } from '@uniswap/widgets'
import { sendAnalyticsEvent } from 'analytics'
import { EventName, SectionName } from 'analytics/constants'
import { useTrace } from 'analytics/Trace'
import CurrencySearchModal from 'components/SearchModal/CurrencySearchModal'
import { useCallback, useEffect, useMemo, useState } from 'react'
......
import { sendAnalyticsEvent, useTrace } from '@uniswap/analytics'
import { EventName, SectionName } from '@uniswap/analytics-events'
import {
TradeType,
Transaction,
......@@ -6,12 +8,8 @@ import {
TransactionType as WidgetTransactionType,
} from '@uniswap/widgets'
import { useWeb3React } from '@web3-react/core'
import { sendAnalyticsEvent } from 'analytics'
import { EventName, SectionName } from 'analytics/constants'
import { useTrace } from 'analytics/Trace'
import { formatToDecimal, getTokenAddress } from 'analytics/utils'
import { formatSwapSignedAnalyticsEventProperties } from 'analytics/utils'
import { WrapType } from 'hooks/useWrapCallback'
import { formatSwapSignedAnalyticsEventProperties, formatToDecimal, getTokenAddress } from 'lib/utils/analytics'
import { useCallback, useMemo } from 'react'
import { useTransactionAdder } from 'state/transactions/hooks'
import {
......
import { Trans } from '@lingui/macro'
import { sendAnalyticsEvent, Trace } from '@uniswap/analytics'
import { EventName, ModalName } from '@uniswap/analytics-events'
import { Trade } from '@uniswap/router-sdk'
import { Currency, CurrencyAmount, Percent, Token, TradeType } from '@uniswap/sdk-core'
import { sendAnalyticsEvent } from 'analytics'
import { ModalName } from 'analytics/constants'
import { EventName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { formatSwapSignedAnalyticsEventProperties } from 'analytics/utils'
import { formatSwapSignedAnalyticsEventProperties } from 'lib/utils/analytics'
import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'
import { InterfaceTrade } from 'state/routing/types'
import { tradeMeaningfullyDiffers } from 'utils/tradeMeaningFullyDiffer'
......
import { Trans } from '@lingui/macro'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import AnimatedDropdown from 'components/AnimatedDropdown'
import Card, { OutlineCard } from 'components/Card'
import { AutoColumn } from 'components/Column'
......@@ -131,7 +131,7 @@ export default function SwapDetailsDropdown({
<Wrapper style={{ marginTop: '0' }}>
<AutoColumn gap={'8px'} style={{ width: '100%', marginBottom: '-8px' }}>
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.SWAP_DETAILS_EXPANDED}
element={ElementName.SWAP_DETAILS_DROPDOWN}
shouldLogImpression={!showDetails}
......
import { Trans } from '@lingui/macro'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { Currency, CurrencyAmount, Percent, Token, TradeType } from '@uniswap/sdk-core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import useTransactionDeadline from 'hooks/useTransactionDeadline'
import {
formatPercentInBasisPointsNumber,
formatPercentNumber,
......@@ -9,8 +10,7 @@ import {
getDurationFromDateMilliseconds,
getDurationUntilTimestampSeconds,
getTokenAddress,
} from 'analytics/utils'
import useTransactionDeadline from 'hooks/useTransactionDeadline'
} from 'lib/utils/analytics'
import { ReactNode } from 'react'
import { Text } from 'rebass'
import { InterfaceTrade } from 'state/routing/types'
......@@ -130,7 +130,7 @@ export default function SwapModalFooter({
<>
<AutoRow>
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
element={ElementName.CONFIRM_SWAP_BUTTON}
name={EventName.SWAP_SUBMITTED_BUTTON_CLICKED}
properties={formatAnalyticsEventProperties({
......
import { Trans } from '@lingui/macro'
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName, SwapPriceUpdateUserResponse } from '@uniswap/analytics-events'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { sendAnalyticsEvent } from 'analytics'
import { EventName, SWAP_PRICE_UPDATE_USER_RESPONSE } from 'analytics/constants'
import { getPriceUpdateBasisPoints } from 'analytics/utils'
import { getPriceUpdateBasisPoints } from 'lib/utils/analytics'
import { useEffect, useState } from 'react'
import { AlertTriangle, ArrowDown } from 'react-feather'
import { Text } from 'rebass'
......@@ -44,7 +44,7 @@ const ArrowWrapper = styled.div`
const formatAnalyticsEventProperties = (
trade: InterfaceTrade<Currency, Currency, TradeType>,
priceUpdate: number | undefined,
response: SWAP_PRICE_UPDATE_USER_RESPONSE
response: SwapPriceUpdateUserResponse
) => ({
chain_id:
trade.inputAmount.currency.chainId === trade.outputAmount.currency.chainId
......@@ -93,7 +93,7 @@ export default function SwapModalHeader({
if (shouldLogModalCloseEvent && showAcceptChanges)
sendAnalyticsEvent(
EventName.SWAP_PRICE_UPDATE_ACKNOWLEDGED,
formatAnalyticsEventProperties(trade, priceUpdate, SWAP_PRICE_UPDATE_USER_RESPONSE.REJECTED)
formatAnalyticsEventProperties(trade, priceUpdate, SwapPriceUpdateUserResponse.REJECTED)
)
setShouldLogModalCloseEvent(false)
}, [shouldLogModalCloseEvent, showAcceptChanges, setShouldLogModalCloseEvent, trade, priceUpdate])
......
import { Trans } from '@lingui/macro'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { Protocol } from '@uniswap/router-sdk'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { FeeAmount } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import AnimatedDropdown from 'components/AnimatedDropdown'
import { AutoColumn } from 'components/Column'
import { LoadingRows } from 'components/Loader/styled'
......@@ -65,7 +65,7 @@ export default memo(function SwapRoute({ trade, syncing, fixedOpen = false, ...r
return (
<Wrapper {...rest} darkMode={darkMode} fixedOpen={fixedOpen}>
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.SWAP_AUTOROUTER_VISUALIZATION_EXPANDED}
element={ElementName.AUTOROUTER_VISUALIZATION_ROW}
shouldLogImpression={!open}
......
import { Trans } from '@lingui/macro'
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName } from '@uniswap/analytics-events'
import { Currency } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { sendAnalyticsEvent } from 'analytics'
import { EventName } from 'analytics/constants'
import { formatToDecimal, getTokenAddress } from 'analytics/utils'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
import { formatToDecimal, getTokenAddress } from 'lib/utils/analytics'
import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
import { useMemo, useState } from 'react'
......
import { MaxUint256 } from '@ethersproject/constants'
import type { TransactionResponse } from '@ethersproject/providers'
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName } from '@uniswap/analytics-events'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { sendAnalyticsEvent } from 'analytics'
import { EventName } from 'analytics/constants'
import { getTokenAddress } from 'analytics/utils'
import { useTokenContract } from 'hooks/useContract'
import { useTokenAllowance } from 'hooks/useTokenAllowance'
import { getTokenAddress } from 'lib/utils/analytics'
import { useCallback, useMemo } from 'react'
import { calculateGasMargin } from 'utils/calculateGasMargin'
......
import { sendAnalyticsEvent } from 'analytics'
import { EventName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { sendAnalyticsEvent, Trace } from '@uniswap/analytics'
import { EventName } from '@uniswap/analytics-events'
import { BagRow, PriceChangeBagRow, UnavailableAssetsHeaderRow } from 'nft/components/bag/BagRow'
import { Column } from 'nft/components/Flex'
import { useBag, useIsMobile } from 'nft/hooks'
......
import { BigNumber } from '@ethersproject/bignumber'
import { parseEther } from '@ethersproject/units'
import { Trans } from '@lingui/macro'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import Loader from 'components/Loader'
import { SupportedChainId } from 'constants/chains'
import { Box } from 'nft/components/Box'
......@@ -169,7 +169,7 @@ export const BagFooter = ({
</Row>
</Column>
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.NFT_BUY_BAG_PAY}
element={ElementName.NFT_BUY_BAG_PAY_BUTTON}
properties={{ ...eventProperties }}
......
import { addressesByNetwork, SupportedChainId } from '@looksrare/sdk'
import { sendAnalyticsEvent, Trace, useTrace } from '@uniswap/analytics'
import { EventName, ModalName } from '@uniswap/analytics-events'
import { useWeb3React } from '@web3-react/core'
import { sendAnalyticsEvent } from 'analytics'
import { EventName, ModalName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { useTrace } from 'analytics/Trace'
import { Box } from 'nft/components/Box'
import { Column, Row } from 'nft/components/Flex'
import { ChevronLeftIcon, XMarkIcon } from 'nft/components/icons'
......
import { sendAnalyticsEvent, useTrace } from '@uniswap/analytics'
import { EventName, PageName } from '@uniswap/analytics-events'
import { ChainId } from '@uniswap/smart-order-router'
import { sendAnalyticsEvent } from 'analytics'
import { EventName, PageName } from 'analytics/constants'
import { useTrace } from 'analytics/Trace'
import { MouseoverTooltip } from 'components/Tooltip'
import { Box } from 'nft/components/Box'
import { Column, Row } from 'nft/components/Flex'
......
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { Box } from 'nft/components/Box'
import { Row } from 'nft/components/Flex'
import { useIsCollectionLoading } from 'nft/hooks'
......@@ -33,7 +33,7 @@ export const ActivitySwitcher = ({
Items
</Box>
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
element={ElementName.NFT_ACTIVITY_TAB}
name={EventName.NFT_ACTIVITY_SELECTED}
>
......
import { sendAnalyticsEvent } from 'analytics'
import { EventName, PageName } from 'analytics/constants'
import { useTrace } from 'analytics/Trace'
import { sendAnalyticsEvent, useTrace } from '@uniswap/analytics'
import { EventName, PageName } from '@uniswap/analytics-events'
import { useBag } from 'nft/hooks'
import { GenieAsset, Markets, UniformHeight } from 'nft/types'
import { formatWeiToDecimal, rarityProviderLogo } from 'nft/utils'
......
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import clsx from 'clsx'
import { loadingAnimation } from 'components/Loader/styled'
import { parseEther } from 'ethers/lib/utils'
......@@ -408,7 +408,7 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
<ActionsContainer>
<ActionsSubContainer>
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
element={ElementName.NFT_FILTER_BUTTON}
name={EventName.NFT_FILTER_OPENED}
shouldLogImpression={!isFiltersExpanded}
......
import { sendAnalyticsEvent } from 'analytics'
import { EventName, FilterTypes } from 'analytics/constants'
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName, FilterTypes } from '@uniswap/analytics-events'
import clsx from 'clsx'
import { Box } from 'nft/components/Box'
import * as styles from 'nft/components/collection/Filters.css'
......
import 'rc-slider/assets/index.css'
import { sendAnalyticsEvent } from 'analytics'
import { EventName, FilterTypes } from 'analytics/constants'
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName, FilterTypes } from '@uniswap/analytics-events'
import { Box } from 'nft/components/Box'
import { Row } from 'nft/components/Flex'
import { NumericInput } from 'nft/components/layout/Input'
......
import { sendAnalyticsEvent } from 'analytics'
import { EventName, FilterTypes } from 'analytics/constants'
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName, FilterTypes } from '@uniswap/analytics-events'
import useDebounce from 'hooks/useDebounce'
import { Box } from 'nft/components/Box'
import { Column, Row } from 'nft/components/Flex'
......
import { formatEther } from '@ethersproject/units'
import { EventName, ModalName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { useTrace } from 'analytics/Trace'
import { Trace, useTrace } from '@uniswap/analytics'
import { EventName, ModalName } from '@uniswap/analytics-events'
import clsx from 'clsx'
import { Box } from 'nft/components/Box'
import { Portal } from 'nft/components/common/Portal'
......
import { Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, EventName } from '@uniswap/analytics-events'
import { useNftBalanceQuery } from 'graphql/data/nft/NftBalance'
import { AnimatedBox, Box } from 'nft/components/Box'
import { assetList } from 'nft/components/collection/CollectionNfts.css'
......@@ -139,7 +139,7 @@ export const ProfilePage = () => {
<Row gap="8" flexWrap="nowrap">
{isSellMode && <SelectAllButton ownerAssets={ownerAssets ?? []} />}
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.NFT_SELL_SELECTED}
shouldLogImpression={!isSellMode}
>
......
import { sendAnalyticsEvent } from 'analytics'
import { EventName } from 'analytics/constants'
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName } from '@uniswap/analytics-events'
import { Box } from 'nft/components/Box'
import { Column, Row } from 'nft/components/Flex'
import { VerifiedIcon } from 'nft/components/icons'
......
......@@ -3,8 +3,8 @@ import { BigNumber } from '@ethersproject/bignumber'
import { hexStripZeros } from '@ethersproject/bytes'
import { ContractReceipt } from '@ethersproject/contracts'
import type { JsonRpcSigner } from '@ethersproject/providers'
import { sendAnalyticsEvent } from 'analytics'
import { EventName } from 'analytics/constants'
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName } from '@uniswap/analytics-events'
import create from 'zustand'
import { devtools } from 'zustand/middleware'
......
import { PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { useDetailsQuery } from 'graphql/data/nft/Details'
import { AssetDetails } from 'nft/components/details/AssetDetails'
import { AssetPriceDetails } from 'nft/components/details/AssetPriceDetails'
......
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { useWeb3React } from '@web3-react/core'
import { PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { useCollectionQuery } from 'graphql/data/nft/Collection'
import { MobileHoverBag } from 'nft/components/bag/MobileHoverBag'
import { AnimatedBox, Box } from 'nft/components/Box'
......
import { PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import Banner from 'nft/components/explore/Banner'
import TrendingCollections from 'nft/components/explore/TrendingCollections'
import styled from 'styled-components/macro'
......
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { useWeb3React } from '@web3-react/core'
import { PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { Box } from 'nft/components/Box'
import { Center, Column, Row } from 'nft/components/Flex'
import { ChevronLeftIcon, XMarkIcon } from 'nft/components/icons'
......
import { BigNumber } from '@ethersproject/bignumber'
import type { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { FeeAmount, NonfungiblePositionManager } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import { sendEvent } from 'components/analytics'
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
import useParsedQueryString from 'hooks/useParsedQueryString'
......@@ -441,7 +441,7 @@ export default function AddLiquidity() {
</ButtonPrimary>
) : !account ? (
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.CONNECT_WALLET_BUTTON_CLICKED}
properties={{ received_swap_quote: false }}
element={ElementName.CONNECT_WALLET_BUTTON}
......
import { BigNumber } from '@ethersproject/bignumber'
import type { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import { sendEvent } from 'components/analytics'
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
import { SwitchLocaleLink } from 'components/SwitchLocaleLink'
......@@ -436,7 +436,7 @@ export default function AddLiquidity() {
</ButtonPrimary>
) : !account ? (
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.CONNECT_WALLET_BUTTON_CLICKED}
properties={{ received_swap_quote: false }}
element={ElementName.CONNECT_WALLET_BUTTON}
......
import { initializeAnalytics, sendAnalyticsEvent, user } from 'analytics'
import { CUSTOM_USER_PROPERTIES, EventName, PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { initializeAnalytics, OriginApplication, sendAnalyticsEvent, Trace, user } from '@uniswap/analytics'
import { CustomUserProperties, EventName, getBrowser, PageName } from '@uniswap/analytics-events'
import Loader from 'components/Loader'
import TopLevelModals from 'components/TopLevelModals'
import { useFeatureFlagsIsLoaded } from 'featureFlags'
......@@ -14,7 +13,6 @@ import { useIsDarkMode } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { SpinnerSVG } from 'theme/components'
import { Z_INDEX } from 'theme/zIndex'
import { getBrowser } from 'utils/browser'
import { getCLS, getFCP, getFID, getLCP, Metric } from 'web-vitals'
import { useAnalyticsReporter } from '../components/analytics'
......@@ -48,6 +46,10 @@ const Collection = lazy(() => import('nft/pages/collection'))
const Profile = lazy(() => import('nft/pages/profile/profile'))
const Asset = lazy(() => import('nft/pages/asset/Asset'))
// Placeholder API key. Actual API key used in the proxy server
const ANALYTICS_DUMMY_KEY = '00000000000000000000000000000000'
const ANALYTICS_PROXY_URL = process.env.REACT_APP_AMPLITUDE_PROXY_URL
const AppWrapper = styled.div`
display: flex;
flex-flow: column;
......@@ -124,7 +126,7 @@ export default function App() {
const [scrolledState, setScrolledState] = useState(false)
useAnalyticsReporter()
initializeAnalytics()
initializeAnalytics(ANALYTICS_DUMMY_KEY, OriginApplication.INTERFACE, ANALYTICS_PROXY_URL)
const scrollListener = (e: Event) => {
if (window.scrollY > 0) {
......@@ -141,10 +143,10 @@ export default function App() {
useEffect(() => {
sendAnalyticsEvent(EventName.APP_LOADED)
user.set(CUSTOM_USER_PROPERTIES.USER_AGENT, navigator.userAgent)
user.set(CUSTOM_USER_PROPERTIES.BROWSER, getBrowser())
user.set(CUSTOM_USER_PROPERTIES.SCREEN_RESOLUTION_HEIGHT, window.screen.height)
user.set(CUSTOM_USER_PROPERTIES.SCREEN_RESOLUTION_WIDTH, window.screen.width)
user.set(CustomUserProperties.USER_AGENT, navigator.userAgent)
user.set(CustomUserProperties.BROWSER, getBrowser())
user.set(CustomUserProperties.SCREEN_RESOLUTION_HEIGHT, window.screen.height)
user.set(CustomUserProperties.SCREEN_RESOLUTION_WIDTH, window.screen.width)
getCLS(({ delta }: Metric) => sendAnalyticsEvent(EventName.WEB_VITALS, { cumulative_layout_shift: delta }))
getFCP(({ delta }: Metric) => sendAnalyticsEvent(EventName.WEB_VITALS, { first_contentful_paint_ms: delta }))
getFID(({ delta }: Metric) => sendAnalyticsEvent(EventName.WEB_VITALS, { first_input_delay_ms: delta }))
......@@ -152,11 +154,11 @@ export default function App() {
}, [])
useEffect(() => {
user.set(CUSTOM_USER_PROPERTIES.DARK_MODE, isDarkMode)
user.set(CustomUserProperties.DARK_MODE, isDarkMode)
}, [isDarkMode])
useEffect(() => {
user.set(CUSTOM_USER_PROPERTIES.EXPERT_MODE, isExpertMode)
user.set(CustomUserProperties.EXPERT_MODE, isExpertMode)
}, [isExpertMode])
useEffect(() => {
......
import { defaultAbiCoder } from '@ethersproject/abi'
import { getAddress, isAddress } from '@ethersproject/address'
import { Trans } from '@lingui/macro'
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { ButtonError } from 'components/Button'
import { BlueCard } from 'components/Card'
import { AutoColumn } from 'components/Column'
......
import { BigNumber } from '@ethersproject/bignumber'
import type { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { Currency, CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core'
import { NonfungiblePositionManager, Pool, Position } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core'
import { PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { sendEvent } from 'components/analytics'
import Badge from 'components/Badge'
import { ButtonConfirmed, ButtonGray, ButtonPrimary } from 'components/Button'
......
import { Trans } from '@lingui/macro'
import { Trace, TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName, PageName } from '@uniswap/analytics-events'
import { useWeb3React } from '@web3-react/core'
import { PageName } from 'analytics/constants'
import { ElementName, Event, EventName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { TraceEvent } from 'analytics/TraceEvent'
import { ButtonGray, ButtonPrimary, ButtonText } from 'components/Button'
import { AutoColumn } from 'components/Column'
import { FlyoutAlignment, NewMenu } from 'components/Menu'
......@@ -320,7 +318,7 @@ export default function Pool() {
)}
{showConnectAWallet && (
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.CONNECT_WALLET_BUTTON_CLICKED}
properties={{ received_swap_quote: false }}
element={ElementName.CONNECT_WALLET_BUTTON}
......
import { Trans } from '@lingui/macro'
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { Pair } from '@uniswap/v2-sdk'
import { useWeb3React } from '@web3-react/core'
import { PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { UNSUPPORTED_V2POOL_CHAIN_IDS } from 'constants/chains'
import JSBI from 'jsbi'
import { useMemo } from 'react'
......
import { Trans } from '@lingui/macro'
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import JSBI from 'jsbi'
import { useCallback, useEffect, useState } from 'react'
import { Plus } from 'react-feather'
......
......@@ -2,10 +2,10 @@ import { BigNumber } from '@ethersproject/bignumber'
import { Contract } from '@ethersproject/contracts'
import type { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { Currency, Percent } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'analytics/constants'
import { TraceEvent } from 'analytics/TraceEvent'
import { sendEvent } from 'components/analytics'
import { useV2LiquidityTokenPermit } from 'hooks/useV2LiquidityTokenPermit'
import { useCallback, useMemo, useState } from 'react'
......@@ -630,7 +630,7 @@ export default function RemoveLiquidity() {
<div style={{ position: 'relative' }}>
{!account ? (
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.CONNECT_WALLET_BUTTON_CLICKED}
properties={{ received_swap_quote: false }}
element={ElementName.CONNECT_WALLET_BUTTON}
......
import { Trans } from '@lingui/macro'
import { sendAnalyticsEvent, Trace, TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName, PageName, SectionName } from '@uniswap/analytics-events'
import { Trade } from '@uniswap/router-sdk'
import { Currency, CurrencyAmount, Percent, Token, TradeType } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { sendAnalyticsEvent } from 'analytics'
import { ElementName, Event, EventName, PageName, SectionName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { TraceEvent } from 'analytics/TraceEvent'
import { formatSwapQuoteReceivedEventProperties } from 'analytics/utils'
import { sendEvent } from 'components/analytics'
import { NetworkAlert } from 'components/NetworkAlert/NetworkAlert'
import PriceImpactWarning from 'components/swap/PriceImpactWarning'
......@@ -18,6 +15,7 @@ import { isSupportedChain } from 'constants/chains'
import { useSwapCallback } from 'hooks/useSwapCallback'
import useTransactionDeadline from 'hooks/useTransactionDeadline'
import JSBI from 'jsbi'
import { formatSwapQuoteReceivedEventProperties } from 'lib/utils/analytics'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { ReactNode } from 'react'
import { ArrowDown, CheckCircle, HelpCircle } from 'react-feather'
......@@ -557,7 +555,7 @@ export default function Swap() {
</SwapSection>
<ArrowWrapper clickable={isSupportedChain(chainId)}>
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.SWAP_TOKENS_REVERSED}
element={ElementName.SWAP_TOKENS_REVERSE_ARROW_BUTTON}
>
......@@ -640,7 +638,7 @@ export default function Swap() {
</ButtonPrimary>
) : !account ? (
<TraceEvent
events={[Event.onClick]}
events={[BrowserEvent.onClick]}
name={EventName.CONNECT_WALLET_BUTTON_CLICKED}
properties={{ received_swap_quote: getIsValidSwapQuote(trade, tradeState, swapInputError) }}
element={ElementName.CONNECT_WALLET_BUTTON}
......
import { Trans } from '@lingui/macro'
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { useWeb3React } from '@web3-react/core'
import { PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { MAX_WIDTH_MEDIA_BREAKPOINT, MEDIUM_MEDIA_BREAKPOINT } from 'components/Tokens/constants'
import { filterStringAtom } from 'components/Tokens/state'
import NetworkFilter from 'components/Tokens/TokenTable/NetworkFilter'
......
import { Trans } from '@lingui/macro'
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import { ButtonPrimary } from 'components/Button'
import { AutoColumn } from 'components/Column'
import { CardBGImage, CardNoise, CardSection, DataCard } from 'components/earn/styled'
......
import { BigNumber } from '@ethersproject/bignumber'
import { Trans } from '@lingui/macro'
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { CurrencyAmount, Fraction, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { PageName } from 'analytics/constants'
import { Trace } from 'analytics/Trace'
import ExecuteModal from 'components/vote/ExecuteModal'
import QueueModal from 'components/vote/QueueModal'
import { useActiveLocale } from 'hooks/useActiveLocale'
......
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { EventName } from '@uniswap/analytics-events'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { sendAnalyticsEvent } from 'analytics'
import { EventName } from 'analytics/constants'
import { formatPercentInBasisPointsNumber, formatToDecimal, getTokenAddress } from 'analytics/utils'
import { DEFAULT_TXN_DISMISS_MS, L2_TXN_DISMISS_MS } from 'constants/misc'
import LibUpdater from 'lib/hooks/transactions/updater'
import { formatPercentInBasisPointsNumber, formatToDecimal, getTokenAddress } from 'lib/utils/analytics'
import { useCallback, useMemo } from 'react'
import { useAppDispatch, useAppSelector } from 'state/hooks'
import { InterfaceTrade } from 'state/routing/types'
......
import { BROWSER } from 'analytics/constants'
// Get browser being used, code comes from: https://developer.mozilla.org/en-US/docs/Web/API/Window/navigator.
export function getBrowser(): string {
const sUsrAg = navigator.userAgent
// The order matters here, and this may report false positives for unlisted browsers.
if (sUsrAg.indexOf('Firefox') > -1) {
return BROWSER.FIREFOX
// "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0"
} else if (sUsrAg.indexOf('SamsungBrowser') > -1) {
return BROWSER.SAMSUNG
// "Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G955F Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/9.4 Chrome/67.0.3396.87 Mobile Safari/537.36
} else if (sUsrAg.indexOf('Opera') > -1 || sUsrAg.indexOf('OPR') > -1) {
return BROWSER.OPERA
// "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 OPR/57.0.3098.106"
} else if (sUsrAg.indexOf('Trident') > -1) {
return BROWSER.INTERNET_EXPLORER
} else if (sUsrAg.indexOf('Brave') > -1) {
return BROWSER.BRAVE
// "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; Zoom 3.6.0; wbx 1.0.0; rv:11.0) like Gecko"
} else if (sUsrAg.indexOf('Edge') > -1) {
return BROWSER.EDGE
// "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299"
} else if (sUsrAg.indexOf('Edg') > -1) {
return BROWSER.EDGE_CHROMIUM
// Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64
} else if (sUsrAg.indexOf('Chrome') > -1) {
return BROWSER.CHROME
// "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/66.0.3359.181 Chrome/66.0.3359.181 Safari/537.36"
} else if (sUsrAg.indexOf('Safari') > -1) {
return BROWSER.SAFARI
// "Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1 980x1306"
} else {
return BROWSER.UNKNOWN
}
}
......@@ -37,36 +37,46 @@
ethers "^5.5.2"
js-base64 "^3.7.2"
"@amplitude/analytics-browser@^1.1.4":
version "1.1.4"
resolved "https://registry.yarnpkg.com/@amplitude/analytics-browser/-/analytics-browser-1.1.4.tgz#a358598d7aea01d9275d02e5e26b780d72f7db64"
integrity sha512-iYncdLhB0tOPavhL5Jl+MWQh9zRidqw0iTB2TT+3GOAp0vxdSssz/uqW1t8zfsC3HsaqQHAGTczQZF00vfkUQQ==
"@amplitude/analytics-browser@^1.5.8":
version "1.6.1"
resolved "https://registry.yarnpkg.com/@amplitude/analytics-browser/-/analytics-browser-1.6.1.tgz#1b67f117643e3c3acba71a915e11d1e280a853eb"
integrity sha512-i9Mt3p6ikZm7zu6QRMIziSzNwWW3F2zEIKoOoBbMxy97hSliM93/VoLBLOzwMhusHK3Xy5OwcIgYVUHdXbmigw==
dependencies:
"@amplitude/analytics-connector" "^1.4.5"
"@amplitude/analytics-core" "^0.6.6"
"@amplitude/analytics-types" "^0.6.2"
"@amplitude/analytics-client-common" "^0.4.0"
"@amplitude/analytics-core" "^0.10.0"
"@amplitude/analytics-types" "^0.12.0"
"@amplitude/ua-parser-js" "^0.7.31"
tslib "^2.3.1"
"@amplitude/analytics-client-common@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@amplitude/analytics-client-common/-/analytics-client-common-0.4.0.tgz#5ba53af7d447a992d006f263dd9040c87e07ec6b"
integrity sha512-I3cy6AYCiVUqXAD6yU+tm3qBZdEyrdruDaUS/vVPoi+MvHIkZIXw7xaQjmkBRURWCgdcxu5LioU8r1ld1widtA==
dependencies:
"@amplitude/analytics-connector" "^1.4.5"
"@amplitude/analytics-core" "^0.10.0"
"@amplitude/analytics-types" "^0.12.0"
tslib "^2.3.1"
"@amplitude/analytics-connector@^1.4.5":
version "1.4.5"
resolved "https://registry.yarnpkg.com/@amplitude/analytics-connector/-/analytics-connector-1.4.5.tgz#07e9375101332bd8b6f15e39e70f31f287e87ad0"
integrity sha512-ELAP6ivg+13uSk+TOirGZE/92M+tTbeiQ/i7eXgDO4Hiy00Abf/UxO/rp9WovtxCyeFYTILrujEYxPv5cRQmFw==
version "1.4.6"
resolved "https://registry.yarnpkg.com/@amplitude/analytics-connector/-/analytics-connector-1.4.6.tgz#60a66eaf0bcdcd17db4f414ff340c69e63116a72"
integrity sha512-6jD2pOosRD4y8DT8StUCz7yTd5ZDkdOU9/AWnlWKM5qk90Mz7sdZrdZ9H7sA/L3yOJEpQOYZgQplQdWWUzyWug==
dependencies:
"@amplitude/ua-parser-js" "0.7.31"
"@amplitude/analytics-core@^0.6.6":
version "0.6.6"
resolved "https://registry.yarnpkg.com/@amplitude/analytics-core/-/analytics-core-0.6.6.tgz#12bb7a1ed9a9dbd0c14e0b5dfa2d3dcf1c71ab81"
integrity sha512-xj1SpK9koaHgqJnrNx8gyfDoFEpMyo/KmgMdx4GBC9ifQh0jntjTbYUTxQYmV9ORuR3znAIR1a4fcnbBaMyGkg==
"@amplitude/analytics-core@^0.10.0":
version "0.10.0"
resolved "https://registry.yarnpkg.com/@amplitude/analytics-core/-/analytics-core-0.10.0.tgz#0d68cede53fecaadfef9c36455eb271454b6ccee"
integrity sha512-D/6U9SzyDmcNWnT/lFnBKfYl4ASicLlwD1tqu4RZoYS3SwHd/PNST+LbnL3yBTEIJIY//qjth9lLBh/RRzePfg==
dependencies:
"@amplitude/analytics-types" "^0.6.2"
"@amplitude/analytics-types" "^0.12.0"
tslib "^2.3.1"
"@amplitude/analytics-types@^0.6.2":
version "0.6.2"
resolved "https://registry.yarnpkg.com/@amplitude/analytics-types/-/analytics-types-0.6.2.tgz#6fd97af97414fa2c6861c30aac3e24ce22152890"
integrity sha512-9tCIY5kF6e3nPLUZC7h3rTANK6uZJvMFmF8R59TrkTbmmsT2bpYS869LMEaZBp4AybxAi15oNkAJ4JE+CkPkFg==
"@amplitude/analytics-types@^0.12.0":
version "0.12.0"
resolved "https://registry.yarnpkg.com/@amplitude/analytics-types/-/analytics-types-0.12.0.tgz#aeec6f204758637603937f05393bdf89fa8e7a5b"
integrity sha512-XwySEhnCdU8fNWUNaB38JS7bwOt4GOUG8OqgzuXtR8HvGnpCvuT7C6H+BIGA7MfctNQBAzR+6IBgDD+8r1/OEQ==
"@amplitude/ua-parser-js@0.7.31", "@amplitude/ua-parser-js@^0.7.31":
version "0.7.31"
......@@ -4112,6 +4122,20 @@
"@typescript-eslint/types" "4.33.0"
eslint-visitor-keys "^2.0.0"
"@uniswap/analytics-events@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@uniswap/analytics-events/-/analytics-events-1.0.4.tgz#9f1133ceaa295cd6c72f716e7218d82616a5f463"
integrity sha512-HvDwT5q0uSBF9CutMyyK+tvSCoASLNhax44AB9RkU7MJB5g/YGTSg9J5w1BXpA8R611fdsHNfUHnqMft1s/pfA==
"@uniswap/analytics@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@uniswap/analytics/-/analytics-1.0.3.tgz#bb22cec8f722acd6b0937045f75c6e108e61016f"
integrity sha512-1DmKkGh5VlOQM8JXrCvvxkDn7KaDn/9aMrgVb9qOAXgBQ1QhsCkUeadsM2agDeJXQcY2JrOPbS04w/60vqHcXw==
dependencies:
"@amplitude/analytics-browser" "^1.5.8"
react "^18.2.0"
react-dom "^18.2.0"
"@uniswap/default-token-list@^2.0.0":
version "2.2.0"
resolved "https://registry.yarnpkg.com/@uniswap/default-token-list/-/default-token-list-2.2.0.tgz#d85a5c2520f57f4920bd989dfc9f01e1b701a567"
......@@ -17060,9 +17084,9 @@ tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2, tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1:
version "2.4.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
version "2.4.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==
tsutils@^3.17.1, tsutils@^3.21.0:
version "3.21.0"
......
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