diff --git a/README.md b/README.md index e36f72c5b..d0302309a 100644 --- a/README.md +++ b/README.md @@ -208,6 +208,7 @@ By default, it offers its full built-in list for both `mainnet` and `testnet`: | optimism | optimismgoerli, optimism_sepolia | | scroll | scroll | | blast | blast | +| xlayer | xlayer | > Osmosis support is in beta, reach out to a Wormhole contributor for early access. diff --git a/package-lock.json b/package-lock.json index 6051bb9a1..16717dfa4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16737,6 +16737,22 @@ } } }, + "node_modules/@wormhole-foundation/sdk-icons": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@wormhole-foundation/sdk-icons/-/sdk-icons-0.6.8.tgz", + "integrity": "sha512-3BGPq47VkWzluiN1QqzHXVNI9oP1srh/kl1ZNDXyiRPVHXDYJ/36SxA8/ab7Rs78o2ZHDDLJ52vPokNMKelXpA==", + "dependencies": { + "@wormhole-foundation/sdk-base": "0.6.8" + } + }, + "node_modules/@wormhole-foundation/sdk-icons/node_modules/@wormhole-foundation/sdk-base": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@wormhole-foundation/sdk-base/-/sdk-base-0.6.8.tgz", + "integrity": "sha512-8F6B9I60SEI2lQDAoPB6bB6NWLFso/hghfD/Zfxrrgu+LumwKIejgvsiOudVRjL2nvqUJJ/lIodgSBckpPW8Kg==", + "dependencies": { + "@scure/base": "^1.1.3" + } + }, "node_modules/@wormhole-foundation/sdk-solana": { "version": "0.7.0-beta.3", "resolved": "https://registry.npmjs.org/@wormhole-foundation/sdk-solana/-/sdk-solana-0.7.0-beta.3.tgz", @@ -17618,23 +17634,6 @@ "pbts": "bin/pbts" } }, - "node_modules/@xlabs-libs/wallet-aggregator-evm": { - "version": "0.0.1-alpha.40", - "resolved": "https://registry.npmjs.org/@xlabs-libs/wallet-aggregator-evm/-/wallet-aggregator-evm-0.0.1-alpha.40.tgz", - "integrity": "sha512-NSkSA2WAAKHru7RJULaFe1ZWQ271ZcFYWUNYzYIUXQBRheiezJ5J8xobAjUrCoMyT6e6qWBsjrVTG6+4Umcz5w==", - "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/providers": "^5.7.2", - "@wagmi/core": "^1.4.13", - "@web3modal/standalone": "^2.2.1", - "@xlabs-libs/wallet-aggregator-core": "^0.0.1-alpha.19", - "ethers": "^5.7.2", - "versions": "^10.4.1", - "viem": "^1.20.3" - } - }, "node_modules/@xlabs-libs/wallet-aggregator-sei": { "version": "0.0.1-alpha.14", "resolved": "https://registry.npmjs.org/@xlabs-libs/wallet-aggregator-sei/-/wallet-aggregator-sei-0.0.1-alpha.14.tgz", @@ -34212,7 +34211,7 @@ "version": "0.1.0-beta.0", "license": "ISC", "dependencies": { - "@certusone/wormhole-sdk": "^0.10.15", + "@certusone/wormhole-sdk": "^0.10.16", "@cosmjs/cosmwasm-stargate": "^0.31.3", "@cosmjs/proto-signing": "^0.31.3", "@cosmjs/stargate": "^0.31.3", @@ -34244,6 +34243,44 @@ "typescript": "^5.3.3" } }, + "sdk/node_modules/@certusone/wormhole-sdk": { + "version": "0.10.16", + "resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.10.16.tgz", + "integrity": "sha512-DRXzRZnsjHeBjARZa9MZ3lQBi95P2afv+7e2cjQLqePhEZzhvCRJY5jaEKuvN+vttZFoj72L6ugBvOZFw7Tm5Q==", + "dependencies": { + "@certusone/wormhole-sdk-proto-web": "0.0.7", + "@certusone/wormhole-sdk-wasm": "^0.0.1", + "@coral-xyz/borsh": "0.2.6", + "@mysten/sui.js": "0.32.2", + "@project-serum/anchor": "^0.25.0", + "@solana/spl-token": "^0.3.5", + "@solana/web3.js": "^1.66.2", + "@terra-money/terra.js": "3.1.9", + "@xpla/xpla.js": "^0.2.1", + "algosdk": "^2.4.0", + "aptos": "1.5.0", + "axios": "^0.24.0", + "bech32": "^2.0.0", + "binary-parser": "^2.2.1", + "bs58": "^4.0.1", + "elliptic": "^6.5.4", + "js-base64": "^3.6.1", + "near-api-js": "^1.0.0" + }, + "optionalDependencies": { + "@injectivelabs/networks": "1.10.12", + "@injectivelabs/sdk-ts": "1.10.72", + "@injectivelabs/utils": "1.10.12" + } + }, + "sdk/node_modules/@certusone/wormhole-sdk/node_modules/axios": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "dependencies": { + "follow-redirects": "^1.14.4" + } + }, "sdk/node_modules/@types/node": { "version": "16.18.68", "dev": true, @@ -34338,11 +34375,12 @@ "@wormhole-foundation/sdk": "^0.7.0-beta.3", "@wormhole-foundation/sdk-definitions": "^0.7.0-beta.3", "@wormhole-foundation/sdk-definitions-ntt": "^0.0.1-beta.5", + "@wormhole-foundation/sdk-icons": "^0.6.8", "@xlabs-libs/wallet-aggregator-aptos": "^0.0.1-alpha.14", "@xlabs-libs/wallet-aggregator-core": "^0.0.1-alpha.18", "@xlabs-libs/wallet-aggregator-cosmos": "^0.0.1-alpha.14", "@xlabs-libs/wallet-aggregator-cosmos-evm": "^0.0.1-alpha.6", - "@xlabs-libs/wallet-aggregator-evm": "^0.0.1-alpha.39", + "@xlabs-libs/wallet-aggregator-evm": "^0.0.1-alpha.42", "@xlabs-libs/wallet-aggregator-sei": "^0.0.1-alpha.14", "@xlabs-libs/wallet-aggregator-solana": "^0.0.1-alpha.15", "@xlabs-libs/wallet-aggregator-sui": "^0.0.1-alpha.10", @@ -34385,6 +34423,23 @@ "react": "^18.2.0", "react-dom": "^18.2.0" } + }, + "wormhole-connect/node_modules/@xlabs-libs/wallet-aggregator-evm": { + "version": "0.0.1-alpha.42", + "resolved": "https://registry.npmjs.org/@xlabs-libs/wallet-aggregator-evm/-/wallet-aggregator-evm-0.0.1-alpha.42.tgz", + "integrity": "sha512-BojrrSmdsx03nRaB6TSVqcETZbC361+RByXhiKbe0VxP38ZT4DkNJvpVnfHIi3q0c6pHmgBdB6rgTsJw3Le4Mw==", + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/providers": "^5.7.2", + "@wagmi/core": "^1.4.13", + "@web3modal/standalone": "^2.2.1", + "@xlabs-libs/wallet-aggregator-core": "^0.0.1-alpha.19", + "ethers": "^5.7.2", + "versions": "^10.4.1", + "viem": "^1.20.3" + } } } } diff --git a/sdk/package.json b/sdk/package.json index bac24a7a6..678e48d11 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -12,7 +12,7 @@ }, "sideEffects": false, "dependencies": { - "@certusone/wormhole-sdk": "^0.10.15", + "@certusone/wormhole-sdk": "^0.10.16", "@cosmjs/cosmwasm-stargate": "^0.31.3", "@cosmjs/proto-signing": "^0.31.3", "@cosmjs/stargate": "^0.31.3", diff --git a/sdk/src/config/MAINNET.ts b/sdk/src/config/MAINNET.ts index dd7e30773..81ddfbebe 100644 --- a/sdk/src/config/MAINNET.ts +++ b/sdk/src/config/MAINNET.ts @@ -23,6 +23,7 @@ export const MAINNET_CHAINS = { sei: 32, scroll: 34, blast: 36, + xlayer: 37, wormchain: 3104, osmosis: 20, cosmoshub: 4000, @@ -297,6 +298,16 @@ const MAINNET: { [chain in MainnetChainName]: ChainConfig } = { finalityThreshold: 0, nativeTokenDecimals: 18, }, + xlayer: { + key: 'xlayer', + id: 37, + context: Context.ETH, + contracts: { + ...CONTRACTS.MAINNET.xlayer, + }, + finalityThreshold: 0, + nativeTokenDecimals: 18, + }, wormchain: { context: Context.COSMOS, key: 'wormchain', @@ -384,6 +395,7 @@ const MAINNET_CONFIG: WormholeConfig = { klaytn: 'https://rpc.ankr.com/klaytn', scroll: 'https://rpc.ankr.com/scroll', blast: 'https://rpc.ankr.com/blast', + xlayer: 'https://rpc.xlayer.tech', }, rest: { sei: '', diff --git a/sdk/src/config/TESTNET.ts b/sdk/src/config/TESTNET.ts index 320ea369e..1bd3a1150 100644 --- a/sdk/src/config/TESTNET.ts +++ b/sdk/src/config/TESTNET.ts @@ -23,6 +23,7 @@ export const TESTNET_CHAINS = { sei: 32, scroll: 34, blast: 36, + xlayer: 37, wormchain: 3104, osmosis: 20, cosmoshub: 4000, @@ -283,6 +284,16 @@ const TESTNET: { [chain in TestnetChainName]: ChainConfig } = { finalityThreshold: 0, nativeTokenDecimals: 18, }, + xlayer: { + key: 'xlayer', + id: 37, + context: Context.ETH, + contracts: { + ...CONTRACTS.TESTNET.xlayer, + }, + finalityThreshold: 0, + nativeTokenDecimals: 18, + }, wormchain: { context: Context.COSMOS, key: 'wormchain', @@ -422,6 +433,7 @@ const TESTNET_CONFIG: WormholeConfig = { optimism_sepolia: 'https://sepolia.optimism.io', scroll: 'https://rpc.ankr.com/scroll_sepolia_testnet', blast: 'https://rpc.ankr.com/blast_testnet_sepolia', + xlayer: 'https://testrpc.xlayer.tech', }, rest: { sei: 'https://rest.atlantic-2.seinetwork.io', diff --git a/wormhole-connect/package.json b/wormhole-connect/package.json index 90b89f93d..b88df3702 100644 --- a/wormhole-connect/package.json +++ b/wormhole-connect/package.json @@ -41,11 +41,12 @@ "@wormhole-foundation/sdk": "^0.7.0-beta.3", "@wormhole-foundation/sdk-definitions": "^0.7.0-beta.3", "@wormhole-foundation/sdk-definitions-ntt": "^0.0.1-beta.5", + "@wormhole-foundation/sdk-icons": "^0.6.8", "@xlabs-libs/wallet-aggregator-aptos": "^0.0.1-alpha.14", "@xlabs-libs/wallet-aggregator-core": "^0.0.1-alpha.18", "@xlabs-libs/wallet-aggregator-cosmos": "^0.0.1-alpha.14", "@xlabs-libs/wallet-aggregator-cosmos-evm": "^0.0.1-alpha.6", - "@xlabs-libs/wallet-aggregator-evm": "^0.0.1-alpha.39", + "@xlabs-libs/wallet-aggregator-evm": "^0.0.1-alpha.42", "@xlabs-libs/wallet-aggregator-sei": "^0.0.1-alpha.14", "@xlabs-libs/wallet-aggregator-solana": "^0.0.1-alpha.15", "@xlabs-libs/wallet-aggregator-sui": "^0.0.1-alpha.10", diff --git a/wormhole-connect/src/config/mainnet/chains.ts b/wormhole-connect/src/config/mainnet/chains.ts index 2eafb91e2..8c0ce0113 100644 --- a/wormhole-connect/src/config/mainnet/chains.ts +++ b/wormhole-connect/src/config/mainnet/chains.ts @@ -232,4 +232,15 @@ export const MAINNET_CHAINS: ChainsConfig = { automaticRelayer: false, maxBlockSearch: 2000, }, + xlayer: { + ...chains.xlayer!, + displayName: 'X Layer', + explorerUrl: 'https://www.okx.com/web3/explorer/xlayer/', + explorerName: 'OKX Explorer', + gasToken: 'OKB', + chainId: 196, + icon: Icon.XLAYER, + automaticRelayer: false, + maxBlockSearch: 2000, + }, }; diff --git a/wormhole-connect/src/config/mainnet/gasEstimates.ts b/wormhole-connect/src/config/mainnet/gasEstimates.ts index 9dafe8079..f8eb5e7aa 100644 --- a/wormhole-connect/src/config/mainnet/gasEstimates.ts +++ b/wormhole-connect/src/config/mainnet/gasEstimates.ts @@ -332,4 +332,11 @@ export const MAINNET_GAS_ESTIMATES: GasEstimates = { claim: 300000, }, }, + xlayer: { + [Route.Bridge]: { + sendNative: 100000, + sendToken: 100000, + claim: 300000, + }, + }, }; diff --git a/wormhole-connect/src/config/mainnet/rpcs.ts b/wormhole-connect/src/config/mainnet/rpcs.ts index d1cc6fa26..a177cd349 100644 --- a/wormhole-connect/src/config/mainnet/rpcs.ts +++ b/wormhole-connect/src/config/mainnet/rpcs.ts @@ -25,6 +25,7 @@ const { REACT_APP_APTOS_GRAPHQL, REACT_APP_SCROLL_RPC, REACT_APP_BLAST_RPC, + REACT_APP_XLAYER_RPC, } = import.meta.env; export const MAINNET_RPC_MAPPING = { @@ -50,6 +51,7 @@ export const MAINNET_RPC_MAPPING = { ...populateRpcField('klaytn', REACT_APP_KLAYTN_RPC), ...populateRpcField('scroll', REACT_APP_SCROLL_RPC), ...populateRpcField('blast', REACT_APP_BLAST_RPC), + ...populateRpcField('xlayer', REACT_APP_XLAYER_RPC), }; export const MAINNET_REST_MAPPING = { diff --git a/wormhole-connect/src/config/mainnet/tokens.ts b/wormhole-connect/src/config/mainnet/tokens.ts index 5afcce135..4a85a4d18 100644 --- a/wormhole-connect/src/config/mainnet/tokens.ts +++ b/wormhole-connect/src/config/mainnet/tokens.ts @@ -2775,4 +2775,31 @@ export const MAINNET_TOKENS: TokensConfig = { default: 8, }, }, + OKB: { + key: 'OKB', + symbol: 'OKB', + nativeChain: 'xlayer', + icon: Icon.XLAYER, + coinGeckoId: 'okb', + decimals: { + Ethereum: 18, + default: 8, + }, + wrappedAsset: 'WOKB', + }, + WOKB: { + key: 'WOKB', + symbol: 'WOKB', + nativeChain: 'xlayer', + icon: Icon.XLAYER, + tokenId: { + chain: 'xlayer', + address: '0xe538905cf8410324e03A5A23C1c177a474D59b2b', + }, + coinGeckoId: 'okb', + decimals: { + Ethereum: 18, + default: 8, + }, + }, }; diff --git a/wormhole-connect/src/config/testnet/chains.ts b/wormhole-connect/src/config/testnet/chains.ts index e00a483e8..95123240f 100644 --- a/wormhole-connect/src/config/testnet/chains.ts +++ b/wormhole-connect/src/config/testnet/chains.ts @@ -297,4 +297,15 @@ export const TESTNET_CHAINS: ChainsConfig = { automaticRelayer: false, maxBlockSearch: 2000, }, + xlayer: { + ...chains.xlayer!, + displayName: 'X Layer', + explorerUrl: 'https://www.okx.com/web3/explorer/xlayer-test/', + explorerName: 'OKX Explorer', + gasToken: 'OKB', + chainId: 195, + icon: Icon.XLAYER, + automaticRelayer: false, + maxBlockSearch: 2000, + }, }; diff --git a/wormhole-connect/src/config/testnet/gasEstimates.ts b/wormhole-connect/src/config/testnet/gasEstimates.ts index b681ac726..58c85bc58 100644 --- a/wormhole-connect/src/config/testnet/gasEstimates.ts +++ b/wormhole-connect/src/config/testnet/gasEstimates.ts @@ -330,4 +330,11 @@ export const TESTNET_GAS_ESTIMATES: GasEstimates = { claim: 200000, }, }, + xlayer: { + [Route.Bridge]: { + sendNative: 100000, + sendToken: 150000, + claim: 200000, + }, + }, }; diff --git a/wormhole-connect/src/config/testnet/rpcs.ts b/wormhole-connect/src/config/testnet/rpcs.ts index 6f59634fb..ab5847281 100644 --- a/wormhole-connect/src/config/testnet/rpcs.ts +++ b/wormhole-connect/src/config/testnet/rpcs.ts @@ -30,6 +30,7 @@ const { REACT_APP_APTOS_TESTNET_GRAPHQL, REACT_APP_SCROLL_TESTNET_RPC, REACT_APP_BLAST_TESTNET_RPC, + REACT_APP_XLAYER_TESTNET_RPC, } = import.meta.env; export const TESTNET_RPC_MAPPING = { @@ -60,6 +61,7 @@ export const TESTNET_RPC_MAPPING = { ...populateRpcField('klaytn', REACT_APP_KLAYTN_TESTNET_RPC), ...populateRpcField('scroll', REACT_APP_SCROLL_TESTNET_RPC), ...populateRpcField('blast', REACT_APP_BLAST_TESTNET_RPC), + ...populateRpcField('xlayer', REACT_APP_XLAYER_TESTNET_RPC), }; export const TESTNET_REST_MAPPING = { diff --git a/wormhole-connect/src/config/testnet/tokens.ts b/wormhole-connect/src/config/testnet/tokens.ts index e5e0cdc40..988e73eb1 100644 --- a/wormhole-connect/src/config/testnet/tokens.ts +++ b/wormhole-connect/src/config/testnet/tokens.ts @@ -2320,4 +2320,31 @@ export const TESTNET_TOKENS: TokensConfig = { default: 8, }, }, + OKB: { + key: 'OKB', + symbol: 'OKB', + nativeChain: 'xlayer', + icon: Icon.XLAYER, + coinGeckoId: 'okb', + decimals: { + Ethereum: 18, + default: 8, + }, + wrappedAsset: 'WOKB', + }, + WOKB: { + key: 'WOKB', + symbol: 'WOKB', + nativeChain: 'xlayer', + icon: Icon.XLAYER, + tokenId: { + chain: 'xlayer', + address: '0xa2aFfd8301BfB3c5b815829f2F509f053556D21B', + }, + coinGeckoId: 'okb', + decimals: { + Ethereum: 18, + default: 8, + }, + }, }; diff --git a/wormhole-connect/src/config/types.ts b/wormhole-connect/src/config/types.ts index 938b3e5c3..559af72a1 100644 --- a/wormhole-connect/src/config/types.ts +++ b/wormhole-connect/src/config/types.ts @@ -46,6 +46,7 @@ export enum Icon { 'NTT', 'SCROLL', 'BLAST', + 'XLAYER', } export enum Route { diff --git a/wormhole-connect/src/icons/TokenIcons.tsx b/wormhole-connect/src/icons/TokenIcons.tsx index f924f49de..74c3669ff 100644 --- a/wormhole-connect/src/icons/TokenIcons.tsx +++ b/wormhole-connect/src/icons/TokenIcons.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { makeStyles } from 'tss-react/mui'; +import { chainToIcon } from '@wormhole-foundation/sdk-icons'; + import { CENTER } from 'utils/style'; import { Icon } from 'config/types'; import WBTC from './Tokens/WBTC'; @@ -86,6 +88,7 @@ const iconMap: { [key in Icon]: React.JSX.Element } = { [Icon.NTT]: NTT(), [Icon.SCROLL]: SCROLL(), [Icon.BLAST]: BLAST(), + [Icon.XLAYER]: , }; function isBuiltinIcon(icon?: Icon | string): icon is Icon { diff --git a/wormhole-connect/src/routes/bridge/bridge.ts b/wormhole-connect/src/routes/bridge/bridge.ts index 7fb51b7f9..2cd5e1484 100644 --- a/wormhole-connect/src/routes/bridge/bridge.ts +++ b/wormhole-connect/src/routes/bridge/bridge.ts @@ -61,6 +61,13 @@ export class BridgeRoute extends BaseRoute { ) return false; + // Special case: OKB cannot be sent on xlayer + if ( + (sourceToken === 'OKB' || sourceToken === 'native') && + sourceChain === 'xlayer' + ) + return false; + if (!!sourceTokenConfig.tokenId && sourceToken === destToken) return true; if ( !sourceTokenConfig.tokenId &&