Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/web/src/components/Icons/Sign.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const Sign = () => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle opacity="0.24" cx="12" cy="12" r="11.5" stroke="#FC72FF" />
<rect width="24" height="24" rx="12" fill="#FC72FF" />
<circle opacity="0.24" cx="12" cy="12" r="11.5" stroke="#00FFFF" />
<rect width="24" height="24" rx="12" fill="#00FFFF" />
<path
d="M13.6297 16.1959C13.4577 16.2779 13.2567 16.3389 13.0292 16.3799L9.74417 16.9549C8.64917 17.1499 8.00411 16.6999 7.81411 15.6049L7.04422 11.2299C6.84922 10.1349 7.29919 9.48994 8.39419 9.29494L9.29312 9.13692C9.39562 9.11892 9.4852 9.20843 9.4667 9.31093L8.87869 12.6399C8.61369 14.1549 9.32865 15.1749 10.8387 15.4399C10.8387 15.4399 13.4482 15.8984 13.5827 15.9244C13.7487 15.9544 13.7752 16.1314 13.6297 16.1959ZM16.9562 9.55293L16.1841 13.9299C15.9981 14.9839 15.3902 15.4344 14.3677 15.2944C14.3287 15.2889 14.2937 15.2889 14.2532 15.2819L10.9706 14.7029C9.87611 14.5099 9.42568 13.8664 9.61868 12.7719L10.2902 8.96391L10.3907 8.39491C10.5837 7.30041 11.2272 6.84992 12.3217 7.04292L15.6046 7.62193C16.6986 7.81493 17.1492 8.45893 16.9562 9.55293ZM13.7766 12.9479C13.8126 12.7439 13.6767 12.5494 13.4727 12.5134L11.4207 12.1514C11.2177 12.1149 11.0222 12.2519 10.9867 12.4554C10.9507 12.6594 11.0867 12.8539 11.2907 12.8899L13.3427 13.2519C13.3647 13.2559 13.3866 13.2574 13.4081 13.2574C13.5866 13.2579 13.7446 13.1299 13.7766 12.9479ZM15.2981 11.5174C15.3341 11.3134 15.1982 11.1189 14.9942 11.0829L11.7117 10.5039C11.5097 10.4684 11.3131 10.6044 11.2776 10.8079C11.2416 11.0119 11.3777 11.2064 11.5817 11.2424L14.8642 11.8214C14.8862 11.8254 14.9082 11.8269 14.9297 11.8269C15.1082 11.8269 15.2661 11.6989 15.2981 11.5174ZM15.6482 9.88643C15.6842 9.68243 15.5481 9.48792 15.3441 9.45192L12.0617 8.87291C11.8597 8.83691 11.6632 8.97343 11.6277 9.17693C11.5917 9.38093 11.7277 9.57544 11.9317 9.61144L15.2141 10.1904C15.2361 10.1944 15.2582 10.1959 15.2797 10.1959C15.4582 10.1964 15.6162 10.0684 15.6482 9.88643Z"
fill="white"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('PoolDetailsStats', () => {
poolData: validPoolDataResponse.data,
isReversed: false,
chainId: 1,
tokenAColor: '#FF37C7',
tokenAColor: '#00DDDD',
tokenBColor: '#222222',
}

Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/components/SwapBottomCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ const CHAIN_THEME_LIGHT: Record<UniverseChainId, ChainTheme> = {
[UniverseChainId.Sepolia]: { bgColor: '#6B8AFF33', textColor: '#6B8AFF' },
[UniverseChainId.Solana]: { bgColor: '#9945FF33', textColor: '#000000' },
[UniverseChainId.Soneium]: { bgColor: '#FFFFFF', textColor: '#000000' },
[UniverseChainId.Unichain]: { bgColor: '#F50DB433', textColor: '#F50DB4' },
[UniverseChainId.UnichainSepolia]: { bgColor: '#F50DB433', textColor: '#F50DB4' },
[UniverseChainId.Unichain]: { bgColor: '#00CCCC33', textColor: '#00CCCC' },
[UniverseChainId.UnichainSepolia]: { bgColor: '#00CCCC33', textColor: '#00CCCC' },
[UniverseChainId.WorldChain]: { bgColor: 'rgba(0, 0, 0, 0.12)', textColor: '#000000' },
[UniverseChainId.Zksync]: { bgColor: 'rgba(54, 103, 246, 0.12)', textColor: '#3667F6' },
[UniverseChainId.Zora]: { bgColor: 'rgba(0, 0, 0, 0.12)', textColor: '#000000' },
Expand Down
167 changes: 167 additions & 0 deletions apps/web/src/hooks/useLightLinkTokenQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import { useEffect, useMemo, useState } from 'react'
import { Token } from '@uniswap/sdk-core'
import { GraphQLApi } from '@universe/api'
import { UniverseChainId } from 'uniswap/src/features/chains/types'

const LIGHTLINK_SUBGRAPH_URL =
'https://graph.phoenix.lightlink.io/query/subgraphs/name/uniswap-v3-lightlink'

// Known LightLink token logos
const LIGHTLINK_TOKEN_LOGOS: Record<string, string> = {
'0x7ebef2a4b1b09381ec5b9df8c5c6f2dbeca59c73':
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png',
'0xbcf8c1b03bbdda88d579330bdf236b58f8bb2cfd':
'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png',
}

export function getLightLinkTokenLogoUrl(address: string): string | undefined {
return LIGHTLINK_TOKEN_LOGOS[address.toLowerCase()]
}

interface SubgraphToken {
id: string
symbol: string
name: string
decimals: string
volumeUSD: string
totalValueLockedUSD: string
derivedETH: string
tokenDayData: Array<{
date: number
priceUSD: string
volumeUSD: string
}>
}

interface LightLinkTokenQueryResult {
data: { token: GraphQLApi.TokenWebQuery['token'] } | undefined
loading: boolean
error: Error | undefined
currency: Token | undefined
}

export function useLightLinkTokenQuery(address: string | undefined): LightLinkTokenQueryResult {
const [subgraphToken, setSubgraphToken] = useState<SubgraphToken | null>(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState<Error | undefined>()

useEffect(() => {
if (!address) {
setLoading(false)
return
}

let cancelled = false
setLoading(true)

const query = `{
token(id: "${address.toLowerCase()}") {
id
symbol
name
decimals
volumeUSD
totalValueLockedUSD
derivedETH
tokenDayData(first: 365, orderBy: date, orderDirection: desc) {
date
priceUSD
volumeUSD
}
}
}`

fetch(LIGHTLINK_SUBGRAPH_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query }),
})
.then((res) => res.json())
.then((json) => {
if (!cancelled) {
setSubgraphToken(json.data?.token ?? null)
setLoading(false)
}
})
.catch((err) => {
if (!cancelled) {
setError(err)
setLoading(false)
}
})

return () => {
cancelled = true
}
}, [address])

const currency = useMemo(() => {
if (!subgraphToken || !address) return undefined
return new Token(
UniverseChainId.LightLink,
address,
parseInt(subgraphToken.decimals, 10),
subgraphToken.symbol,
subgraphToken.name,
)
}, [subgraphToken, address])

// Shape the data to match TokenWebQuery['token'] as closely as possible
const data = useMemo(() => {
if (!subgraphToken) return undefined

const logoUrl = getLightLinkTokenLogoUrl(subgraphToken.id)
const volume24H = parseFloat(subgraphToken.volumeUSD)
const tvl = parseFloat(subgraphToken.totalValueLockedUSD)

const token: GraphQLApi.TokenWebQuery['token'] = {
__typename: 'Token' as const,
id: `lightlink-${subgraphToken.id}`,
name: subgraphToken.name,
symbol: subgraphToken.symbol,
decimals: parseInt(subgraphToken.decimals, 10),
address: subgraphToken.id,
chain: GraphQLApi.Chain.UnknownChain,
standard: GraphQLApi.TokenStandard.Erc20,
feeData: null,
market: {
__typename: 'TokenMarket' as const,
id: `lightlink-market-${subgraphToken.id}`,
volume24H: { __typename: 'Amount' as const, id: `vol-${subgraphToken.id}`, value: volume24H, currency: GraphQLApi.Currency.Usd },
totalValueLocked: { __typename: 'Amount' as const, id: `tvl-${subgraphToken.id}`, value: tvl, currency: GraphQLApi.Currency.Usd },
price: subgraphToken.tokenDayData.length > 0
? {
__typename: 'Amount' as const,
id: `price-${subgraphToken.id}`,
value: parseFloat(subgraphToken.tokenDayData[0].priceUSD),
currency: GraphQLApi.Currency.Usd,
}
: null,
pricePercentChange24h: null,
priceHigh52W: null,
priceLow52W: null,
},
project: {
__typename: 'TokenProject' as const,
id: `lightlink-project-${subgraphToken.id}`,
name: subgraphToken.name,
description: null,
homepageUrl: null,
twitterName: null,
logoUrl: logoUrl ?? null,
tokens: [
{
__typename: 'Token' as const,
id: `lightlink-${subgraphToken.id}`,
chain: GraphQLApi.Chain.UnknownChain,
address: subgraphToken.id,
},
],
},
}

return { token }
}, [subgraphToken])

return { data, loading, error, currency }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Unichain } from 'ui/src/components/icons/Unichain'
import { opacify } from 'ui/src/theme'
import { uniswapUrls } from 'uniswap/src/constants/urls'

