From aed43cfe6e15eb919e1cc9402f073196c12d2b11 Mon Sep 17 00:00:00 2001 From: yuli-ferna Date: Thu, 19 Dec 2024 13:30:12 -0400 Subject: [PATCH] OKB MNT and scrollETH config --- src/components/ShowTx.tsx | 15 ++++ src/components/SmartAddress.tsx | 22 ++++++ src/components/Transfer/Redeem.tsx | 21 ++++++ src/components/UnwrapNative.tsx | 29 ++++++++ src/hooks/useGetSourceParsedTokenAccounts.ts | 78 ++++++++++++++++++++ src/utils/consts.ts | 23 ++++++ 6 files changed, 188 insertions(+) diff --git a/src/components/ShowTx.tsx b/src/components/ShowTx.tsx index 01ab24b76..d720f47ac 100644 --- a/src/components/ShowTx.tsx +++ b/src/components/ShowTx.tsx @@ -24,6 +24,9 @@ import { CHAIN_ID_SUI, CHAIN_ID_BASE, CHAIN_ID_WORLDCHAIN, + CHAIN_ID_SCROLL, + CHAIN_ID_MANTLE, + CHAIN_ID_XLAYER, } from "@certusone/wormhole-sdk"; import { CHAIN_ID_NEAR } from "@certusone/wormhole-sdk/lib/esm"; import { Button, makeStyles, Typography } from "@material-ui/core"; @@ -190,6 +193,18 @@ export default function ShowTx({ ? `https://${ CLUSTER === "testnet" ? "worldchain-sepolia.explorer.alchemy.com" : "worldscan.org" }/tx/${tx?.id}` + : chainId === CHAIN_ID_SCROLL + ? `https://${ + CLUSTER === "testnet" ? "sepolia.scrollscan.dev" : "scrollscan.com" + }/tx/${tx?.id}` + : chainId === CHAIN_ID_MANTLE + ? `https://${ + CLUSTER === "testnet" ? "explorer.testnet.mantle.xyz" : "explorer.mantle.xyz" + }/tx/${tx?.id}` + : chainId === CHAIN_ID_XLAYER + ? `https://${ + CLUSTER === "testnet" ? "www.okx.com/web3/explorer/xlayer-test" : "www.okx.com/web3/explorer/xlayer" + }/tx/${tx?.id}` : undefined; const explorerName = getExplorerName(chainId); diff --git a/src/components/SmartAddress.tsx b/src/components/SmartAddress.tsx index fd90ad4e1..2d15051d7 100644 --- a/src/components/SmartAddress.tsx +++ b/src/components/SmartAddress.tsx @@ -28,6 +28,9 @@ import { CHAIN_ID_SUI, CHAIN_ID_BASE, CHAIN_ID_WORLDCHAIN, + CHAIN_ID_SCROLL, + CHAIN_ID_MANTLE, + CHAIN_ID_XLAYER, } from "@certusone/wormhole-sdk"; import { Button, makeStyles, Tooltip, Typography } from "@material-ui/core"; import { FileCopy, OpenInNew } from "@material-ui/icons"; @@ -213,6 +216,25 @@ export default function SmartAddress({ }/${ isAsset ? "token" : "address" }/${useableAddress}` + : chainId === CHAIN_ID_SCROLL + ? `https://${ + CLUSTER === "testnet" ? "sepolia.scrollscan.dev" : "scrollscan.com" + }/${ + isAsset ? "token" : "address" + }/${useableAddress}` + : chainId === CHAIN_ID_MANTLE + ? `https://${ + CLUSTER === "testnet" ? "explorer.testnet.mantle.xyz" : "explorer.mantle.xyz" + }/${ + isAsset ? "token" : "address" + }/${useableAddress}` + + : chainId === CHAIN_ID_XLAYER + ? `https://${ + CLUSTER === "testnet" ? "www.okx.com/web3/explorer/xlayer-test" : "www.okx.com/web3/explorer/xlayer" + }/${ + isAsset ? "token" : "address" + }/${useableAddress}` : chainId === CHAIN_ID_APTOS ? propertyVersion !== undefined // NFT ? `https://explorer.aptoslabs.com/token/${useableAddress}/${propertyVersion}${ diff --git a/src/components/Transfer/Redeem.tsx b/src/components/Transfer/Redeem.tsx index cd2a8634a..4dbb1d15f 100644 --- a/src/components/Transfer/Redeem.tsx +++ b/src/components/Transfer/Redeem.tsx @@ -7,12 +7,15 @@ import { CHAIN_ID_FANTOM, CHAIN_ID_KARURA, CHAIN_ID_KLAYTN, + CHAIN_ID_MANTLE, CHAIN_ID_MOONBEAM, CHAIN_ID_NEON, CHAIN_ID_OASIS, CHAIN_ID_POLYGON, + CHAIN_ID_SCROLL, CHAIN_ID_SOLANA, CHAIN_ID_WORLDCHAIN, + CHAIN_ID_XLAYER, ChainId, isEVMChain, isTerraChain, @@ -46,6 +49,7 @@ import { CHAINS_BY_ID, CLUSTER, getHowToAddTokensToWalletUrl, + SCROLLWETH_ADDRESS, WAVAX_ADDRESS, WBNB_ADDRESS, WETH_ADDRESS, @@ -53,7 +57,9 @@ import { WGLMR_ADDRESS, WKLAY_ADDRESS, WMATIC_ADDRESS, + WMNT_ADDRESS, WNEON_ADDRESS, + WOKB_ADDRESS, WORLDWETH_ADDRESS, WROSE_ADDRESS, } from "../../utils/consts"; @@ -206,6 +212,18 @@ function Redeem() { targetChain === CHAIN_ID_WORLDCHAIN && targetAsset && targetAsset.toLowerCase() === WORLDWETH_ADDRESS.toLowerCase(); + const isScrollNative = + targetChain === CHAIN_ID_SCROLL && + targetAsset && + targetAsset.toLowerCase() === SCROLLWETH_ADDRESS.toLowerCase(); + const isMantleNative = + targetChain === CHAIN_ID_MANTLE && + targetAsset && + targetAsset.toLowerCase() === WMNT_ADDRESS.toLowerCase(); + const isXlayerNative = + targetChain === CHAIN_ID_XLAYER && + targetAsset && + targetAsset.toLowerCase() === WOKB_ADDRESS.toLowerCase(); const isSolNative = targetChain === CHAIN_ID_SOLANA && targetAsset && @@ -222,6 +240,9 @@ function Redeem() { isMoonbeamNative || isArbitrumNative || isWorldchainNative || + isScrollNative || + isMantleNative || + isXlayerNative || isSolNative; const [useNativeRedeem, setUseNativeRedeem] = useState(true); const toggleNativeRedeem = useCallback(() => { diff --git a/src/components/UnwrapNative.tsx b/src/components/UnwrapNative.tsx index c98c8013a..be7097b08 100644 --- a/src/components/UnwrapNative.tsx +++ b/src/components/UnwrapNative.tsx @@ -12,6 +12,9 @@ import { CHAIN_ID_BASE, ethers_contracts, CHAIN_ID_WORLDCHAIN, + CHAIN_ID_SCROLL, + CHAIN_ID_XLAYER, + CHAIN_ID_MANTLE, } from "@certusone/wormhole-sdk"; import { Container, @@ -39,6 +42,7 @@ import neonIcon from "../icons/neon.svg"; import oasisIcon from "../icons/oasis-network-rose-logo.svg"; import polygonIcon from "../icons/polygon.svg"; import worldchainIcon from "../icons/worldchain.svg"; +import scrollIcon from "../icons/scroll.svg"; import { COLORS } from "../muiTheme"; import { DataWrapper, @@ -72,11 +76,18 @@ import { BASE_WETH_DECIMALS, WORLDWETH_ADDRESS, WORLDWETH_DECIMALS, + SCROLLWETH_ADDRESS, + SCROLLWETH_DECIMALS, + WMNT_ADDRESS, + WMNT_DECIMALS, + WOKB_ADDRESS, + WOKB_DECIMALS, } from "../utils/consts"; import parseError from "../utils/parseError"; import ButtonWithLoader from "./ButtonWithLoader"; import ConnectWalletButton from "./ConnectWalletButton"; import HeaderText from "./HeaderText"; +import { chainToIcon } from "@wormhole-foundation/sdk-icons"; const useStyles = makeStyles((theme) => ({ formControl: { @@ -184,6 +195,24 @@ const supportedTokens = { address: WORLDWETH_ADDRESS, decimals: WORLDWETH_DECIMALS, }, + [CHAIN_ID_SCROLL]: { + symbol: "WETH", + icon: scrollIcon, + address: SCROLLWETH_ADDRESS, + decimals: SCROLLWETH_DECIMALS, + }, + [CHAIN_ID_MANTLE]: { + symbol: "WMNT", + icon: chainToIcon("Mantle"), + address: WMNT_ADDRESS, + decimals: WMNT_DECIMALS, + }, + [CHAIN_ID_XLAYER]: { + symbol: "WOKB", + icon: chainToIcon("Xlayer"), + address: WOKB_ADDRESS, + decimals: WOKB_DECIMALS, + }, } as const; type SupportedChain = keyof typeof supportedTokens; diff --git a/src/hooks/useGetSourceParsedTokenAccounts.ts b/src/hooks/useGetSourceParsedTokenAccounts.ts index 039e14955..27482d148 100644 --- a/src/hooks/useGetSourceParsedTokenAccounts.ts +++ b/src/hooks/useGetSourceParsedTokenAccounts.ts @@ -28,6 +28,9 @@ import { CHAIN_ID_ARBITRUM, CHAIN_ID_BASE, CHAIN_ID_WORLDCHAIN, + CHAIN_ID_MANTLE, + CHAIN_ID_SCROLL, + CHAIN_ID_XLAYER, } from "@certusone/wormhole-sdk"; import { Dispatch } from "@reduxjs/toolkit"; import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; @@ -68,6 +71,7 @@ import polygonIcon from "../icons/polygon.svg"; import aptosIcon from "../icons/aptos.svg"; import suiIcon from "../icons/sui.svg"; import worldchainIcon from "../icons/worldchain.svg"; +import scrollIcon from "../icons/scroll.svg"; import { errorSourceParsedTokenAccounts as errorSourceParsedTokenAccountsNFT, fetchSourceParsedTokenAccounts as fetchSourceParsedTokenAccountsNFT, @@ -139,6 +143,12 @@ import { SUI_NATIVE_TOKEN_KEY, WORLDWETH_ADDRESS, WORLDWETH_DECIMALS, + SCROLLWETH_ADDRESS, + SCROLLWETH_DECIMALS, + WMNT_ADDRESS, + WMNT_DECIMALS, + WOKB_ADDRESS, + WOKB_DECIMALS, } from "../utils/consts"; import { makeNearAccount } from "../utils/near"; import { @@ -151,6 +161,7 @@ import { AptosCoinResourceReturn } from "./useAptosMetadata"; import { TokenClient, TokenTypes } from "aptos"; import { getSuiProvider } from "../utils/sui"; import { useSuiWallet } from "../contexts/SuiWalletContext"; +import { chainToIcon } from "@wormhole-foundation/sdk-icons"; export function createParsedTokenAccount( publicKey: string, @@ -636,6 +647,33 @@ const createNativeWorldchainParsedTokenAccount = ( }); }; +const createNativeParsedTokenAccount = ( + provider: Provider, + signerAddress: string | undefined, + wrappedAddress: string, + decimals: number, + icon: string, + symbol: string, +) => { + return !(provider && signerAddress) + ? Promise.reject() + : provider.getBalance(signerAddress).then((balanceInWei) => { + const balanceInEth = ethers.utils.formatEther(balanceInWei); + return createParsedTokenAccount( + signerAddress, //public key + wrappedAddress, //Mint key, On the other side this will be weth, so this is hopefully a white lie. + balanceInWei.toString(), //amount, in wei + decimals, + parseFloat(balanceInEth), //This loses precision, but is a limitation of the current datamodel. This field is essentially deprecated + balanceInEth.toString(), //This is the actual display field, which has full precision. + symbol, //A white lie for display purposes + symbol, //A white lie for display purposes + icon, + true //isNativeAsset + ); + }); +}; + const createNFTParsedTokenAccountFromCovalent = ( walletAddress: string, covalent: CovalentData, @@ -1854,6 +1892,46 @@ function useGetAvailableTokens(nft: boolean = false) { }; }, [lookupChain, provider, signerAddress, nft, ethNativeAccount]); + //Scroll, Mantle, Xlayer native asset load + useEffect(() => { + let cancelled = false; + if ( + signerAddress && + (lookupChain === CHAIN_ID_SCROLL || + lookupChain === CHAIN_ID_MANTLE || + lookupChain === CHAIN_ID_XLAYER) && + !ethNativeAccount && + !nft + ) { + setEthNativeAccountLoading(true); + let address = lookupChain === CHAIN_ID_SCROLL ? SCROLLWETH_ADDRESS : lookupChain === CHAIN_ID_MANTLE ? WMNT_ADDRESS : WOKB_ADDRESS; + let decimals = lookupChain === CHAIN_ID_SCROLL ? SCROLLWETH_DECIMALS : lookupChain === CHAIN_ID_MANTLE ? WMNT_DECIMALS : WOKB_DECIMALS; + let icon = lookupChain === CHAIN_ID_SCROLL ? scrollIcon : lookupChain === CHAIN_ID_MANTLE ? chainToIcon("Mantle") : chainToIcon("Xlayer"); + let symbol = lookupChain === CHAIN_ID_SCROLL ? "scrollETH" : lookupChain === CHAIN_ID_MANTLE ? "MNT" : "OKB"; + createNativeParsedTokenAccount(provider, signerAddress, address, decimals, icon, symbol).then( + (result) => { + console.log("create native account returned with value", result); + if (!cancelled) { + setEthNativeAccount(result); + setEthNativeAccountLoading(false); + setEthNativeAccountError(""); + } + }, + (error) => { + if (!cancelled) { + setEthNativeAccount(undefined); + setEthNativeAccountLoading(false); + setEthNativeAccountError("Unable to retrieve your MATIC balance."); + } + } + ); + } + + return () => { + cancelled = true; + }; + }, [lookupChain, provider, signerAddress, nft, ethNativeAccount]); + //Ethereum covalent or blockscout accounts load useEffect(() => { diff --git a/src/utils/consts.ts b/src/utils/consts.ts index d558b6c84..361ba3706 100644 --- a/src/utils/consts.ts +++ b/src/utils/consts.ts @@ -1715,6 +1715,29 @@ export const WORLDWETH_ADDRESS = : "0xDDb64fE46a91D46ee29420539FC25FD07c5FEa3E"; export const WORLDWETH_DECIMALS = 18; +export const SCROLLWETH_ADDRESS = + CLUSTER === "mainnet" + ? "0x5300000000000000000000000000000000000004" + : CLUSTER === "testnet" + ? "0x5300000000000000000000000000000000000004" + : "0xDDb64fE46a91D46ee29420539FC25FD07c5FEa3E"; +export const SCROLLWETH_DECIMALS = 18; + +export const WMNT_ADDRESS = + CLUSTER === "mainnet" + ? "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8" + : CLUSTER === "testnet" + ? "0xa4c4cb2A072eE99f77212Fa18c2B7Ca26DA23905" + : "0xDDb64fE46a91D46ee29420539FC25FD07c5FEa3E"; +export const WMNT_DECIMALS = 18; + +export const WOKB_ADDRESS = + CLUSTER === "mainnet" + ? "0xe538905cf8410324e03A5A23C1c177a474D59b2b" + : CLUSTER === "testnet" + ? "0xa2aFfd8301BfB3c5b815829f2F509f053556D21B" + : "0xDDb64fE46a91D46ee29420539FC25FD07c5FEa3E"; +export const WOKB_DECIMALS = 18; export const ALGO_DECIMALS = 6;