Skip to content

Commit 0bc1b53

Browse files
chef-ryanchef-eric
andauthored
feat: auto token verification (#11731)
<!-- Before opening a pull request, please read the [contributing guidelines](https://github.com/pancakeswap/pancake-frontend/blob/develop/CONTRIBUTING.md) first --> <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on removing the dependency on `lodash` in the `@pancakeswap` codebase, replacing it with custom utility functions from `@pancakeswap/utils`. It also introduces new features and updates related to fee management and farm data handling. ### Detailed summary - Removed `lodash` dependencies. - Added `findTokenByAddress` and `findTokenBySymbol` functions. - Introduced `feeAmount` in farm-related types. - Updated various files to use new utility functions. - Enhanced API handling for farms and pools. - Improved memoization functions. - Adjusted state management in various hooks and components. > The following files were skipped due to too many changes: `apps/web/src/config/constants/lists.ts`, `apps/web/src/views/universalFarms/components/useColumnConfig.tsx`, `apps/web/src/components/FeeTierBreakdown.tsx`, `apps/web/src/views/universalFarms/components/PoolsFilterPanel.tsx`, `packages/smart-router/evm/infinity-router/queries/remotePoolTransform.ts`, `apps/web/src/state/farmsV4/search/filters.ts`, `apps/web/src/views/universalFarms/atom/farmsSearchAtom.ts`, `apps/web/src/state/farmsV4/search/farm.util.ts`, `apps/web/src/state/farmsV4/search/edgeFarmQueries.ts`, `apps/web/src/state/farmsV4/search/batchFarmDataFiller.ts`, `apps/web/src/state/farmsV4/state/farmPools/hooks.ts`, `apps/web/src/views/universalFarms/PoolsPage.tsx` > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex --> --------- Co-authored-by: ChefEric <[email protected]>
1 parent d21ba5b commit 0bc1b53

File tree

73 files changed

+2722
-726
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+2722
-726
lines changed

.changeset/wet-chefs-trade.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@pancakeswap/farms': patch
3+
'@pancakeswap/utils': patch
4+
---
5+
6+
Remove lodash deps for @pancakeswap/farms to support edge api env.

apps/web/src/components/FeeTierBreakdown.tsx

Lines changed: 63 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,56 @@ import { useTranslation } from '@pancakeswap/localization'
33
import { Percent } from '@pancakeswap/sdk'
44
import { Flex, InfoIcon, Text, useModal } from '@pancakeswap/uikit'
55
import { FeeTierTooltip, Liquidity } from '@pancakeswap/widgets-internal'
6-
import { useInfinityFeeTier } from 'hooks/infinity/useInfinityFeeTier'
6+
import { InfinityFeeTier, InfinityFeeTierPoolParams, useInfinityFeeTier } from 'hooks/infinity/useInfinityFeeTier'
77
import { usePoolById } from 'hooks/infinity/usePool'
88
import { useCallback, useMemo } from 'react'
9+
import { getPoolInfoForInfiFee } from 'state/farmsV4/search/farm.util'
10+
import { PoolInfo } from 'state/farmsV4/state/type'
911
import { Address } from 'viem'
1012

1113
interface FeeTierBreakdownProps {
1214
poolId?: Address
1315
chainId?: number
1416
hookData?: HookData
17+
poolInfo?: PoolInfo
1518
infoIconVisible?: boolean
1619
}
1720
export const InfinityFeeTierBreakdown = ({
1821
poolId,
1922
chainId,
2023
hookData,
2124
infoIconVisible = true,
25+
poolInfo,
2226
}: FeeTierBreakdownProps) => {
23-
const { t } = useTranslation()
24-
const [, pool] = usePoolById(poolId, chainId)
27+
const enabled = !poolInfo?.farm
28+
29+
const [, pool] = usePoolById(poolId, chainId, enabled)
30+
const farm = poolInfo?.farm
31+
32+
const info = farm ? getPoolInfoForInfiFee(farm) : pool
33+
if (!info) {
34+
return null
35+
}
36+
return (
37+
<InfinityFeeTierBreakdownDisplay
38+
pool={info!}
39+
poolId={poolId}
40+
chainId={chainId}
41+
hookData={hookData}
42+
infoIconVisible={infoIconVisible}
43+
/>
44+
)
45+
}
2546

26-
const { protocol, type, percent, lpFee, protocolFee } = useInfinityFeeTier(pool)
47+
export const InfinityFeeTierBreakdownDisplay = ({
48+
pool,
49+
50+
hookData,
51+
infoIconVisible = true,
52+
}: FeeTierBreakdownProps & {
53+
pool: InfinityFeeTierPoolParams
54+
}) => {
55+
const infinityFeeTier = useInfinityFeeTier(pool)
2756
const [onPresentHookDetailModal] = useModal(<Liquidity.HookModal hookData={hookData} />)
2857
const handleInfoIconClick = useCallback(
2958
(e) => {
@@ -34,36 +63,22 @@ export const InfinityFeeTierBreakdown = ({
3463
[onPresentHookDetailModal],
3564
)
3665

37-
const p = useMemo(() => {
38-
if (percent.equalTo(0) && hookData?.defaultFee) {
39-
return new Percent(hookData.defaultFee, 1e6)
40-
}
41-
return percent
42-
}, [hookData?.defaultFee, percent])
43-
4466
const tooltips = useMemo(() => {
45-
return (
46-
<>
47-
<Text bold> {t('%t% LP', { t: protocol.toUpperCase() })}</Text>
48-
<Text>
49-
{' '}
50-
-{' '}
51-
{t('%p%% LP Fee', {
52-
p: (lpFee.equalTo(0) ? new Percent(hookData?.defaultFee ?? 0, 1e6) : lpFee).toSignificant(2),
53-
})}
54-
</Text>
55-
<Text> - {t('%p%% Protocol Fee', { p: protocolFee.toSignificant(2) })}</Text>
56-
</>
57-
)
58-
}, [lpFee, protocolFee, t, protocol])
67+
return <FeeTierTooltips infinityFeeTier={infinityFeeTier} hookData={hookData} />
68+
}, [infinityFeeTier, hookData])
5969

6070
if (!pool) {
6171
return null
6272
}
6373

6474
return (
6575
<Flex alignItems="center">
66-
<FeeTierTooltip tooltips={tooltips} dynamic={pool?.dynamic} type={type} percent={p} />
76+
<FeeTierTooltip
77+
tooltips={tooltips}
78+
dynamic={pool?.dynamic}
79+
type={infinityFeeTier.type}
80+
percent={infinityFeeTier.percent}
81+
/>
6782
{hookData?.category?.includes(HOOK_CATEGORY.DynamicFees) && infoIconVisible ? (
6883
<InfoIcon
6984
color="textSubtle"
@@ -77,3 +92,25 @@ export const InfinityFeeTierBreakdown = ({
7792
</Flex>
7893
)
7994
}
95+
96+
export const FeeTierTooltips: React.FC<{
97+
infinityFeeTier: InfinityFeeTier
98+
hookData?: HookData
99+
}> = ({ infinityFeeTier, hookData }) => {
100+
const { t } = useTranslation()
101+
const { protocol, lpFee, protocolFee } = infinityFeeTier
102+
103+
return (
104+
<>
105+
<Text bold> {t('%t% LP', { t: protocol.toUpperCase() })}</Text>
106+
<Text>
107+
{' '}
108+
-{' '}
109+
{t('%p%% LP Fee', {
110+
p: (lpFee.equalTo(0) ? new Percent(hookData?.defaultFee ?? 0, 1e6) : lpFee).toSignificant(2),
111+
})}
112+
</Text>
113+
<Text> - {t('%p%% Protocol Fee', { p: protocolFee.toSignificant(2) })}</Text>
114+
</>
115+
)
116+
}

apps/web/src/components/SearchModal/ManageLists.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ function listUrlRowHTMLId(listUrl: string) {
6565
return `list-row-${listUrl.replace(/\./g, '-')}`
6666
}
6767

68+
function resolveLogo(list: TokenList): string {
69+
const uri = list.logoURI
70+
if (uri?.match(/static\.coingecko\.com/)) {
71+
return 'https://tokens.pancakeswap.finance/images/projects/coingecko.png'
72+
}
73+
return uri || ''
74+
}
75+
6876
const ListRow = memo(function ListRow({ listUrl, chainId: chainIdProp }: { listUrl: string; chainId?: number }) {
6977
const { chainId: activeChainId } = useActiveChainId()
7078
const chainId = chainIdProp || activeChainId
@@ -124,6 +132,7 @@ const ListRow = memo(function ListRow({ listUrl, chainId: chainIdProp }: { listU
124132
)
125133

126134
if (!list) return null
135+
const logoURI = resolveLogo(list)
127136

128137
return (
129138
<RowWrapper
@@ -133,8 +142,8 @@ const ListRow = memo(function ListRow({ listUrl, chainId: chainIdProp }: { listU
133142
id={listUrlRowHTMLId(listUrl)}
134143
>
135144
{tooltipVisible && tooltip}
136-
{list.logoURI ? (
137-
<ListLogo size="40px" style={{ marginRight: '1rem' }} logoURI={list.logoURI} alt={`${list.name} list logo`} />
145+
{logoURI ? (
146+
<ListLogo size="40px" style={{ marginRight: '1rem' }} logoURI={logoURI} alt={`${list.name} list logo`} />
138147
) : (
139148
<div style={{ width: '24px', height: '24px', marginRight: '1rem' }} />
140149
)}
Lines changed: 12 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,26 @@
1-
import { ChainId } from '@pancakeswap/chains'
2-
import { Currency, Token, WBNB } from '@pancakeswap/sdk'
1+
import { Currency, Token } from '@pancakeswap/sdk'
32
import {
43
ImageProps,
54
TokenImage as UIKitTokenImage,
65
TokenPairImage as UIKitTokenPairImage,
76
TokenPairImageProps as UIKitTokenPairImageProps,
87
TokenPairLogo as UIKitTokenPairLogo,
98
} from '@pancakeswap/uikit'
10-
import uriToHttp from '@pancakeswap/utils/uriToHttp'
119
import { ASSET_CDN } from 'config/constants/endpoints'
1210
import { useMemo } from 'react'
13-
import { isAddressEqual, safeGetAddress } from 'utils'
14-
import { zeroAddress } from 'viem'
11+
import {
12+
getCurrencyLogoSrcs,
13+
getImageUrlFromToken,
14+
getImageUrlsFromToken,
15+
tokenImageChainNameMapping,
16+
} from 'utils/tokenImages'
1517

1618
interface TokenPairImageProps extends Omit<UIKitTokenPairImageProps, 'primarySrc' | 'secondarySrc'> {
1719
primaryToken: Currency
1820
secondaryToken: Currency
1921
withChainLogo?: boolean
2022
}
2123

22-
export const tokenImageChainNameMapping = {
23-
[ChainId.BSC]: '',
24-
[ChainId.ETHEREUM]: 'eth/',
25-
[ChainId.POLYGON_ZKEVM]: 'polygon-zkevm/',
26-
[ChainId.ZKSYNC]: 'zksync/',
27-
[ChainId.ARBITRUM_ONE]: 'arbitrum/',
28-
[ChainId.LINEA]: 'linea/',
29-
[ChainId.BASE]: 'base/',
30-
[ChainId.OPBNB]: 'opbnb/',
31-
}
32-
33-
export const getImageUrlFromToken = (token: Currency) => {
34-
let address = token?.isNative ? token.wrapped.address : token?.address
35-
if (token && token.chainId === ChainId.BSC && !token.isNative && isAddressEqual(token.address, zeroAddress)) {
36-
address = WBNB[ChainId.BSC].wrapped.address
37-
}
38-
39-
return token
40-
? token.isNative && token.chainId !== ChainId.BSC
41-
? `${ASSET_CDN}/web/native/${token.chainId}.png`
42-
: `https://tokens.pancakeswap.finance/images/${tokenImageChainNameMapping[token.chainId]}${safeGetAddress(
43-
address,
44-
)}.png`
45-
: ''
46-
}
47-
48-
export const getImageUrlsFromToken = (token: Currency & { logoURI?: string | undefined }) => {
49-
const uriLocations = token?.logoURI ? uriToHttp(token?.logoURI) : []
50-
const imageUri = getImageUrlFromToken(token)
51-
return [...uriLocations, imageUri]
52-
}
53-
5424
export const getChainLogoUrlFromChainId = (chainId: number) => `${ASSET_CDN}/web/chains/${chainId}.png`
5525

5626
export const TokenPairImage: React.FC<React.PropsWithChildren<TokenPairImageProps>> = ({
@@ -80,13 +50,10 @@ export const TokenPairLogo: React.FC<React.PropsWithChildren<TokenPairImageProps
8050
() => (withChainLogo ? [getChainLogoUrlFromChainId(primaryToken.chainId)] : []),
8151
[withChainLogo, primaryToken.chainId],
8252
)
53+
const primarySrcs = getCurrencyLogoSrcs(primaryToken as Currency & { logoURI?: string | undefined })
54+
const secondarySrcs = getCurrencyLogoSrcs(secondaryToken as Currency & { logoURI?: string | undefined })
8355
return (
84-
<UIKitTokenPairLogo
85-
primarySrcs={getImageUrlsFromToken(primaryToken)}
86-
secondarySrcs={getImageUrlsFromToken(secondaryToken)}
87-
chainLogoSrcs={chainLogo}
88-
{...props}
89-
/>
56+
<UIKitTokenPairLogo primarySrcs={primarySrcs} secondarySrcs={secondarySrcs} chainLogoSrcs={chainLogo} {...props} />
9057
)
9158
}
9259

@@ -97,3 +64,5 @@ interface TokenImageProps extends ImageProps {
9764
export const TokenImage: React.FC<React.PropsWithChildren<TokenImageProps>> = ({ token, ...props }) => {
9865
return <UIKitTokenImage src={getImageUrlFromToken(token)} {...props} />
9966
}
67+
68+
export { getCurrencyLogoSrcs, getImageUrlFromToken, getImageUrlsFromToken, tokenImageChainNameMapping }

apps/web/src/config/constants/lists.ts

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import { ChainId } from '@pancakeswap/chains'
22

33
export const PANCAKE_EXTENDED = 'https://tokens.pancakeswap.finance/pancakeswap-extended.json'
44

5-
const COINGECKO = 'https://tokens.pancakeswap.finance/coingecko.json'
5+
const COINGECKO_BSC = 'https://tokens.coingecko.com/binance-smart-chain/all.json'
6+
const COINGECKO_ARB = 'https://tokens.coingecko.com/arbitrum-one/all.json'
7+
const COINGECKO_BASE = 'https://tokens.coingecko.com/base/all.json'
8+
const COINGECKO_LINEA = 'https://tokens.coingecko.com/linea/all.json'
69
export const PANCAKE_ETH_DEFAULT = 'https://tokens.pancakeswap.finance/pancakeswap-eth-default.json'
710
export const PANCAKE_ZKSYNC_DEFAULT = 'https://tokens.pancakeswap.finance/pancakeswap-zksync-default.json'
811
export const PANCAKE_POLYGON_ZKEVM_DEFAULT = 'https://tokens.pancakeswap.finance/pancakeswap-polygon-zkevm-default.json'
@@ -11,33 +14,26 @@ export const PANCAKE_LINEA_DEFAULT = 'https://tokens.pancakeswap.finance/pancake
1114
export const PANCAKE_BASE_DEFAULT = 'https://tokens.pancakeswap.finance/pancakeswap-base-default.json'
1215
export const PANCAKE_OPBNB_DEFAULT = 'https://tokens.pancakeswap.finance/pancakeswap-opbnb-default.json'
1316

14-
export const PANCAKE_ETH_MM = 'https://tokens.pancakeswap.finance/pancakeswap-eth-mm.json'
15-
export const PANCAKE_BSC_MM = 'https://tokens.pancakeswap.finance/pancakeswap-bnb-mm.json'
16-
export const PANCAKE_ARB_MM = 'https://tokens.pancakeswap.finance/pancakeswap-arb-mm.json'
1717
export const PANCAKE_MONAD_TESTNET_DEFAULT = 'https://tokens.pancakeswap.finance/pancakeswap-monad-testnet-default.json'
1818

1919
const COINGECKO_ETH = 'https://tokens.coingecko.com/uniswap/all.json'
2020
// export const CMC = 'https://tokens.pancakeswap.finance/cmc.json' // not updated for a while
2121

22-
const ETH_URLS = [PANCAKE_ETH_DEFAULT, PANCAKE_ETH_MM, COINGECKO_ETH]
23-
const BSC_URLS = [PANCAKE_EXTENDED, COINGECKO, PANCAKE_BSC_MM]
22+
const ETH_URLS = [PANCAKE_ETH_DEFAULT, COINGECKO_ETH]
23+
const BSC_URLS = [PANCAKE_EXTENDED, COINGECKO_BSC]
2424
const POLYGON_ZKEVM_URLS = [
2525
PANCAKE_POLYGON_ZKEVM_DEFAULT,
2626
// 'https://tokens.coingecko.com/polygon-zkevm/all.json'
2727
]
28-
const ARBITRUM_URLS = [
29-
PANCAKE_ARB_DEFAULT,
30-
PANCAKE_ARB_MM,
31-
// 'https://tokens.coingecko.com/arbitrum-one/all.json'
32-
]
33-
const LINEA_URLS = [PANCAKE_LINEA_DEFAULT, 'https://tokens.coingecko.com/linea/all.json']
28+
const ARBITRUM_URLS = [PANCAKE_ARB_DEFAULT, COINGECKO_ARB]
29+
const LINEA_URLS = [PANCAKE_LINEA_DEFAULT, COINGECKO_LINEA]
3430
const ZKSYNC_URLS = [
3531
PANCAKE_ZKSYNC_DEFAULT,
3632
// 'https://tokens.coingecko.com/zksync/all.json'
3733
]
3834
const OP_SUPER_CHAIN_URL =
3935
'https://raw.githubusercontent.com/ethereum-optimism/ethereum-optimism.github.io/master/optimism.tokenlist.json'
40-
const BASE_URLS = [PANCAKE_BASE_DEFAULT, OP_SUPER_CHAIN_URL, 'https://tokens.coingecko.com/base/all.json']
36+
const BASE_URLS = [PANCAKE_BASE_DEFAULT, OP_SUPER_CHAIN_URL, COINGECKO_BASE]
4137
const OPBNB_URLS = [PANCAKE_OPBNB_DEFAULT]
4238
const MONAD_TESTNET_URLS = [PANCAKE_MONAD_TESTNET_DEFAULT]
4339

@@ -67,20 +63,19 @@ export const DEFAULT_LIST_OF_LISTS: string[] = [
6763
export const DEFAULT_ACTIVE_LIST_URLS: string[] = [
6864
PANCAKE_EXTENDED,
6965
PANCAKE_ETH_DEFAULT,
70-
PANCAKE_ETH_MM,
71-
PANCAKE_BSC_MM,
72-
PANCAKE_ARB_MM,
73-
PANCAKE_ETH_DEFAULT,
7466
PANCAKE_POLYGON_ZKEVM_DEFAULT,
7567
PANCAKE_ZKSYNC_DEFAULT,
7668
PANCAKE_ARB_DEFAULT,
7769
PANCAKE_LINEA_DEFAULT,
7870
PANCAKE_BASE_DEFAULT,
7971
PANCAKE_OPBNB_DEFAULT,
8072
OP_SUPER_CHAIN_URL,
81-
COINGECKO,
73+
COINGECKO_BSC,
8274
COINGECKO_ETH,
75+
COINGECKO_ARB,
76+
COINGECKO_BASE,
8377
PANCAKE_MONAD_TESTNET_DEFAULT,
78+
COINGECKO_LINEA,
8479
]
8580

8681
export const MULTI_CHAIN_LIST_URLS: { [chainId: number]: string[] } = {

apps/web/src/hooks/infinity/useCampaigns.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ const fetchCampaignsByPageNo = async ({
102102

103103
type CampaignsByChanIdProps = Omit<CampaignsByPoolIdProps, 'poolIds' | 'page' | 'fetchAll'>
104104

105-
const fetchAllCampaignsByChainId = async ({ chainId, includeInactive = true }: CampaignsByChanIdProps) => {
105+
export const fetchAllCampaignsByChainId = async ({ chainId, includeInactive = true }: CampaignsByChanIdProps) => {
106106
if (!chainId) {
107107
return []
108108
}

0 commit comments

Comments
 (0)