diff --git a/assets/images/bsc.png b/assets/images/bsc.png new file mode 100644 index 000000000..27688c0af Binary files /dev/null and b/assets/images/bsc.png differ diff --git a/components/Coin/BalanceBreakdown.tsx b/components/Coin/BalanceBreakdown.tsx index 702f6fe44..4f79087be 100644 --- a/components/Coin/BalanceBreakdown.tsx +++ b/components/Coin/BalanceBreakdown.tsx @@ -2,7 +2,7 @@ import { useMemo } from 'react'; import { View } from 'react-native'; import { Image } from 'expo-image'; import { formatUnits } from 'viem'; -import { base, fuse, mainnet } from 'viem/chains'; +import { base, bsc, fuse, mainnet } from 'viem/chains'; import SavingsIcon from '@/assets/images/savings'; import WalletIcon from '@/assets/images/wallet'; @@ -36,12 +36,14 @@ const CHAIN_ICONS: Record = { [mainnet.id]: getAsset('images/eth.png'), [fuse.id]: getAsset('images/fuse-4x.png'), [base.id]: getAsset('images/base.png'), + [bsc.id]: getAsset('images/bsc.png'), }; const CHAIN_NAMES: Record = { [mainnet.id]: 'Ethereum', [fuse.id]: 'Fuse', [base.id]: 'Base', + [bsc.id]: 'BNB Chain', }; const BalanceBreakdown = ({ token, className }: BalanceBreakdownProps) => { diff --git a/constants/alchemy.ts b/constants/alchemy.ts index 85e9cad71..eae058897 100644 --- a/constants/alchemy.ts +++ b/constants/alchemy.ts @@ -1,17 +1,19 @@ -import { arbitrum, base, mainnet, polygon } from 'viem/chains'; +import { arbitrum, base, bsc, mainnet, polygon } from 'viem/chains'; import { EXPO_PUBLIC_ALCHEMY_API_KEY } from '@/lib/config'; /** * Alchemy is the primary on-chain data provider for these chains; * Blockscout is used as fallback on Alchemy failure. Fuse (122) is not - * supported by Alchemy and always uses Blockscout. + * supported by Alchemy and always uses Blockscout. BSC (56) is Alchemy-only + * (Blockscout has no BSC instance). */ export const ALCHEMY_SUPPORTED_CHAIN_IDS: ReadonlySet = new Set([ mainnet.id, base.id, polygon.id, arbitrum.id, + bsc.id, ]); export const ALCHEMY_CHAIN_URLS: Record = { @@ -19,6 +21,7 @@ export const ALCHEMY_CHAIN_URLS: Record = { [base.id]: `https://base-mainnet.g.alchemy.com/v2/${EXPO_PUBLIC_ALCHEMY_API_KEY}`, [polygon.id]: `https://polygon-mainnet.g.alchemy.com/v2/${EXPO_PUBLIC_ALCHEMY_API_KEY}`, [arbitrum.id]: `https://arb-mainnet.g.alchemy.com/v2/${EXPO_PUBLIC_ALCHEMY_API_KEY}`, + [bsc.id]: `https://bnb-mainnet.g.alchemy.com/v2/${EXPO_PUBLIC_ALCHEMY_API_KEY}`, }; export const isAlchemyChain = (chainId: number): boolean => diff --git a/constants/bridge.ts b/constants/bridge.ts index 9f2215bcd..aac272322 100644 --- a/constants/bridge.ts +++ b/constants/bridge.ts @@ -1,6 +1,6 @@ import { ImageSourcePropType } from 'react-native'; import { NATIVE_TOKEN_ADDRESS } from 'thirdweb'; -import { arbitrum, base, fuse, mainnet, polygon } from 'viem/chains'; +import { arbitrum, base, bsc, fuse, mainnet, polygon } from 'viem/chains'; import { WRAPPED_FUSE } from '@/constants/addresses'; @@ -8,6 +8,7 @@ type BridgeToken = { name?: string; fullName?: string; address: string; + decimals?: number; icon?: ImageSourcePropType; version?: string; isPermit?: boolean; @@ -155,9 +156,24 @@ export const BRIDGE_TOKENS: BridgeTokens = { }, name: 'Fuse', icon: require('@/assets/images/fuse.png'), - sort: 5, + sort: 6, bridgeSpeed: 0, }, + [bsc.id]: { + tokens: { + USDC: { + name: 'USDC', + fullName: 'Binance-Peg USD Coin', + address: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d', + decimals: 18, + isPermit: false, + }, + }, + name: 'BNB Chain', + icon: require('@/assets/images/bsc.png'), + sort: 5, + bridgeSpeed: 2, + }, }; export const getUsdcAddress = (chainId: number) => { diff --git a/hooks/useDepositFromEOA.ts b/hooks/useDepositFromEOA.ts index 544b88ab8..87db4382c 100644 --- a/hooks/useDepositFromEOA.ts +++ b/hooks/useDepositFromEOA.ts @@ -425,7 +425,13 @@ const useDepositFromEOA = ( }, }); - const amountWei = parseUnits(amount, 6); + // Source token decimals (defaults to 6). Some chains' USDC is not 6 + // decimals (e.g. Binance-Peg USDC on BNB Chain is 18), so derive it from + // the bridge config rather than hardcoding. + const srcDecimals = + Object.values(BRIDGE_TOKENS[srcChainId]?.tokens ?? {}).find(t => t.name === token) + ?.decimals ?? 6; + const amountWei = parseUnits(amount, srcDecimals); let txHash: `0x${string}` | undefined; let transaction: { transactionHash: `0x${string}` } | undefined = { diff --git a/lib/assets.ts b/lib/assets.ts index 0461a6b63..7a477c94e 100644 --- a/lib/assets.ts +++ b/lib/assets.ts @@ -85,6 +85,7 @@ export const ASSETS = { module: require('@/assets/images/brl-fiat-currency.tsx'), hash: '75a2ebe8', }, + 'images/bsc.png': { module: require('@/assets/images/bsc.png'), hash: '4135f6a8' }, 'images/buy_crypto.png': { module: require('@/assets/images/buy_crypto.png'), hash: 'a072a946' }, 'images/card-earn.png': { module: require('@/assets/images/card-earn.png'), hash: '3e55e4d1' }, 'images/card-effortless.png': { diff --git a/lib/thirdweb.ts b/lib/thirdweb.ts index 757fab5d6..91839f6a5 100644 --- a/lib/thirdweb.ts +++ b/lib/thirdweb.ts @@ -1,5 +1,5 @@ import { createThirdwebClient, defineChain } from 'thirdweb'; -import { arbitrum, base, mainnet, polygon } from 'thirdweb/chains'; +import { arbitrum, base, bsc, mainnet, polygon } from 'thirdweb/chains'; import { darkTheme } from 'thirdweb/react'; import { createWallet } from 'thirdweb/wallets'; @@ -50,7 +50,7 @@ const fuse = defineChain({ }, }); -const chains = [mainnet, fuse, polygon, base, arbitrum]; +const chains = [mainnet, fuse, polygon, base, arbitrum, bsc]; export const getChain = (chainId: number) => { return chains.find(chain => chain.id === chainId);