const primary = '#F50DB4'
const primary = '#00CCCC'

export function UnichainCard() {
const { t } = useTranslation()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EmblemProps } from 'pages/Portfolio/components/AnimatedStyledBanner/Emblems/types'
import { useSporeColors } from 'ui/src'

export function EmblemA({ fill = '#FF37C7', opacity = 1, ...props }: EmblemProps): JSX.Element {
export function EmblemA({ fill = '#00DDDD', opacity = 1, ...props }: EmblemProps): JSX.Element {
const colors = useSporeColors()

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EmblemProps } from 'pages/Portfolio/components/AnimatedStyledBanner/Emblems/types'
import { useSporeColors } from 'ui/src'

export function EmblemB({ fill = '#FF37C7', opacity = 1, ...props }: EmblemProps): JSX.Element {
export function EmblemB({ fill = '#00DDDD', opacity = 1, ...props }: EmblemProps): JSX.Element {
const colors = useSporeColors()

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { EmblemProps } from 'pages/Portfolio/components/AnimatedStyledBanner/Emb
import { useId } from 'react'
import { useSporeColors } from 'ui/src'

export function EmblemC({ fill = '#FF37C7', opacity = 1, ...props }: EmblemProps): JSX.Element {
export function EmblemC({ fill = '#00DDDD', opacity = 1, ...props }: EmblemProps): JSX.Element {
const colors = useSporeColors()
const clipPathId = useId()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EmblemProps } from 'pages/Portfolio/components/AnimatedStyledBanner/Emblems/types'
import { useSporeColors } from 'ui/src'

export function EmblemD({ fill = '#FF37C7', opacity = 1, ...props }: EmblemProps): JSX.Element {
export function EmblemD({ fill = '#00DDDD', opacity = 1, ...props }: EmblemProps): JSX.Element {
const colors = useSporeColors()

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EmblemProps } from 'pages/Portfolio/components/AnimatedStyledBanner/Emblems/types'
import { useSporeColors } from 'ui/src'

export function EmblemE({ fill = '#FF37C7', opacity = 1, ...props }: EmblemProps): JSX.Element {
export function EmblemE({ fill = '#00DDDD', opacity = 1, ...props }: EmblemProps): JSX.Element {
const colors = useSporeColors()

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EmblemProps } from 'pages/Portfolio/components/AnimatedStyledBanner/Emblems/types'
import { useSporeColors } from 'ui/src'

export function EmblemF({ fill = '#FF37C7', opacity = 1, ...props }: EmblemProps): JSX.Element {
export function EmblemF({ fill = '#00DDDD', opacity = 1, ...props }: EmblemProps): JSX.Element {
const colors = useSporeColors()

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EmblemProps } from 'pages/Portfolio/components/AnimatedStyledBanner/Emblems/types'
import { useSporeColors } from 'ui/src'

export function EmblemG({ fill = '#FF37C7', opacity = 1, ...props }: EmblemProps): JSX.Element {
export function EmblemG({ fill = '#00DDDD', opacity = 1, ...props }: EmblemProps): JSX.Element {
const colors = useSporeColors()

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EmblemProps } from 'pages/Portfolio/components/AnimatedStyledBanner/Emblems/types'
import { useSporeColors } from 'ui/src'

export function EmblemH({ fill = '#FF37C7', opacity = 1, ...props }: EmblemProps): JSX.Element {
export function EmblemH({ fill = '#00DDDD', opacity = 1, ...props }: EmblemProps): JSX.Element {
const colors = useSporeColors()

return (
Expand Down
31 changes: 27 additions & 4 deletions apps/web/src/pages/TokenDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { TokenDetailsPageSkeleton } from 'components/Tokens/TokenDetails/Skeleto
import { NATIVE_CHAIN_ID } from 'constants/tokens'
import { useActiveAddresses } from 'features/accounts/store/hooks'
import { useSrcColor } from 'hooks/useColor'
import { useLightLinkTokenQuery } from 'hooks/useLightLinkTokenQuery'
import { ExploreTab } from 'pages/Explore/constants'
import { useDynamicMetatags } from 'pages/metatags'
import { LoadedTDPContext, MultiChainMap, PendingTDPContext, TDPProvider } from 'pages/TokenDetails/TDPContext'
Expand Down Expand Up @@ -79,24 +80,46 @@ function useCreateTDPContext(): PendingTDPContext | LoadedTDPContext {
}

const currencyChainInfo = getChainInfo(useChainIdFromUrlParam() ?? UniverseChainId.Mainnet)
const isLightLink = currencyChainInfo.id === UniverseChainId.LightLink

const isNative = tokenAddress === NATIVE_CHAIN_ID

const tokenDBAddress = isNative ? getNativeTokenDBAddress(currencyChainInfo.backendChain.chain) : tokenAddress

// Standard GraphQL query (skipped for LightLink)
const tokenQuery = GraphQLApi.useTokenWebQuery({
variables: { address: tokenDBAddress, chain: currencyChainInfo.backendChain.chain },
errorPolicy: 'all',
skip: isLightLink,
})

// LightLink subgraph fallback
const lightLinkResult = useLightLinkTokenQuery(isLightLink ? tokenAddress : undefined)

// Merge: for LightLink, overlay subgraph data onto tokenQuery shape
const effectiveTokenQuery = useMemo(() => {
if (!isLightLink) return tokenQuery
// Create a compatible object that looks like an Apollo QueryResult
return {
...tokenQuery,
data: lightLinkResult.data as GraphQLApi.TokenWebQuery | undefined,
loading: lightLinkResult.loading,
error: lightLinkResult.error as any,
}
}, [isLightLink, tokenQuery, lightLinkResult.data, lightLinkResult.loading, lightLinkResult.error])

const currency = useMemo(() => {
if (isNative) {
return nativeOnChain(currencyChainInfo.id)
}
if (isLightLink) {
return lightLinkResult.currency
}
if (tokenQuery.data?.token) {
return gqlToCurrency(tokenQuery.data.token)
}
return undefined
}, [tokenQuery.data?.token, isNative, currencyChainInfo.id])
}, [tokenQuery.data?.token, isNative, currencyChainInfo.id, isLightLink, lightLinkResult.currency])

const chartState = useCreateTDPChartState(tokenDBAddress, currencyChainInfo.backendChain.chain)

Expand All @@ -106,7 +129,7 @@ function useCreateTDPContext(): PendingTDPContext | LoadedTDPContext {
const colors = useSporeColors()
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const { preloadedLogoSrc } = (useLocation().state as { preloadedLogoSrc?: string }) ?? {}
const extractedColorSrc = tokenQuery.data?.token?.project?.logoUrl ?? preloadedLogoSrc
const extractedColorSrc = effectiveTokenQuery.data?.token?.project?.logoUrl ?? preloadedLogoSrc
const tokenColor =
useSrcColor({
src: extractedColorSrc,
Expand All @@ -121,7 +144,7 @@ function useCreateTDPContext(): PendingTDPContext | LoadedTDPContext {
currencyChainId: currencyChainInfo.id,
// `currency.address` is checksummed, whereas the `tokenAddress` url param may not be
address: (currency?.isNative ? NATIVE_CHAIN_ID : currency?.address) ?? tokenAddress,
tokenQuery,
tokenQuery: effectiveTokenQuery as any,
chartState,
multiChainMap,
tokenColor,
Expand All @@ -131,7 +154,7 @@ function useCreateTDPContext(): PendingTDPContext | LoadedTDPContext {
currencyChainInfo.backendChain.chain,
currencyChainInfo.id,
tokenAddress,
tokenQuery,
effectiveTokenQuery,
chartState,
multiChainMap,
tokenColor,
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/pages/Wrapped/DisconnectedState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const GlowEffect = styled(Flex, {
bottom: 0,
width: '100%',
height: 30,
background: '#fc74fe',
background: '#00FFFF',
filter: 'blur(90px)',
opacity: 0.4,
})
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/pages/Wrapped/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default function Wrapped() {
maxHeight={`calc(100% - ${INTERFACE_NAV_HEIGHT}px)`}
maxWidth={1200}
aspectRatio={hasWallet ? (isLandscape ? '3/2' : '9/16') : undefined}
backgroundColor="#361A37"
backgroundColor="#0A2E2E"
borderRadius={48}
alignItems="center"
justifyContent="center"
Expand Down
Loading