Skip to content

Commit

Permalink
feat: Use gauges as routing reference (#8994)
Browse files Browse the repository at this point in the history
<!--
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 adds new dependencies and introduces changes to the code in the
`packages/tokens` and `packages/smart-router` directories.

### Detailed summary
- Added new dependencies: `@pancakeswap/gauges`
- Added `getTokensByChain` function in `helpers/getTokensByChain.ts`
- Exported additional constants in `index.ts`
- Updated `allTokens.ts` to include tokens for various chains
- Updated `getPairCombinations.ts` in `smart-router` to include new
imports and functions

> The following files were skipped due to too many changes:
`pnpm-lock.yaml`

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your
question}`

<!-- end pr-codex -->
  • Loading branch information
chefjackson authored Feb 6, 2024
1 parent c370217 commit d28653a
Show file tree
Hide file tree
Showing 25 changed files with 332 additions and 86 deletions.
109 changes: 105 additions & 4 deletions packages/smart-router/evm/v3-router/functions/getPairCombinations.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,92 @@
import { ChainId } from '@pancakeswap/chains'
import { Currency, Token } from '@pancakeswap/sdk'
import { getTokensByChain } from '@pancakeswap/tokens'
import type { Address } from 'viem'
import { GAUGES_CONFIG, GaugeConfig, GaugeType } from '@pancakeswap/gauges'
import flatMap from 'lodash/flatMap.js'
import memoize from 'lodash/memoize.js'
import uniqBy from 'lodash/uniqBy.js'

import { ADDITIONAL_BASES, BASES_TO_CHECK_TRADES_AGAINST, CUSTOM_BASES } from '../../constants'
import { wrappedCurrency } from '../../utils/currency'
import { isCurrenciesSameChain } from '../utils'
import { isCurrenciesSameChain, log } from '../utils'

const allGuages = GAUGES_CONFIG[ChainId.BSC]

const getToken = memoize(
(chainId?: ChainId, address?: Address): Token | undefined => {
if (!chainId || !address) {
return undefined
}
const tokens = getTokensByChain(chainId)
for (const token of tokens) {
if (token.address.toLowerCase() === address.toLowerCase()) {
return token
}
}
return undefined
},
(chainId, address) => `${chainId}_${address}`,
)

// TODO: move to gauges
const getGaugesByChain = memoize(
(chainId?: ChainId): GaugeConfig[] => allGuages.filter((gauge) => gauge.chainId === chainId),
(chainId) => chainId,
)

function isTokenInCommonBases(token?: Token) {
return Boolean(token && BASES_TO_CHECK_TRADES_AGAINST[token.chainId as ChainId].find((t) => t.equals(token)))
}

const getTokenBasesFromGauges = memoize(
(currency?: Currency): Token[] => {
const chainId: ChainId | undefined = currency?.chainId
const address = currency?.wrapped.address
const gauges = getGaugesByChain(currency?.chainId)
const bases = new Set<Token>()
const addTokenToBases = (token?: Token) => token && !isTokenInCommonBases(token) && bases.add(token)
const addTokensToBases = (tokens: Token[]) => tokens.forEach(addTokenToBases)
const isCurrentToken = (addr: Address) => addr.toLowerCase() === address?.toLowerCase()

if (currency && chainId && isTokenInCommonBases(currency.wrapped)) {
return []
}
for (const gauge of gauges) {
const { type } = gauge
if (type === GaugeType.V2 || type === GaugeType.V3) {
const { token0Address, token1Address } = gauge
if (isCurrentToken(token0Address)) {
addTokenToBases(getToken(chainId, token1Address))
}
if (isCurrentToken(token1Address)) {
addTokenToBases(getToken(chainId, token0Address))
}
continue
}
if (type === GaugeType.StableSwap) {
const { tokenAddresses } = gauge
const index = tokenAddresses.findIndex(isCurrentToken)
if (index < 0) {
continue
}
addTokensToBases(
[...tokenAddresses.slice(0, index), ...tokenAddresses.slice(index + 1)]
.map((addr) => getToken(chainId, addr))
.filter((token?: Token): token is Token => Boolean(token)),
)
}
}
const baseList = Array.from(bases)
log(
`[ADDITIONAL_BASES] Token ${currency?.symbol}, bases from guages: [${baseList
.map((base) => base.symbol)
.join(',')}]`,
)
return baseList
},
(c) => `${c?.chainId}_${c?.wrapped.address}`,
)

const resolver = (currencyA?: Currency, currencyB?: Currency) => {
if (!currencyA || !currencyB || currencyA.wrapped.equals(currencyB.wrapped)) {
Expand All @@ -17,6 +98,28 @@ const resolver = (currencyA?: Currency, currencyB?: Currency) => {
return `${token0.chainId}_${token0.address}_${token1.address}`
}

type TokenBases = {
[tokenAddress: Address]: Token[]
}

function getAdditionalCheckAgainstBaseTokens(currencyA?: Currency, currencyB?: Currency) {
const chainId: ChainId | undefined = currencyA?.chainId
const additionalBases: TokenBases = {
...(chainId ? ADDITIONAL_BASES[chainId] ?? {} : {}),
}
const uniq = (tokens: Token[]) => uniqBy(tokens, (t) => t.address)
const additionalA =
currencyA && chainId
? uniq([...(additionalBases[currencyA.wrapped.address] || []), ...getTokenBasesFromGauges(currencyA)]) ?? []
: []
const additionalB =
currencyB && chainId
? uniq([...(additionalBases[currencyB.wrapped.address] || []), ...getTokenBasesFromGauges(currencyB)]) ?? []
: []

return [...additionalA, ...additionalB]
}

export const getCheckAgainstBaseTokens = memoize((currencyA?: Currency, currencyB?: Currency): Token[] => {
// eslint-disable-next-line prefer-destructuring
const chainId: ChainId | undefined = currencyA?.chainId
Expand All @@ -33,10 +136,8 @@ export const getCheckAgainstBaseTokens = memoize((currencyA?: Currency, currency
}

const common = BASES_TO_CHECK_TRADES_AGAINST[chainId] ?? []
const additionalA = tokenA ? ADDITIONAL_BASES[chainId]?.[tokenA.address] ?? [] : []
const additionalB = tokenB ? ADDITIONAL_BASES[chainId]?.[tokenB.address] ?? [] : []

return [...common, ...additionalA, ...additionalB]
return [...common, ...getAdditionalCheckAgainstBaseTokens(currencyA, currencyB)]
}, resolver)

export const getPairCombinations = memoize((currencyA?: Currency, currencyB?: Currency): [Currency, Currency][] => {
Expand Down
1 change: 1 addition & 0 deletions packages/smart-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
],
"dependencies": {
"@pancakeswap/chains": "workspace:*",
"@pancakeswap/gauges": "workspace:*",
"@pancakeswap/multicall": "workspace:*",
"@pancakeswap/sdk": "workspace:*",
"@pancakeswap/swap-sdk-core": "workspace:*",
Expand Down
39 changes: 39 additions & 0 deletions packages/tokens/src/allTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ChainId } from '@pancakeswap/chains'

import { bscTokens } from './constants/bsc'
import { goerliTestnetTokens } from './constants/goerli'
import { bscTestnetTokens } from './constants/bscTestnet'
import { ethereumTokens } from './constants/eth'
import { arbitrumTokens } from './constants/arb'
import { polygonZkEvmTokens } from './constants/polygonZkEVM'
import { polygonZkEvmTestnetTokens } from './constants/polygonZkEVMTestnet'
import { zksyncTokens } from './constants/zkSync'
import { zkSyncTestnetTokens } from './constants/zkSyncTestnet'
import { lineaTestnetTokens } from './constants/lineaTestnet'
import { lineaTokens } from './constants/linea'
import { arbitrumGoerliTokens } from './constants/arbGoerli'
import { opBnbTokens } from './constants/opBNB'
import { opBnbTestnetTokens } from './constants/opBnbTestnet'
import { baseTokens } from './constants/base'
import { baseTestnetTokens } from './constants/baseTestnet'
import { scrollSepoliaTokens } from './constants/scrollSepolia'

export const allTokens = {
[ChainId.GOERLI]: goerliTestnetTokens,
[ChainId.BSC]: bscTokens,
[ChainId.BSC_TESTNET]: bscTestnetTokens,
[ChainId.ETHEREUM]: ethereumTokens,
[ChainId.ARBITRUM_ONE]: arbitrumTokens,
[ChainId.POLYGON_ZKEVM]: polygonZkEvmTokens,
[ChainId.POLYGON_ZKEVM_TESTNET]: polygonZkEvmTestnetTokens,
[ChainId.ZKSYNC]: zksyncTokens,
[ChainId.ZKSYNC_TESTNET]: zkSyncTestnetTokens,
[ChainId.LINEA_TESTNET]: lineaTestnetTokens,
[ChainId.LINEA]: lineaTokens,
[ChainId.ARBITRUM_GOERLI]: arbitrumGoerliTokens,
[ChainId.OPBNB]: opBnbTokens,
[ChainId.OPBNB_TESTNET]: opBnbTestnetTokens,
[ChainId.BASE]: baseTokens,
[ChainId.BASE_TESTNET]: baseTestnetTokens,
[ChainId.SCROLL_SEPOLIA]: scrollSepoliaTokens,
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
13 changes: 13 additions & 0 deletions packages/tokens/src/helpers/getTokensByChain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ChainId } from '@pancakeswap/chains'
import { Token } from '@pancakeswap/sdk'

import { allTokens } from '../allTokens'

export function getTokensByChain(chainId?: ChainId): Token[] {
if (!chainId) {
return []
}

const tokenMap = allTokens[chainId]
return Object.values(tokenMap)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ChainId } from '@pancakeswap/chains'
import { enumValues } from '@pancakeswap/utils/enumValues'
import { TokenAddressMap } from '@pancakeswap/token-lists'

export * from './getTokensByChain'

const createEmptyList = () => {
const list = {} as Record<ChainId, TokenAddressMap<ChainId>[ChainId]>
for (const chainId of enumValues(ChainId)) {
Expand Down
36 changes: 18 additions & 18 deletions packages/tokens/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
export * from './common'
export * from './constants/common'
export * from './helpers'
export * from './goerli'
export * from './bsc'
export * from './bscTestnet'
export * from './eth'
export * from './arb'
export * from './polygonZkEVM'
export * from './polygonZkEVMTestnet'
export * from './zkSync'
export * from './zkSyncTestnet'
export * from './lineaTestnet'
export * from './linea'
export * from './arbGoerli'
export * from './opBnbTestnet'
export * from './opBNB'
export * from './base'
export * from './baseTestnet'
export * from './scrollSepolia'
export * from './constants/goerli'
export * from './constants/bsc'
export * from './constants/bscTestnet'
export * from './constants/eth'
export * from './constants/arb'
export * from './constants/polygonZkEVM'
export * from './constants/polygonZkEVMTestnet'
export * from './constants/zkSync'
export * from './constants/zkSyncTestnet'
export * from './constants/lineaTestnet'
export * from './constants/linea'
export * from './constants/arbGoerli'
export * from './constants/opBnbTestnet'
export * from './constants/opBNB'
export * from './constants/base'
export * from './constants/baseTestnet'
export * from './constants/scrollSepolia'
Loading

0 comments on commit d28653a

Please sign in to comment.