import _ from 'lodash' import * as CHAINS from '@constants/chains/master' import * as all from '@constants/tokens/bridgeable' import * as allPool from '@constants/tokens/poolMaster' import { GMX, ETH, USDC, USDT, WETH } from '@constants/tokens/bridgeable' import { SYN_ETH_SUSHI_TOKEN } from '@constants/tokens/sushiMaster' import { Chain, Token } from '@utils/types' import { ETHEREUM_ADDRESS } from '@constants' import { CHAINS_BY_ID } from '@constants/chains' const allSwap = [WETH, USDC, USDT] // TODO change this to token by key interface TokensByChain { [cID: string]: Token[] } interface GasTokensByChain { [chainId: string]: Chain['nativeCurrency'][] } interface TokenByKey { [cID: string]: Token } export const sortTokens = (tokens: Token[]) => Object.values(tokens).sort((a, b) => b.visibilityRank - a.visibilityRank) const sortedTokens = Object.values(all).sort( (a, b) => b.visibilityRank - a.visibilityRank ) // Key value pairs here will override bridgeMap to hide particular chain-token pairs export const PAUSED_TOKENS_BY_CHAIN = { [CHAINS.ETH.id]: ['WETH'], [CHAINS.OPTIMISM.id]: ['WETH'], [CHAINS.BOBA.id]: ['WETH'], [CHAINS.MOONBEAM.id]: ['WETH'], [CHAINS.BASE.id]: ['WETH'], [CHAINS.BLAST.id]: ['WETH'], [CHAINS.ARBITRUM.id]: ['WETH'], [CHAINS.FANTOM.id]: [], [CHAINS.DOGE.id]: ['BUSD', 'WETH'], [CHAINS.KLAYTN.id]: ['WETH'], } export const findChainIdsWithPausedToken = (routeSymbol: string) => { return _.reduce( PAUSED_TOKENS_BY_CHAIN, (result, tokens, chainId) => { if (_.includes(tokens, routeSymbol)) { result.push(chainId) } return result }, [] ) } const getBridgeableTokens = (): TokensByChain => { const bridgeableTokens: TokensByChain = {} Object.entries(all).map(([key, token]) => { for (const cID of Object.keys(token.addresses)) { // Skip if the token is paused on the current chain if (PAUSED_TOKENS_BY_CHAIN[cID]?.includes(key)) continue if (!bridgeableTokens[cID]) { bridgeableTokens[cID] = [token] } else { if (!bridgeableTokens[cID]?.includes(token)) { bridgeableTokens[cID] = [...bridgeableTokens[cID], token] } } } }) return bridgeableTokens } const getTokenHashMap = () => { const tokenHashMap = {} for (const [chainId, tokensOnChain] of _.toPairs(BRIDGABLE_TOKENS)) { tokenHashMap[chainId] = {} for (const token of tokensOnChain) { tokenHashMap[chainId][token.addresses[chainId]] = token } } tokenHashMap[CHAINS.AVALANCHE.id][GMX.wrapperAddresses[CHAINS.AVALANCHE.id]] = GMX Object.keys(WETH.addresses).map((chain) => { tokenHashMap[chain][WETH.addresses[chain]] = ETH }) return tokenHashMap } export const TOKENS_SORTED_BY_SWAPABLETYPE = Array.from( new Set(sortedTokens.map((token) => token.swapableType)) ) export const TOKENS_SORTED_BY_SYMBOL = Array.from( new Set(sortedTokens.map((token) => token.symbol)) ) export const BRIDGABLE_TOKENS = getBridgeableTokens() const bridgeableTokens = _(BRIDGABLE_TOKENS) .values() .flatten() .map((t) => t.symbol) .value() export const NON_BRIDGEABLE_GAS_TOKENS: GasTokensByChain = Object.values( CHAINS_BY_ID ).reduce((acc, chain) => { if (!bridgeableTokens.includes(chain.nativeCurrency.symbol)) { if (acc[chain.id]) { acc[chain.id].concat(chain.nativeCurrency) } else { acc[chain.id] = [chain.nativeCurrency] } } return acc }, {}) export const tokenSymbolToToken = (chainId: number, symbol: string) => { if (chainId) { const token = BRIDGABLE_TOKENS[chainId]?.find((token) => { return token.symbol === symbol }) return token } } export const tokenAddressToToken = ( chainId: number, tokenAddress: string ): Token => { if (chainId) { if (tokenAddress === WETH.addresses[chainId]) { return WETH } else if (tokenAddress === ETHEREUM_ADDRESS) { return ETH } else { const token = BRIDGABLE_TOKENS[chainId]?.find((token: Token) => { return token.addresses[chainId] === tokenAddress }) return token } } } export const TOKEN_HASH_MAP = getTokenHashMap() // SWAPS const allTokensWithSwap = [...Object.values(all), ...Object.values(allSwap)] const getSwapPriorityRanking = () => { const swapPriorityRanking = {} allTokensWithSwap.map((token) => { if (!token.priorityPool) return for (const cID of Object.keys(token.addresses)) { if (!swapPriorityRanking[cID]) { swapPriorityRanking[cID] = {} } for (const poolToken of token.poolTokens) { swapPriorityRanking[cID][poolToken.symbol] = token } } }) return swapPriorityRanking } export const POOL_PRIORITY_RANKING = getSwapPriorityRanking() // POOLS const getPoolsByChain = (displayOnly: boolean): TokensByChain => { const poolTokens: TokensByChain = {} Object.values(allPool).map((token) => { if (displayOnly && !token.display) return for (const cID of Object.keys(token.addresses)) { if (!poolTokens[cID]) { poolTokens[cID] = [token] } else { if (!poolTokens[cID]?.includes(token)) { poolTokens[cID] = [...poolTokens[cID], token] } } } }) return poolTokens } const getChainsByPoolName = () => { const CHAINS_BY_POOL_NAME = {} const poolsByChain = getPoolsByChain(false) Object.keys(poolsByChain).map((chainId) => { for (const swapToken of poolsByChain[chainId]) { CHAINS_BY_POOL_NAME[swapToken.poolName] = chainId } }) return CHAINS_BY_POOL_NAME } const getTokensByPoolTypeByChain = (type: string) => { const poolTokens: TokensByChain = {} Object.values(allPool).map((token) => { if (!token.display || !token?.poolType?.includes(type)) return for (const cID of Object.keys(token.addresses)) { if (!poolTokens[cID]) { poolTokens[cID] = [token] } else { if (!poolTokens[cID]?.includes(token)) { poolTokens[cID] = [...poolTokens[cID], token] } } } }) return poolTokens } const getLegacyTokensByChain = () => { const poolTokens: TokensByChain = {} Object.values(allPool).map((token) => { if (!token.legacy) return for (const cID of Object.keys(token.addresses)) { if (!poolTokens[cID]) { poolTokens[cID] = [token] } else { if (!poolTokens[cID]?.includes(token)) { poolTokens[cID] = [...poolTokens[cID], token] } } } }) return poolTokens } const getPoolByRouterIndex = () => { const poolTokens: TokenByKey = {} Object.values(allPool).map((token) => { poolTokens[token.routerIndex] = token }) return poolTokens } export const POOL_CHAINS_BY_NAME = getChainsByPoolName() export const POOL_BY_ROUTER_INDEX = getPoolByRouterIndex() export const POOLS_BY_CHAIN = getPoolsByChain(false) export const DISPLAY_POOLS_BY_CHAIN = getPoolsByChain(true) export const USD_POOLS_BY_CHAIN = getTokensByPoolTypeByChain('USD') export const ETH_POOLS_BY_CHAIN = getTokensByPoolTypeByChain('ETH') export const LEGACY_POOLS_BY_CHAIN = getLegacyTokensByChain() export const STAKABLE_TOKENS = { ...getPoolsByChain(false), [CHAINS.ETH.id]: [SYN_ETH_SUSHI_TOKEN], } const getStakingMap = () => { const STAKING_MAP_TOKENS = {} Object.keys(POOLS_BY_CHAIN).map((chainId) => { if (!STAKING_MAP_TOKENS[chainId]) { STAKING_MAP_TOKENS[chainId] = {} } STAKING_MAP_TOKENS[chainId] = {} for (const token of STAKABLE_TOKENS[chainId]) { STAKING_MAP_TOKENS[chainId][token.poolName] = token } }) return STAKING_MAP_TOKENS } export const STAKING_MAP_TOKENS = getStakingMap()