diff --git a/api/_constants.ts b/api/_constants.ts index 8f1b20d4d..2106b4db1 100644 --- a/api/_constants.ts +++ b/api/_constants.ts @@ -98,6 +98,12 @@ const defaultRelayerFeeCapitalCostConfig: { cutoff: ethers.utils.parseUnits("10000").toString(), decimals: 18, }, + GRASS: { + lowerBound: ethers.utils.parseUnits("0.0001").toString(), + upperBound: ethers.utils.parseUnits("0.0005").toString(), + cutoff: ethers.utils.parseUnits("10000").toString(), + decimals: 18, + }, }; defaultRelayerFeeCapitalCostConfig["USDC.e"] = { diff --git a/api/_errors.ts b/api/_errors.ts index b48ac2651..8cdef3e83 100644 --- a/api/_errors.ts +++ b/api/_errors.ts @@ -267,6 +267,7 @@ export function handleErrorCondition( at: endpoint, code: acrossApiError.code, message: `Status ${acrossApiError.status} - ${acrossApiError.message}`, + cause: acrossApiError.cause, }); return response.status(acrossApiError.status).json(acrossApiError); diff --git a/api/_utils.ts b/api/_utils.ts index fb658cd46..69c2a7bf3 100644 --- a/api/_utils.ts +++ b/api/_utils.ts @@ -83,7 +83,6 @@ type RpcProviderName = keyof typeof rpcProvidersJson.providers.urls; const { REACT_APP_HUBPOOL_CHAINID, - REACT_APP_PUBLIC_INFURA_ID, REACT_APP_COINGECKO_PRO_API_KEY, BASE_FEE_MARKUP, PRIORITY_FEE_MARKUP, @@ -165,9 +164,9 @@ export const getLogger = (): LoggingUtility => { const defaultLogLevel = VERCEL_ENV === "production" ? "ERROR" : "DEBUG"; let logLevel = - LOG_LEVEL && !Object.keys(LogLevels).includes(LOG_LEVEL) - ? defaultLogLevel - : (LOG_LEVEL as keyof typeof LogLevels); + LOG_LEVEL && Object.keys(LogLevels).includes(LOG_LEVEL) + ? (LOG_LEVEL as keyof typeof LogLevels) + : defaultLogLevel; logger = { debug: (...args) => { @@ -537,19 +536,6 @@ export const getHubPool = (provider: providers.Provider) => { return HubPool__factory.connect(ENABLED_ROUTES.hubPoolAddress, provider); }; -/** - * Resolves an Infura provider given the name of the ETH network - * @param nameOrChainId The name of an ethereum network - * @returns A valid Ethers RPC provider - */ -export const infuraProvider = (nameOrChainId: providers.Networkish) => { - const url = new ethers.providers.InfuraProvider( - nameOrChainId, - REACT_APP_PUBLIC_INFURA_ID - ).connection.url; - return new ethers.providers.StaticJsonRpcProvider(url); -}; - /** * Resolves a fixed Static RPC provider if an override url has been specified. * @returns A provider or undefined if an override was not specified. @@ -906,7 +892,7 @@ export const getProvider = ( } else if (override) { providerCache[cacheKey] = override; } else { - providerCache[cacheKey] = infuraProvider(_chainId); + throw new Error(`No provider URL set for chain: ${chainId}`); } } return providerCache[cacheKey]; @@ -925,9 +911,10 @@ function getProviderFromConfigJson( const urls = getRpcUrlsFromConfigJson(chainId); if (urls.length === 0) { - console.warn( - `No provider URL found for chainId ${chainId} in rpc-providers.json` - ); + getLogger().warn({ + at: "getProviderFromConfigJson", + message: `No provider URL found for chainId ${chainId} in rpc-providers.json`, + }); return undefined; } diff --git a/api/limits.ts b/api/limits.ts index d9dd4f06c..7fc4514a6 100644 --- a/api/limits.ts +++ b/api/limits.ts @@ -174,7 +174,8 @@ const handler = async ( ] = await Promise.all([ getCachedTokenPrice( l1Token.address, - sdk.utils.getNativeTokenSymbol(destinationChainId).toLowerCase() + sdk.constants.CUSTOM_GAS_TOKENS[destinationChainId]?.toLowerCase() ?? + sdk.utils.getNativeTokenSymbol(destinationChainId).toLowerCase() ), getCachedTokenPrice(l1Token.address, "usd"), getCachedLatestBlock(HUB_POOL_CHAIN_ID), diff --git a/scripts/chain-configs/index.ts b/scripts/chain-configs/index.ts index abd858edb..f955d5dc6 100644 --- a/scripts/chain-configs/index.ts +++ b/scripts/chain-configs/index.ts @@ -6,6 +6,7 @@ export { default as BASE_SEPOLIA } from "./base-sepolia"; export { default as BLAST } from "./blast"; export { default as BLAST_SEPOLIA } from "./blast-sepolia"; export { default as INK } from "./ink"; +export { default as LENS_SEPOLIA } from "./lens-sepolia"; export { default as LINEA } from "./linea"; export { default as LISK } from "./lisk"; export { default as LISK_SEPOLIA } from "./lisk-sepolia"; diff --git a/scripts/chain-configs/lens-sepolia/assets/grayscale-logo.svg b/scripts/chain-configs/lens-sepolia/assets/grayscale-logo.svg new file mode 100644 index 000000000..16e98373e --- /dev/null +++ b/scripts/chain-configs/lens-sepolia/assets/grayscale-logo.svg @@ -0,0 +1,13 @@ + + + diff --git a/scripts/chain-configs/lens-sepolia/assets/logo.svg b/scripts/chain-configs/lens-sepolia/assets/logo.svg new file mode 100644 index 000000000..fe0fb7969 --- /dev/null +++ b/scripts/chain-configs/lens-sepolia/assets/logo.svg @@ -0,0 +1,13 @@ + + + diff --git a/scripts/chain-configs/lens-sepolia/index.ts b/scripts/chain-configs/lens-sepolia/index.ts new file mode 100644 index 000000000..21e9f230f --- /dev/null +++ b/scripts/chain-configs/lens-sepolia/index.ts @@ -0,0 +1,23 @@ +import { CHAIN_IDs, PUBLIC_NETWORKS } from "@across-protocol/constants"; +import { utils as sdkUtils } from "@across-protocol/sdk"; +import { ChainConfig } from "../types"; + +const { getDeployedAddress, getDeployedBlockNumber } = sdkUtils; + +const chainId = CHAIN_IDs.LENS_SEPOLIA; +const chainInfoBase = PUBLIC_NETWORKS[chainId]; + +export default { + ...chainInfoBase, + logoPath: "./assets/logo.svg", + grayscaleLogoPath: "./assets/grayscale-logo.svg", + spokePool: { + address: getDeployedAddress("SpokePool", chainId), + blockNumber: getDeployedBlockNumber("SpokePool", chainId), + }, + chainId, + publicRpcUrl: "https://rpc.testnet.lens.dev", + blockTimeSeconds: 1, + tokens: ["GRASS", "WETH", "WGRASS"], + enableCCTP: false, +} as ChainConfig; diff --git a/scripts/chain-configs/sepolia/index.ts b/scripts/chain-configs/sepolia/index.ts index 2a2ba493f..a7d3667c6 100644 --- a/scripts/chain-configs/sepolia/index.ts +++ b/scripts/chain-configs/sepolia/index.ts @@ -17,7 +17,7 @@ export default { }, chainId, publicRpcUrl: "https://gateway.tenderly.co/public/sepolia", - tokens: ["WETH", "ETH", "USDC"], + tokens: ["WETH", "ETH", "USDC", "GRASS"], enableCCTP: false, swapTokens: [], } as ChainConfig; diff --git a/scripts/generate-routes.ts b/scripts/generate-routes.ts index 3a5db6b17..29f28acbd 100644 --- a/scripts/generate-routes.ts +++ b/scripts/generate-routes.ts @@ -58,6 +58,7 @@ const enabledSepoliaChainConfigs = [ chainConfigs.POLYGON_AMOY, chainConfigs.BLAST_SEPOLIA, chainConfigs.LISK_SEPOLIA, + chainConfigs.LENS_SEPOLIA, ]; const enabledRoutes = { @@ -275,6 +276,18 @@ function transformChainConfigs( ]; } + if ( + tokenSymbol === "WGRASS" && + toChainConfig.tokens.includes("GRASS") + ) { + return [ + { + inputTokenSymbol: "WGRASS", + outputTokenSymbol: "GRASS", + }, + ]; + } + // Handle WETH Polygon & other non-eth chains if ( tokenSymbol === "WETH" && diff --git a/src/assets/chain-logos/lens-sepolia-grayscale.svg b/src/assets/chain-logos/lens-sepolia-grayscale.svg new file mode 100644 index 000000000..95a53dc22 --- /dev/null +++ b/src/assets/chain-logos/lens-sepolia-grayscale.svg @@ -0,0 +1,14 @@ + + + diff --git a/src/assets/chain-logos/lens-sepolia.svg b/src/assets/chain-logos/lens-sepolia.svg new file mode 100644 index 000000000..5531b2f06 --- /dev/null +++ b/src/assets/chain-logos/lens-sepolia.svg @@ -0,0 +1,13 @@ + + + diff --git a/src/constants/chains/configs.ts b/src/constants/chains/configs.ts index d4c6e1c65..42fae087a 100644 --- a/src/constants/chains/configs.ts +++ b/src/constants/chains/configs.ts @@ -40,6 +40,11 @@ import inkGrayscaleLogo from "assets/chain-logos/ink-grayscale.svg"; import { ReactComponent as inkLogoSvg } from "assets/chain-logos/ink.svg"; import { ReactComponent as inkGrayscaleLogoSvg } from "assets/chain-logos/ink-grayscale.svg"; +import lensSepoliaLogo from "assets/chain-logos/lens-sepolia.svg"; +import lensSepoliaGrayscaleLogo from "assets/chain-logos/lens-sepolia-grayscale.svg"; +import { ReactComponent as lensSepoliaLogoSvg } from "assets/chain-logos/lens-sepolia.svg"; +import { ReactComponent as lensSepoliaGrayscaleLogoSvg } from "assets/chain-logos/lens-sepolia-grayscale.svg"; + import lineaLogo from "assets/chain-logos/linea.svg"; import lineaGrayscaleLogo from "assets/chain-logos/linea-grayscale.svg"; import { ReactComponent as lineaLogoSvg } from "assets/chain-logos/linea.svg"; @@ -259,6 +264,23 @@ export const ink = { pollingInterval: 1000, }; +export const lensSepolia = { + name: "Lens Sepolia", + fullName: "Lens sepolia", + chainId: 37111, + logoURI: lensSepoliaLogo, + grayscaleLogoURI: lensSepoliaGrayscaleLogo, + logoSvg: lensSepoliaLogoSvg, + grayscaleLogoSvg: lensSepoliaGrayscaleLogoSvg, + rpcUrl: "https://rpc.testnet.lens.dev", + explorerUrl: "https://block-explorer.testnet.lens.dev", + constructExplorerLink: (txHash: string) => + `${lensSepolia.explorerUrl}/tx/${txHash}`, + nativeCurrencySymbol: "GRASS", + customRpcUrl: process.env.REACT_APP_CHAIN_37111_PROVIDER_URL, + pollingInterval: 1000, +}; + export const linea = { name: "Linea", fullName: "Linea", @@ -554,6 +576,7 @@ export const chainConfigs = [ blast, blastSepolia, ink, + lensSepolia, linea, lisk, liskSepolia, diff --git a/src/constants/chains/index.ts b/src/constants/chains/index.ts index 4b7d85252..421a305bd 100644 --- a/src/constants/chains/index.ts +++ b/src/constants/chains/index.ts @@ -36,6 +36,7 @@ const orderedEnabledChainIds = [ CHAIN_IDs.POLYGON_AMOY, CHAIN_IDs.BLAST_SEPOLIA, CHAIN_IDs.LISK_SEPOLIA, + CHAIN_IDs.LENS_SEPOLIA, ]; export const chainInfoList: ChainInfoList = orderedEnabledChainIds.map( diff --git a/src/constants/tokens.ts b/src/constants/tokens.ts index ec12265e2..cc9f7c77f 100644 --- a/src/constants/tokens.ts +++ b/src/constants/tokens.ts @@ -15,6 +15,8 @@ import snxLogo from "assets/token-logos/snx.svg"; import pooltogetherLogo from "assets/token-logos/pool.svg"; import lskLogo from "assets/token-logos/lsk.svg"; import usdbLogo from "assets/token-logos/usdb.svg"; +// TODO: Replace with actual GRASS logo once known +import grassLogo from "assets/icons/question-circle.svg"; import { BRIDGED_USDC_SYMBOLS } from "../utils/sdk"; @@ -83,4 +85,6 @@ export const orderedTokenLogos = { OP: optimismLogo, ARB: arbitrumLogo, LSK: lskLogo, + GRASS: grassLogo, + WGRASS: grassLogo, }; diff --git a/src/data/chains_11155111.json b/src/data/chains_11155111.json index d4302785d..00c1777bc 100644 --- a/src/data/chains_11155111.json +++ b/src/data/chains_11155111.json @@ -28,6 +28,13 @@ "name": "USD Coin", "decimals": 6, "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/src/assets/token-logos/usdc.svg" + }, + { + "address": "0x2Be68B15c693D3b5747F9F0D49D30A2E81BAA2Df", + "symbol": "GRASS", + "name": "Grass", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/src/assets/token-logos/grass.svg" } ], "outputTokens": [ @@ -51,6 +58,13 @@ "name": "USD Coin", "decimals": 6, "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/src/assets/token-logos/usdc.svg" + }, + { + "address": "0x2Be68B15c693D3b5747F9F0D49D30A2E81BAA2Df", + "symbol": "GRASS", + "name": "Grass", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/src/assets/token-logos/grass.svg" } ] }, @@ -382,5 +396,60 @@ "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/src/assets/token-logos/eth.svg" } ] + }, + { + "chainId": 37111, + "name": "Lens Sepolia", + "publicRpcUrl": "https://rpc.testnet.lens.dev", + "explorerUrl": "https://block-explorer.testnet.lens.dev", + "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/scripts/chain-configs/lens-sepolia/assets/logo.svg", + "spokePool": "0x6A0a7f39530923911832Dd60667CE5da5449967B", + "spokePoolBlock": 156275, + "inputTokens": [ + { + "address": "0xeee5a340Cdc9c179Db25dea45AcfD5FE8d4d3eB8", + "symbol": "GRASS", + "name": "Grass", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/src/assets/token-logos/grass.svg" + }, + { + "address": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "symbol": "WETH", + "name": "Wrapped Ether", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/src/assets/token-logos/weth.svg" + }, + { + "address": "0xeee5a340Cdc9c179Db25dea45AcfD5FE8d4d3eB8", + "symbol": "WGRASS", + "name": "Wrapped Grass", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/src/assets/token-logos/wgrass.svg" + } + ], + "outputTokens": [ + { + "address": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "symbol": "WETH", + "name": "Wrapped Ether", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/src/assets/token-logos/weth.svg" + }, + { + "address": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "symbol": "ETH", + "name": "Ether", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/src/assets/token-logos/eth.svg" + }, + { + "address": "0xeee5a340Cdc9c179Db25dea45AcfD5FE8d4d3eB8", + "symbol": "GRASS", + "name": "Grass", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/src/assets/token-logos/grass.svg" + } + ] } ] diff --git a/src/data/routes_11155111_0x14224e63716afAcE30C9a417E0542281869f7d9e.json b/src/data/routes_11155111_0x14224e63716afAcE30C9a417E0542281869f7d9e.json index 2bf848111..ccdb4e69f 100644 --- a/src/data/routes_11155111_0x14224e63716afAcE30C9a417E0542281869f7d9e.json +++ b/src/data/routes_11155111_0x14224e63716afAcE30C9a417E0542281869f7d9e.json @@ -212,6 +212,39 @@ "isNative": true, "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" }, + { + "fromChain": 11155111, + "toChain": 37111, + "fromTokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0x5ef6C01E11889d86803e0B23e3cB3F9E9d97B662", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 11155111, + "toChain": 37111, + "fromTokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0x5ef6C01E11889d86803e0B23e3cB3F9E9d97B662", + "fromTokenSymbol": "ETH", + "toTokenSymbol": "ETH", + "isNative": true, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 11155111, + "toChain": 37111, + "fromTokenAddress": "0x2Be68B15c693D3b5747F9F0D49D30A2E81BAA2Df", + "toTokenAddress": "0xeee5a340Cdc9c179Db25dea45AcfD5FE8d4d3eB8", + "fromSpokeAddress": "0x5ef6C01E11889d86803e0B23e3cB3F9E9d97B662", + "fromTokenSymbol": "GRASS", + "toTokenSymbol": "GRASS", + "isNative": false, + "l1TokenAddress": "0x2Be68B15c693D3b5747F9F0D49D30A2E81BAA2Df" + }, { "fromChain": 84532, "toChain": 11155111, @@ -399,6 +432,28 @@ "isNative": true, "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" }, + { + "fromChain": 84532, + "toChain": 37111, + "fromTokenAddress": "0x4200000000000000000000000000000000000006", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0x82B564983aE7274c86695917BBf8C99ECb6F0F8F", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 84532, + "toChain": 37111, + "fromTokenAddress": "0x4200000000000000000000000000000000000006", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0x82B564983aE7274c86695917BBf8C99ECb6F0F8F", + "fromTokenSymbol": "ETH", + "toTokenSymbol": "ETH", + "isNative": true, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, { "fromChain": 421614, "toChain": 11155111, @@ -597,6 +652,28 @@ "isNative": true, "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" }, + { + "fromChain": 421614, + "toChain": 37111, + "fromTokenAddress": "0x980B62Da83eFf3D4576C647993b0c1D7faf17c73", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0x7E63A5f1a8F0B4d0934B2f2327DAED3F6bb2ee75", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 421614, + "toChain": 37111, + "fromTokenAddress": "0x980B62Da83eFf3D4576C647993b0c1D7faf17c73", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0x7E63A5f1a8F0B4d0934B2f2327DAED3F6bb2ee75", + "fromTokenSymbol": "ETH", + "toTokenSymbol": "ETH", + "isNative": true, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, { "fromChain": 11155420, "toChain": 11155111, @@ -795,6 +872,28 @@ "isNative": false, "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" }, + { + "fromChain": 11155420, + "toChain": 37111, + "fromTokenAddress": "0x4200000000000000000000000000000000000006", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0x4e8E101924eDE233C13e2D8622DC8aED2872d505", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 11155420, + "toChain": 37111, + "fromTokenAddress": "0x4200000000000000000000000000000000000006", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0x4e8E101924eDE233C13e2D8622DC8aED2872d505", + "fromTokenSymbol": "ETH", + "toTokenSymbol": "ETH", + "isNative": true, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, { "fromChain": 919, "toChain": 11155111, @@ -949,6 +1048,28 @@ "isNative": true, "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" }, + { + "fromChain": 919, + "toChain": 37111, + "fromTokenAddress": "0x4200000000000000000000000000000000000006", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0xbd886FC0725Cc459b55BbFEb3E4278610331f83b", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 919, + "toChain": 37111, + "fromTokenAddress": "0x4200000000000000000000000000000000000006", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0xbd886FC0725Cc459b55BbFEb3E4278610331f83b", + "fromTokenSymbol": "ETH", + "toTokenSymbol": "ETH", + "isNative": true, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, { "fromChain": 80002, "toChain": 11155111, @@ -1026,6 +1147,17 @@ "isNative": false, "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" }, + { + "fromChain": 80002, + "toChain": 37111, + "fromTokenAddress": "0x52eF3d68BaB452a294342DC3e5f464d7f610f72E", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0xd08baaE74D6d2eAb1F3320B2E1a53eeb391ce8e5", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, { "fromChain": 168587773, "toChain": 11155111, @@ -1180,6 +1312,28 @@ "isNative": true, "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" }, + { + "fromChain": 168587773, + "toChain": 37111, + "fromTokenAddress": "0x4200000000000000000000000000000000000023", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0x5545092553Cf5Bf786e87a87192E902D50D8f022", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 168587773, + "toChain": 37111, + "fromTokenAddress": "0x4200000000000000000000000000000000000023", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0x5545092553Cf5Bf786e87a87192E902D50D8f022", + "fromTokenSymbol": "ETH", + "toTokenSymbol": "ETH", + "isNative": true, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, { "fromChain": 4202, "toChain": 11155111, @@ -1333,6 +1487,138 @@ "toTokenSymbol": "ETH", "isNative": true, "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 4202, + "toChain": 37111, + "fromTokenAddress": "0x4200000000000000000000000000000000000006", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0xeF684C38F94F48775959ECf2012D7E864ffb9dd4", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 4202, + "toChain": 37111, + "fromTokenAddress": "0x4200000000000000000000000000000000000006", + "toTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "fromSpokeAddress": "0xeF684C38F94F48775959ECf2012D7E864ffb9dd4", + "fromTokenSymbol": "ETH", + "toTokenSymbol": "ETH", + "isNative": true, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 37111, + "toChain": 11155111, + "fromTokenAddress": "0xeee5a340Cdc9c179Db25dea45AcfD5FE8d4d3eB8", + "toTokenAddress": "0x2Be68B15c693D3b5747F9F0D49D30A2E81BAA2Df", + "fromSpokeAddress": "0x6A0a7f39530923911832Dd60667CE5da5449967B", + "fromTokenSymbol": "GRASS", + "toTokenSymbol": "GRASS", + "isNative": false, + "l1TokenAddress": "0x2Be68B15c693D3b5747F9F0D49D30A2E81BAA2Df" + }, + { + "fromChain": 37111, + "toChain": 11155111, + "fromTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "toTokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14", + "fromSpokeAddress": "0x6A0a7f39530923911832Dd60667CE5da5449967B", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 37111, + "toChain": 11155111, + "fromTokenAddress": "0xeee5a340Cdc9c179Db25dea45AcfD5FE8d4d3eB8", + "toTokenAddress": "0x2Be68B15c693D3b5747F9F0D49D30A2E81BAA2Df", + "fromSpokeAddress": "0x6A0a7f39530923911832Dd60667CE5da5449967B", + "fromTokenSymbol": "WGRASS", + "toTokenSymbol": "GRASS", + "isNative": false, + "l1TokenAddress": "0x2Be68B15c693D3b5747F9F0D49D30A2E81BAA2Df" + }, + { + "fromChain": 37111, + "toChain": 84532, + "fromTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "toTokenAddress": "0x4200000000000000000000000000000000000006", + "fromSpokeAddress": "0x6A0a7f39530923911832Dd60667CE5da5449967B", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 37111, + "toChain": 421614, + "fromTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "toTokenAddress": "0x980B62Da83eFf3D4576C647993b0c1D7faf17c73", + "fromSpokeAddress": "0x6A0a7f39530923911832Dd60667CE5da5449967B", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 37111, + "toChain": 11155420, + "fromTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "toTokenAddress": "0x4200000000000000000000000000000000000006", + "fromSpokeAddress": "0x6A0a7f39530923911832Dd60667CE5da5449967B", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 37111, + "toChain": 919, + "fromTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "toTokenAddress": "0x4200000000000000000000000000000000000006", + "fromSpokeAddress": "0x6A0a7f39530923911832Dd60667CE5da5449967B", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 37111, + "toChain": 80002, + "fromTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "toTokenAddress": "0x52eF3d68BaB452a294342DC3e5f464d7f610f72E", + "fromSpokeAddress": "0x6A0a7f39530923911832Dd60667CE5da5449967B", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 37111, + "toChain": 168587773, + "fromTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "toTokenAddress": "0x4200000000000000000000000000000000000023", + "fromSpokeAddress": "0x6A0a7f39530923911832Dd60667CE5da5449967B", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + }, + { + "fromChain": 37111, + "toChain": 4202, + "fromTokenAddress": "0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16", + "toTokenAddress": "0x4200000000000000000000000000000000000006", + "fromSpokeAddress": "0x6A0a7f39530923911832Dd60667CE5da5449967B", + "fromTokenSymbol": "WETH", + "toTokenSymbol": "WETH", + "isNative": false, + "l1TokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" } ], "swapRoutes": [ diff --git a/src/utils/constants.ts b/src/utils/constants.ts index ae82d34da..8bd6729e2 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -242,6 +242,7 @@ export const nonEthChains = [ ChainId.POLYGON, ChainId.POLYGON_AMOY, ChainId.ALEPH_ZERO, + ChainId.LENS_SEPOLIA, ]; export const tokenTable = Object.fromEntries( diff --git a/src/utils/sdk.ts b/src/utils/sdk.ts index b8b26a1bd..955b346b3 100644 --- a/src/utils/sdk.ts +++ b/src/utils/sdk.ts @@ -12,7 +12,10 @@ export { mapAsync } from "@across-protocol/sdk/dist/esm/utils/ArrayUtils"; export { getCurrentTime } from "@across-protocol/sdk/dist/esm/utils/TimeUtils"; export { isBridgedUsdc } from "@across-protocol/sdk/dist/esm/utils/TokenUtils"; export { BRIDGED_USDC_SYMBOLS } from "@across-protocol/sdk/dist/esm/constants"; -export { getNativeTokenSymbol } from "@across-protocol/sdk/dist/esm/utils/NetworkUtils"; +export { + getNativeTokenSymbol, + chainIsLens, +} from "@across-protocol/sdk/dist/esm/utils/NetworkUtils"; export function getUpdateV3DepositTypedData( depositId: number, diff --git a/src/views/Bridge/components/ChainSelector.tsx b/src/views/Bridge/components/ChainSelector.tsx index a81a676a7..0f40bcb54 100644 --- a/src/views/Bridge/components/ChainSelector.tsx +++ b/src/views/Bridge/components/ChainSelector.tsx @@ -13,10 +13,10 @@ import { shortenAddress, } from "utils"; -import { getAllChains } from "../utils"; import { useBalanceBySymbolPerChain, useConnection } from "hooks"; import { useMemo } from "react"; import { BigNumber } from "ethers"; +import { getSupportedChains } from "../utils"; type Props = { selectedRoute: Route; @@ -25,8 +25,6 @@ type Props = { onSelectChain: (chainId: number) => void; }; -const allChains = getAllChains(); - export function ChainSelector({ selectedRoute, fromOrTo, @@ -36,8 +34,8 @@ export function ChainSelector({ const isFrom = fromOrTo === "from"; const { fromChain, toChain, fromTokenSymbol, toTokenSymbol } = selectedRoute; const selectedChain = getChainInfo(isFrom ? fromChain : toChain); - const tokenInfo = getToken(isFrom ? fromTokenSymbol : toTokenSymbol); + const allChains = getSupportedChains(fromOrTo); const { account, isConnected } = useConnection(); const { balances } = useBalanceBySymbolPerChain({ @@ -74,7 +72,7 @@ export function ChainSelector({ } }); } - }, [balances, isConnected, isFrom]); + }, [allChains, balances, isConnected, isFrom]); return ( diff --git a/src/views/Bridge/utils.ts b/src/views/Bridge/utils.ts index c1c023768..494a2ff99 100644 --- a/src/views/Bridge/utils.ts +++ b/src/views/Bridge/utils.ts @@ -12,6 +12,7 @@ import { nonEthChains, GetBridgeFeesResult, chainEndpointToId, + chainIsLens, } from "utils"; import { SwapQuoteApiResponse } from "utils/serverless-api/prod/swap-quote"; @@ -88,6 +89,14 @@ export function getReceiveTokenSymbol( return "ETH"; } + if (inputTokenSymbol === "GRASS" && chainIsLens(destinationChainId)) { + return isReceiverContract ? "WGRASS" : "GRASS"; + } + + if (inputTokenSymbol === "WGRASS") { + return "GRASS"; + } + return outputTokenSymbol; } @@ -351,23 +360,46 @@ export function getAvailableOutputTokens( ); } -export function getAllChains() { - return enabledRoutes - .map((route) => getChainInfo(route.fromChain)) - .filter( - (chain, index, self) => - index === - self.findIndex((fromChain) => fromChain.chainId === chain.chainId) - ) - .sort((a, b) => { - if (a.name < b.name) { - return -1; - } - if (a.name > b.name) { - return 1; - } - return 0; - }); +export const ChainType = { + FROM: "from", + TO: "to", + ALL: "all", +} as const; + +export type ChainTypeT = (typeof ChainType)[keyof typeof ChainType]; + +export function getSupportedChains(chainType: ChainTypeT = ChainType.ALL) { + let chainIds: number[] = []; + + switch (chainType) { + case ChainType.FROM: + chainIds = enabledRoutes.map((route) => route.fromChain); + break; + case ChainType.TO: + chainIds = enabledRoutes.map((route) => route.toChain); + break; + case ChainType.ALL: + default: + chainIds = enabledRoutes.flatMap((route) => [ + route.fromChain, + route.toChain, + ]); + break; + } + + const uniqueChainIds = Array.from(new Set(chainIds)); + + const uniqueChains = uniqueChainIds.map((chainId) => getChainInfo(chainId)); + + return uniqueChains.sort((a, b) => { + if (a.name < b.name) { + return -1; + } + if (a.name > b.name) { + return 1; + } + return 0; + }); } export function getRouteFromUrl(overrides?: RouteFilter) { diff --git a/yarn.lock b/yarn.lock index b45c687ad..a8b4b0985 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22961,7 +22961,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -22996,15 +22996,6 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.0, string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -23079,7 +23070,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -23107,13 +23098,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -25830,7 +25814,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -25865,15 +25849,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"