ci(release): publish latest release

parent cd8fe9b1
IPFS hash of the deployment:
- CIDv0: `QmQRJ4TzV1zYobbsNLsA4WvSVSvpSxdRAMzWcyHjVyP5FK`
- CIDv1: `bafybeia647xbmz33dcdo7fwhybp54imlqc2hwkdnl53lbnurjajwiofaxy`
- CIDv0: `QmYjLCs2fp85NtK5CYeZBisiUZdf9ZLWBfaQ4CSG67qUyq`
- CIDv1: `bafybeie2mrhbxzypdlpnuhuxdtlhsdvuxtdmrawrp3hl6oufdrwyybhs5q`
The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org).
......@@ -10,15 +10,15 @@ You can also access the Uniswap Interface from an IPFS gateway.
Your Uniswap settings are never remembered across different URLs.
IPFS gateways:
- https://bafybeia647xbmz33dcdo7fwhybp54imlqc2hwkdnl53lbnurjajwiofaxy.ipfs.dweb.link/
- https://bafybeia647xbmz33dcdo7fwhybp54imlqc2hwkdnl53lbnurjajwiofaxy.ipfs.cf-ipfs.com/
- [ipfs://QmQRJ4TzV1zYobbsNLsA4WvSVSvpSxdRAMzWcyHjVyP5FK/](ipfs://QmQRJ4TzV1zYobbsNLsA4WvSVSvpSxdRAMzWcyHjVyP5FK/)
- https://bafybeie2mrhbxzypdlpnuhuxdtlhsdvuxtdmrawrp3hl6oufdrwyybhs5q.ipfs.dweb.link/
- https://bafybeie2mrhbxzypdlpnuhuxdtlhsdvuxtdmrawrp3hl6oufdrwyybhs5q.ipfs.cf-ipfs.com/
- [ipfs://QmYjLCs2fp85NtK5CYeZBisiUZdf9ZLWBfaQ4CSG67qUyq/](ipfs://QmYjLCs2fp85NtK5CYeZBisiUZdf9ZLWBfaQ4CSG67qUyq/)
### 5.51.6 (2024-10-11)
## 5.52.0 (2024-10-11)
### Bug Fixes
### Features
* **web:** hide astrochain usdc (#12963) acd6d55
* **web:** remove red gas UI on web shared swap [prod] + 2 other hotfixes (#12948) 18013a2
web/5.51.6
\ No newline at end of file
web/5.52.0
\ No newline at end of file
......@@ -11,9 +11,8 @@ import { updateSignature } from 'state/signatures/reducer'
import { SignatureType } from 'state/signatures/types'
import { addTransaction, finalizeTransaction } from 'state/transactions/reducer'
import { TransactionType } from 'state/transactions/types'
import { logSwapSuccess, logUniswapXSwapSuccess } from 'tracing/swapFlowLoggers'
import { logSwapFinalized, logUniswapXSwapFinalized } from 'tracing/swapFlowLoggers'
import { UniswapXOrderStatus } from 'types/uniswapx'
import { TransactionStatus } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks'
import { isL2ChainId } from 'uniswap/src/features/chains/utils'
import { useTrace } from 'utilities/src/telemetry/trace/TraceContext'
......@@ -52,8 +51,8 @@ function useOnActivityUpdate(): OnActivityUpdate {
const hash = original.hash
dispatch(finalizeTransaction({ chainId, hash, ...update }))
if (original.info.type === TransactionType.SWAP && update.status === TransactionStatus.Confirmed) {
logSwapSuccess(hash, chainId, analyticsContext)
if (original.info.type === TransactionType.SWAP) {
logSwapFinalized(hash, chainId, analyticsContext, update.status)
}
addPopup({ type: PopupType.Transaction, hash }, hash, popupDismissalTime)
......@@ -68,6 +67,9 @@ function useOnActivityUpdate(): OnActivityUpdate {
const updatedOrder = { ...original, ...update }
dispatch(updateSignature(updatedOrder))
// SignatureDetails.type should not be typed as optional, but this will be fixed when we merge activity for uniswap. The default value appeases the typechecker.
const signatureType = updatedOrder.type ?? SignatureType.SIGN_UNISWAPX_V2_ORDER
if (updatedOrder.status === UniswapXOrderStatus.FILLED) {
const hash = updatedOrder.txHash
const from = original.offerer
......@@ -75,13 +77,34 @@ function useOnActivityUpdate(): OnActivityUpdate {
dispatch(addTransaction({ chainId, from, hash, info: updatedOrder.swapInfo }))
addPopup({ type: PopupType.Transaction, hash }, hash, popupDismissalTime)
// Only track swap success for Dutch orders; limit order fill-time will throw off time tracking analytics
// Only track swap success for non-limit orders; limit order fill-time will throw off time tracking analytics
if (original.type !== SignatureType.SIGN_LIMIT) {
logUniswapXSwapSuccess(hash, updatedOrder.orderHash, chainId, analyticsContext)
logUniswapXSwapFinalized(
hash,
updatedOrder.orderHash,
chainId,
analyticsContext,
signatureType,
UniswapXOrderStatus.FILLED,
)
}
} else if (original.status !== updatedOrder.status) {
const orderHash = original.orderHash
addPopup({ type: PopupType.Order, orderHash }, orderHash, popupDismissalTime)
if (
updatedOrder.status === UniswapXOrderStatus.CANCELLED ||
updatedOrder.status === UniswapXOrderStatus.EXPIRED
) {
logUniswapXSwapFinalized(
undefined,
updatedOrder.orderHash,
chainId,
analyticsContext,
signatureType,
updatedOrder.status,
)
}
}
}
},
......
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import ms from 'ms'
import {
GetQuickQuoteArgs,
PreviewTradeResult,
QuickRouteResponse,
QuoteState,
RouterPreference,
} from 'state/routing/types'
import { GetQuickQuoteArgs, PreviewTradeResult, QuickRouteResponse, QuoteState } from 'state/routing/types'
import { isExactInput, transformQuickRouteToTrade } from 'state/routing/utils'
import { logSwapQuoteRequest } from 'tracing/swapFlowLoggers'
import { trace } from 'tracing/trace'
import { InterfaceEventNameLocal } from 'uniswap/src/features/telemetry/constants'
import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send'
import { logSwapQuoteFetch } from 'uniswap/src/features/transactions/swap/analytics'
const UNISWAP_GATEWAY_DNS_URL = process.env.REACT_APP_UNISWAP_GATEWAY_DNS
if (UNISWAP_GATEWAY_DNS_URL === undefined) {
......@@ -25,7 +19,7 @@ export const quickRouteApi = createApi({
getQuickRoute: build.query<PreviewTradeResult, GetQuickQuoteArgs>({
queryFn(args, _api, _extraOptions, fetch) {
return trace({ name: 'QuickRoute', op: 'quote.quick_route' }, async (trace) => {
logSwapQuoteRequest(args.tokenInChainId, RouterPreference.API, true)
logSwapQuoteFetch({ chainId: args.tokenInChainId, isQuickRoute: true })
const { tokenInAddress, tokenInChainId, tokenOutAddress, tokenOutChainId, amount, tradeType } = args
const type = isExactInput(tradeType) ? 'EXACT_IN' : 'EXACT_OUT'
......
......@@ -18,10 +18,10 @@ import {
UniswapXv2Config,
} from 'state/routing/types'
import { isExactInput, transformQuoteToTrade } from 'state/routing/utils'
import { logSwapQuoteRequest } from 'tracing/swapFlowLoggers'
import { trace } from 'tracing/trace'
import { InterfaceEventNameLocal } from 'uniswap/src/features/telemetry/constants'
import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send'
import { logSwapQuoteFetch } from 'uniswap/src/features/transactions/swap/analytics'
import { logger } from 'utilities/src/logger/logger'
const UNISWAP_GATEWAY_DNS_URL = process.env.REACT_APP_UNISWAP_GATEWAY_DNS
......@@ -107,7 +107,10 @@ export const routingApi = createApi({
getQuote: build.query<TradeResult, GetQuoteArgs>({
queryFn(args, _api, _extraOptions, fetch) {
return trace({ name: 'Quote', op: 'quote', data: { ...args } }, async (trace) => {
logSwapQuoteRequest(args.tokenInChainId, args.routerPreference, false)
logSwapQuoteFetch({
chainId: args.tokenInChainId,
isUSDQuote: args.routerPreference === INTERNAL_ROUTER_PREFERENCE_PRICE,
})
const {
tokenInAddress: tokenIn,
tokenInChainId,
......
import { SwapEventName } from '@uniswap/analytics-events'
import { INTERNAL_ROUTER_PREFERENCE_PRICE, RouterPreference } from 'state/routing/types'
import { logSwapQuoteRequest, logSwapSuccess, logUniswapXSwapSuccess } from 'tracing/swapFlowLoggers'
import { SignatureType } from 'state/signatures/types'
import { logSwapFinalized, logUniswapXSwapFinalized } from 'tracing/swapFlowLoggers'
import { UniswapXOrderStatus } from 'types/uniswapx'
import { TransactionStatus } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks'
import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send'
import { maybeLogFirstSwapAction } from 'uniswap/src/features/transactions/swap/utils/maybeLogFirstSwapAction'
import { TransactionOriginType } from 'uniswap/src/features/transactions/types/transactionDetails'
......@@ -28,7 +30,7 @@ describe('swapFlowLoggers', () => {
const mockChainId = 1
const mockAnalyticsContext = { page: 'mockContext' }
logSwapSuccess(mockHash, mockChainId, mockAnalyticsContext)
logSwapFinalized(mockHash, mockChainId, mockAnalyticsContext, TransactionStatus.Confirmed)
expect(sendAnalyticsEvent).toHaveBeenCalledWith(SwapEventName.SWAP_TRANSACTION_COMPLETED, {
transactionOriginType: TransactionOriginType.Internal,
......@@ -47,7 +49,14 @@ describe('swapFlowLoggers', () => {
const mockChainId = 1
const mockAnalyticsContext = { page: 'mockContext' }
logUniswapXSwapSuccess(mockHash, mockOrderHash, mockChainId, mockAnalyticsContext)
logUniswapXSwapFinalized(
mockHash,
mockOrderHash,
mockChainId,
mockAnalyticsContext,
SignatureType.SIGN_UNISWAPX_V2_ORDER,
UniswapXOrderStatus.FILLED,
)
expect(sendAnalyticsEvent).toHaveBeenCalledWith(SwapEventName.SWAP_TRANSACTION_COMPLETED, {
transactionOriginType: TransactionOriginType.Internal,
......@@ -71,28 +80,4 @@ describe('swapFlowLoggers', () => {
...mockAnalyticsContext,
})
})
it('logSwapQuoteRequest calls sendAnalyticsEvent with correct parameters', () => {
const mockChainId = 1
logSwapQuoteRequest(mockChainId, RouterPreference.X)
expect(sendAnalyticsEvent).toHaveBeenCalledWith(SwapEventName.SWAP_QUOTE_FETCH, {
chainId: mockChainId,
isQuickRoute: false,
time_to_first_quote_request: 100,
time_to_first_quote_request_since_first_input: 100,
})
})
it('logSwapQuoteRequest excludes perf metrics for price quotes', () => {
const mockChainId = 1
logSwapQuoteRequest(mockChainId, INTERNAL_ROUTER_PREFERENCE_PRICE)
expect(sendAnalyticsEvent).toHaveBeenCalledWith(SwapEventName.SWAP_QUOTE_FETCH, {
chainId: mockChainId,
isQuickRoute: false,
})
})
})
import { SwapEventName } from '@uniswap/analytics-events'
import { INTERNAL_ROUTER_PREFERENCE_PRICE, RouterPreference } from 'state/routing/types'
import { SignatureType } from 'state/signatures/types'
import { ConfirmedTransactionDetails } from 'state/transactions/types'
import { UniswapXOrderStatus } from 'types/uniswapx'
import { TransactionStatus } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks'
import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send'
import { SwapRouting } from 'uniswap/src/features/telemetry/types'
import { SwapEventType, timestampTracker } from 'uniswap/src/features/transactions/swap/utils/SwapEventTimestampTracker'
import { TransactionOriginType } from 'uniswap/src/features/transactions/types/transactionDetails'
import { ITraceContext } from 'utilities/src/telemetry/trace/TraceContext'
export function logSwapSuccess(hash: string, chainId: number, analyticsContext: ITraceContext) {
export function logSwapFinalized(
hash: string,
chainId: number,
analyticsContext: ITraceContext,
status: ConfirmedTransactionDetails['status'],
) {
const hasSetSwapSuccess = timestampTracker.hasTimestamp(SwapEventType.FirstSwapSuccess)
const elapsedTime = timestampTracker.setElapsedTime(SwapEventType.FirstSwapSuccess)
sendAnalyticsEvent(SwapEventName.SWAP_TRANSACTION_COMPLETED, {
const event =
status === TransactionStatus.Confirmed
? SwapEventName.SWAP_TRANSACTION_COMPLETED
: SwapEventName.SWAP_TRANSACTION_FAILED
sendAnalyticsEvent(event, {
routing: 'classic',
// We only log the time-to-swap metric for the first swap of a session,
// so if it was previously set we log undefined here.
......@@ -23,17 +37,32 @@ export function logSwapSuccess(hash: string, chainId: number, analyticsContext:
...analyticsContext,
})
}
export function logUniswapXSwapSuccess(
hash: string,
const SIGNATURE_TYPE_TO_SWAP_ROUTING: Record<SignatureType, SwapRouting> = {
[SignatureType.SIGN_LIMIT]: 'limit_order',
[SignatureType.SIGN_PRIORITY_ORDER]: 'priority_order',
[SignatureType.SIGN_UNISWAPX_V2_ORDER]: 'uniswap_x_v2',
[SignatureType.SIGN_UNISWAPX_ORDER]: 'uniswap_x',
}
export function logUniswapXSwapFinalized(
hash: string | undefined,
orderHash: string,
chainId: number,
analyticsContext: ITraceContext,
signatureType: SignatureType,
status: UniswapXOrderStatus.FILLED | UniswapXOrderStatus.CANCELLED | UniswapXOrderStatus.EXPIRED,
) {
const hasSetSwapSuccess = timestampTracker.hasTimestamp(SwapEventType.FirstSwapSuccess)
const elapsedTime = timestampTracker.setElapsedTime(SwapEventType.FirstSwapSuccess)
sendAnalyticsEvent(SwapEventName.SWAP_TRANSACTION_COMPLETED, {
routing: 'uniswap_x_v2',
const event =
status === UniswapXOrderStatus.FILLED
? SwapEventName.SWAP_TRANSACTION_COMPLETED
: SwapEventName.SWAP_TRANSACTION_FAILED
sendAnalyticsEvent(event, {
routing: SIGNATURE_TYPE_TO_SWAP_ROUTING[signatureType],
order_hash: orderHash,
transactionOriginType: TransactionOriginType.Internal,
// We only log the time-to-swap metric for the first swap of a session,
......@@ -47,27 +76,3 @@ export function logUniswapXSwapSuccess(
...analyticsContext,
})
}
export function logSwapQuoteRequest(
chainId: number,
routerPreference: RouterPreference | typeof INTERNAL_ROUTER_PREFERENCE_PRICE,
isQuickRoute?: boolean,
) {
let performanceMetrics = {}
if (routerPreference !== INTERNAL_ROUTER_PREFERENCE_PRICE) {
const hasSetSwapQuote = timestampTracker.hasTimestamp(SwapEventType.FirstQuoteFetchStarted)
const elapsedTime = timestampTracker.setElapsedTime(SwapEventType.FirstQuoteFetchStarted)
performanceMetrics = {
// We only log the time_to_first_quote_request metric for the first quote request of a session.
time_to_first_quote_request: hasSetSwapQuote ? undefined : elapsedTime,
time_to_first_quote_request_since_first_input: hasSetSwapQuote
? undefined
: timestampTracker.getElapsedTime(SwapEventType.FirstQuoteFetchStarted, SwapEventType.FirstSwapAction),
}
}
sendAnalyticsEvent(SwapEventName.SWAP_QUOTE_FETCH, {
chainId,
isQuickRoute: isQuickRoute ?? false,
...performanceMetrics,
})
}
import { InterfaceEventName, InterfaceModalName } from '@uniswap/analytics-events'
import { Currency } from '@uniswap/sdk-core'
import { hasStringAsync } from 'expo-clipboard'
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
......@@ -256,7 +257,11 @@ export function TokenSelectorContent({
])
return (
<>
<Trace
logImpression={isInterface} // TODO(WEB-5161): Deduplicate shared vs interface-only trace event
eventOnTrigger={InterfaceEventName.TOKEN_SELECTOR_OPENED}
modal={InterfaceModalName.TOKEN_SELECTOR}
>
<Trace logImpression element={currencyFieldName} section={SectionName.TokenSelector}>
<Flex grow gap="$spacing8" style={scrollbarStyles}>
{!isSmallScreen && (
......@@ -311,7 +316,7 @@ export function TokenSelectorContent({
{isSurfaceReady && <Flex grow>{tokenSelector}</Flex>}
</Flex>
</Trace>
</>
</Trace>
)
}
......
......@@ -14,6 +14,7 @@ import { GasFeeResult } from 'uniswap/src/features/gas/types'
import { NetworkFeeWarning } from 'uniswap/src/features/transactions/swap/modals/NetworkFeeWarning'
import { UniswapXGasBreakdown } from 'uniswap/src/features/transactions/swap/types/swapTxAndGasInfo'
import { UniverseChainId } from 'uniswap/src/types/chains'
import { isInterface } from 'utilities/src/platform'
export function NetworkFee({
chainId,
......@@ -39,6 +40,7 @@ export function NetworkFee({
const uniswapXGasFeeInfo = useFormattedUniswapXGasFeeInfo(uniswapXGasBreakdown, chainId)
const gasFeeHighRelativeToValue = useGasFeeHighRelativeToValue(gasFeeUSD, transactionUSDValue)
const showHighGasFeeUI = gasFeeHighRelativeToValue && !isInterface // Avoid high gas UI on interface
return (
<Flex row alignItems="center" gap="$spacing12" justifyContent="space-between">
......@@ -60,7 +62,7 @@ export function NetworkFee({
<UniswapXFee gasFee={gasFeeFormatted} preSavingsGasFee={uniswapXGasFeeInfo?.preSavingsGasFeeFormatted} />
) : (
<Text
color={gasFee.isLoading ? '$neutral3' : gasFeeHighRelativeToValue ? '$statusCritical' : '$neutral1'}
color={gasFee.isLoading ? '$neutral3' : showHighGasFeeUI ? '$statusCritical' : '$neutral1'}
variant="body3"
>
{gasFeeFormatted}
......
......@@ -3,6 +3,7 @@ import { uniswapUrls } from 'uniswap/src/constants/urls'
import { TRADING_API_CACHE_KEY, fetchIndicativeQuote } from 'uniswap/src/data/apiClients/tradingApi/TradingApiClient'
import { UseQueryApiHelperHookArgs } from 'uniswap/src/data/apiClients/types'
import { IndicativeQuoteRequest, IndicativeQuoteResponse } from 'uniswap/src/data/tradingApi/__generated__'
import { logSwapQuoteFetch } from 'uniswap/src/features/transactions/swap/analytics'
export function useTradingApiIndicativeQuoteQuery({
params,
......@@ -16,7 +17,12 @@ export function useTradingApiIndicativeQuoteQuery({
return useQuery<IndicativeQuoteResponse>({
queryKey,
queryFn: params
? async (): ReturnType<typeof fetchIndicativeQuote> => await fetchIndicativeQuote(params)
? async (): ReturnType<typeof fetchIndicativeQuote> => {
if (params.tokenInChainId) {
logSwapQuoteFetch({ chainId: params.tokenInChainId, isQuickRoute: true })
}
return await fetchIndicativeQuote(params)
}
: skipToken,
...rest,
})
......
......@@ -9,22 +9,28 @@ import {
} from 'uniswap/src/data/apiClients/tradingApi/TradingApiClient'
import { UseQueryWithImmediateGarbageCollectionApiHelperHookArgs } from 'uniswap/src/data/apiClients/types'
import { QuoteRequest } from 'uniswap/src/data/tradingApi/__generated__'
import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { logSwapQuoteFetch } from 'uniswap/src/features/transactions/swap/analytics'
export function useTradingApiQuoteQuery({
params,
...rest
}: UseQueryWithImmediateGarbageCollectionApiHelperHookArgs<
WithV4Flag<QuoteRequest>,
WithV4Flag<QuoteRequest & { isUSDQuote?: boolean }>,
DiscriminatedQuoteResponse
>): UseQueryResult<DiscriminatedQuoteResponse> {
const queryKey = [TRADING_API_CACHE_KEY, uniswapUrls.tradingApiPaths.quote, params]
const v4Enabled = useFeatureFlag(FeatureFlags.V4Swap)
return useQueryWithImmediateGarbageCollection<DiscriminatedQuoteResponse>({
queryKey,
queryFn: params ? async (): ReturnType<typeof fetchQuote> => await fetchQuote({ ...params, v4Enabled }) : skipToken,
queryFn: params
? async (): ReturnType<typeof fetchQuote> => {
const { isUSDQuote, ...fetchParams } = params
if (fetchParams.tokenInChainId) {
logSwapQuoteFetch({ chainId: fetchParams.tokenInChainId, isUSDQuote })
}
return await fetchQuote(fetchParams)
}
: skipToken,
...rest,
})
}
import { SwapEventName } from '@uniswap/analytics-events'
import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send'
import { logSwapQuoteFetch } from 'uniswap/src/features/transactions/swap/analytics'
jest.mock('uniswap/src/features/telemetry/send', () => ({
sendAnalyticsEvent: jest.fn(),
}))
jest.mock('uniswap/src/features/transactions/swap/utils/SwapEventTimestampTracker', () => ({
...jest.requireActual('uniswap/src/features/transactions/swap/utils/SwapEventTimestampTracker'),
timestampTracker: {
hasTimestamp: (): boolean => false,
setElapsedTime: (): number => 100,
getElapsedTime: (): number => 100,
},
}))
describe('analytics', () => {
beforeEach(() => {
jest.clearAllMocks()
})
it('logSwapQuoteRequest calls sendAnalyticsEvent with correct parameters', () => {
const mockChainId = 1
logSwapQuoteFetch({ chainId: mockChainId })
expect(sendAnalyticsEvent).toHaveBeenCalledWith(SwapEventName.SWAP_QUOTE_FETCH, {
chainId: mockChainId,
isQuickRoute: false,
time_to_first_quote_request: 100,
time_to_first_quote_request_since_first_input: 100,
})
})
it('logSwapQuoteRequest excludes perf metrics for price quotes', () => {
const mockChainId = 1
logSwapQuoteFetch({ chainId: mockChainId, isUSDQuote: true })
expect(sendAnalyticsEvent).toHaveBeenCalledWith(SwapEventName.SWAP_QUOTE_FETCH, {
chainId: mockChainId,
isQuickRoute: false,
})
})
})
......@@ -10,6 +10,7 @@ import { SwapRouting, SwapTradeBaseProperties } from 'uniswap/src/features/telem
import { ValueType, getCurrencyAmount } from 'uniswap/src/features/tokens/getCurrencyAmount'
import { DerivedSwapInfo } from 'uniswap/src/features/transactions/swap/types/derivedSwapInfo'
import { Trade } from 'uniswap/src/features/transactions/swap/types/trade'
import { SwapEventType, timestampTracker } from 'uniswap/src/features/transactions/swap/utils/SwapEventTimestampTracker'
import { getSwapFeeUsd } from 'uniswap/src/features/transactions/swap/utils/getSwapFeeUsd'
import { isClassic } from 'uniswap/src/features/transactions/swap/utils/routing'
import { getClassicQuoteFromResponse } from 'uniswap/src/features/transactions/swap/utils/tradingApi'
......@@ -179,6 +180,31 @@ export function getBaseTradeAnalyticsPropertiesFromSwapInfo({
}
}
export function logSwapQuoteFetch({
chainId,
isUSDQuote = false,
isQuickRoute = false,
}: {
chainId: number
isUSDQuote?: boolean
isQuickRoute?: boolean
}): void {
let performanceMetrics = {}
if (!isUSDQuote) {
const hasSetSwapQuote = timestampTracker.hasTimestamp(SwapEventType.FirstQuoteFetchStarted)
const elapsedTime = timestampTracker.setElapsedTime(SwapEventType.FirstQuoteFetchStarted)
// We only log the time_to_first_quote_request metric for the first quote request of a session.
const time_to_first_quote_request = hasSetSwapQuote ? undefined : elapsedTime
const time_to_first_quote_request_since_first_input = hasSetSwapQuote
? undefined
: timestampTracker.getElapsedTime(SwapEventType.FirstQuoteFetchStarted, SwapEventType.FirstSwapAction)
performanceMetrics = { time_to_first_quote_request, time_to_first_quote_request_since_first_input }
}
sendAnalyticsEvent(SwapEventName.SWAP_QUOTE_FETCH, { chainId, isQuickRoute, ...performanceMetrics })
}
// eslint-disable-next-line consistent-return
export function tradeRoutingToFillType({
routing,
......
......@@ -103,7 +103,7 @@ function useDebouncedTrade(): Trade | IndicativeTrade | undefined {
function GasRow({ gasInfo, hidden }: { gasInfo: DebouncedGasInfo; hidden?: boolean }): JSX.Element | null {
if (gasInfo.fiatPriceFormatted) {
const color = gasInfo.isHighRelativeToValue ? '$statusCritical' : '$neutral2'
const color = gasInfo.isHighRelativeToValue && !isInterface ? '$statusCritical' : '$neutral2' // Avoid high gas UI on interface
const uniswapXSavings = gasInfo.uniswapXGasFeeInfo?.preSavingsGasFeeFormatted
const body = uniswapXSavings ? (
<UniswapXFee gasFee={gasInfo.fiatPriceFormatted} preSavingsGasFee={uniswapXSavings} smaller={isWeb} />
......
import { TradeType } from '@uniswap/sdk-core'
import { useMemo, useRef } from 'react'
import { FetchError } from 'uniswap/src/data/apiClients/FetchError'
import { WithV4Flag } from 'uniswap/src/data/apiClients/tradingApi/TradingApiClient'
import { useTradingApiQuoteQuery } from 'uniswap/src/data/apiClients/tradingApi/useTradingApiQuoteQuery'
import { QuoteRequest, TradeType as TradingApiTradeType } from 'uniswap/src/data/tradingApi/__generated__/index'
import { TradeType as TradingApiTradeType } from 'uniswap/src/data/tradingApi/__generated__/index'
import { useActiveGasStrategy, useShadowGasStrategies } from 'uniswap/src/features/gas/hooks'
import { areEqualGasStrategies } from 'uniswap/src/features/gas/types'
import { FeatureFlags } from 'uniswap/src/features/gating/flags'
......@@ -12,6 +11,7 @@ import { useIndicativeTrade } from 'uniswap/src/features/transactions/swap/hooks
import { usePollingIntervalByChain } from 'uniswap/src/features/transactions/swap/hooks/usePollingIntervalByChain'
import { TradeWithStatus, UseTradeArgs } from 'uniswap/src/features/transactions/swap/types/trade'
import {
SWAP_GAS_URGENCY_OVERRIDE,
getTokenAddressForApi,
toTradingApiSupportedChainId,
transformTradingApiResponseToTrade,
......@@ -88,7 +88,7 @@ export function useTrade({
const v4Enabled = useFeatureFlag(FeatureFlags.V4Swap)
const quoteRequestArgs = useMemo((): WithV4Flag<QuoteRequest> | undefined => {
const quoteRequestArgs = useMemo((): Parameters<typeof useTradingApiQuoteQuery>[0]['params'] | undefined => {
if (skipQuery) {
return undefined
}
......@@ -101,9 +101,11 @@ export function useTrade({
tokenIn: tokenInAddress,
tokenOut: tokenOutAddress,
slippageTolerance: customSlippageTolerance,
...routingParams,
urgency: SWAP_GAS_URGENCY_OVERRIDE,
gasStrategies: [activeGasStrategy, ...(shadowGasStrategies ?? [])],
v4Enabled,
isUSDQuote,
...routingParams,
}
}, [
activeAccountAddress,
......@@ -119,6 +121,7 @@ export function useTrade({
tokenOutAddress,
tokenOutChainId,
v4Enabled,
isUSDQuote,
])
/***** Fetch quote from trading API ******/
......
......@@ -25,6 +25,7 @@ import { SwapGasFeeEstimation } from 'uniswap/src/features/transactions/swap/typ
import { ApprovalAction, TokenApprovalInfo } from 'uniswap/src/features/transactions/swap/types/trade'
import { isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing'
import {
SWAP_GAS_URGENCY_OVERRIDE,
getBridgeQuoteFromResponse,
getClassicQuoteFromResponse,
isClassicQuote,
......@@ -119,6 +120,7 @@ export function useTransactionRequestInfo({
deadline,
refreshGasPrice: true,
gasStrategies: [activeGasStrategy, ...(shadowGasStrategies ?? [])],
urgency: SWAP_GAS_URGENCY_OVERRIDE,
v4Enabled,
}
......
......@@ -11,7 +11,7 @@ import { LearnMoreLink } from 'uniswap/src/components/text/LearnMoreLink'
import { uniswapUrls } from 'uniswap/src/constants/urls'
import { FormattedUniswapXGasFeeInfo } from 'uniswap/src/features/gas/types'
import { ModalName } from 'uniswap/src/features/telemetry/constants'
import { isMobileApp } from 'utilities/src/platform'
import { isInterface, isMobileApp } from 'utilities/src/platform'
export function NetworkFeeWarning({
gasFeeHighRelativeToValue,
......@@ -28,7 +28,7 @@ export function NetworkFeeWarning({
const colors = useSporeColors()
const { t } = useTranslation()
const showHighGasFeeUI = gasFeeHighRelativeToValue && !uniswapXGasFeeInfo
const showHighGasFeeUI = gasFeeHighRelativeToValue && !uniswapXGasFeeInfo && !isInterface // Avoid high gas UI on interface
return (
<WarningInfo
......
......@@ -21,6 +21,7 @@ import {
V2PoolInRoute as TradingApiV2PoolInRoute,
V3PoolInRoute as TradingApiV3PoolInRoute,
V4PoolInRoute as TradingApiV4PoolInRoute,
Urgency,
V4PoolInRoute,
} from 'uniswap/src/data/tradingApi/__generated__/index'
import { NativeCurrency } from 'uniswap/src/features/tokens/NativeCurrency'
......@@ -42,8 +43,10 @@ import { CurrencyField } from 'uniswap/src/types/currency'
import { areAddressesEqual } from 'uniswap/src/utils/addresses'
import { currencyId } from 'uniswap/src/utils/currencyId'
import { logger } from 'utilities/src/logger/logger'
import { isInterface } from 'utilities/src/platform'
export const NATIVE_ADDRESS_FOR_TRADING_API = '0x0000000000000000000000000000000000000000'
export const SWAP_GAS_URGENCY_OVERRIDE = isInterface ? Urgency.NORMAL : undefined // on Interface, use a normal urgency, else use TradingAPI default
interface TradingApiResponseToTradeArgs {
currencyIn: Currency
......
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