Bridge assets across Ethereum, Polygon, and Arbitrum. Track everything in one dashboard.
Universal DeFi Hub is a cross-chain bridge platform that lets you move ETH between Ethereum Sepolia, Polygon Amoy, and Arbitrum Sepolia testnets while tracking your entire multi-chain portfolio in one place.
The problem? Managing assets across multiple chains is a nightmare. You're constantly switching networks in MetaMask, losing track of which wallet has what, and manually checking balances on different block explorers. It's frustrating and error-prone.
I built a solution that feels like using a regular app instead of juggling blockchain infrastructure. Connect your wallet once, and you immediately see your balances across all three chains in a unified dashboard. Want to move 1 ETH from Sepolia to Arbitrum? Just select the chains, enter the amount, and bridge it. The interface handles everything - you get real-time transaction status, automatic balance updates, and a complete history of every bridge you've done.
Under the hood, I'm using wagmi for multi-chain balance fetching, ENS for human-readable addresses (no more copying 0x addresses), and localStorage for transaction history. The bridge currently runs in demo mode for the hackathon, sending transactions to a burn address on the source chain to simulate cross-chain transfers without requiring deployed bridge contracts.
The UI is clean and actually makes sense - your total portfolio value at the top, individual chain cards showing balances, a bridge interface that doesn't require a PhD to understand, and transaction history so you can see what you've moved and when.
I also integrated Sui wallet support to show I'm not limited to EVM chains. Users can connect their Sui wallet alongside MetaMask and see their SUI balance in the same dashboard.
This isn't trying to be everything to everyone. It's focused on solving one problem well: making multi-chain asset management less painful. No confusing menus, no hidden fees, no requiring you to understand the technical details of how bridges work. Just connect, bridge, and track your stuff.
Built for developers and DeFi users who are tired of the current multi-chain experience sucking.
I built this entirely in React + TypeScript with Vite as the build tool. The frontend uses Tailwind CSS for styling because I wanted to move fast without fighting with CSS frameworks.
For blockchain interactions, I'm using wagmi v3 which honestly made multi-chain support way easier than I expected. The core trick is using wagmi's useBalance hook with different chainId parameters - I can fetch balances from Sepolia, Polygon Amoy, and Arbitrum Sepolia simultaneously just by calling the same hook three times with different chain IDs. This happens in a custom useMultiChainBalance hook that aggregates everything and calculates the total portfolio value.
The bridge interface is where things got interesting. I wanted real cross-chain transfers but deploying actual bridge contracts (lock/unlock or burn/mint mechanisms) would've taken the entire hackathon. So I built a demo mode that sends ETH to the burn address (0x000000000000000000000000000000000000dEaD) on the source chain. It's not a real bridge, but it lets me demonstrate the UX flow - transaction status modals, balance updates, history tracking - without the complexity of cross-chain message passing.
For transaction tracking, I'm using localStorage with a custom bridgeService that saves every transaction with its hash, from/to chains, amount, timestamp, and status. The history page reads from this and links to the appropriate block explorers (Sepolia Etherscan, Polygon Amoy scan, Arbiscan). I keep max 50 transactions to avoid filling up localStorage.
ENS integration was surprisingly straightforward. I created a custom useENS hook that uses viem's createPublicClient pointing at Ethereum mainnet (you need mainnet for ENS resolution even when your app runs on testnets). It does getEnsName lookups and caches results. The ENSName component shows the .eth name with a tooltip displaying the full address on hover, and falls back to shortened addresses (0x1234...5678) if no ENS name exists.
The Sui integration was trickier. Sui uses a completely different wallet system (@mysten/dapp-kit) and runs on a separate VM, so I had to set up parallel provider trees in main.tsx. There's a SuiClientProvider wrapping a WalletProvider for Sui stuff, while wagmi handles the EVM chains. The Sui balance hook converts from MIST to SUI (divide by 1e9) and the SuiCard component manages connection state separately from MetaMask. Users can have both wallets connected simultaneously.
One hacky thing I did: the transaction status modal has a fake loading animation that runs for ~30 seconds to simulate cross-chain confirmation time, even though in demo mode the transaction completes instantly. This makes the UX feel more realistic and gives users visual feedback that something's happening.
I tried integrating LI.FI SDK for real cross-chain bridging but ran into testnet support issues - their API returned empty routes for Sepolia/Polygon Amoy/Arbitrum Sepolia pairs. Turns out LI.FI works great on mainnets but the specific testnets I picked aren't fully supported. I kept the demo mode instead of switching testnets because I'd already built the entire UI around these three chains.
The wagmi config was also a pain point. I had to manually define the testnet chain objects because wagmi's built-in chain list doesn't include all the testnets I needed. Each chain needs an ID, name, RPC URL, and block explorer URL. I'm using public RPCs which sometimes rate limit, but it's fine for a hackathon demo.
For the dashboard, I implemented a manual refresh button alongside automatic fetching because wagmi's useBalance has a default staleTime. Sometimes users bridge assets and want to see updated balances immediately without waiting for the automatic refetch interval.
The styling gradient background (gray-900 via purple-900) was intentional - I wanted it to feel premium and modern without looking like every other DeFi app. The purple accent color carries through buttons, borders, and highlights to create visual consistency.
One thing that almost broke everything: I tried adding Arc (Circle's L1) as a fourth chain and it completely broke the balance display for all chains. The Arc balance hook returned a different data structure than wagmi's useBalance, so when the Dashboard tried to read chain.data.data.formatted it was getting undefined for Arc and then React was having a meltdown. I had to revert that entire integration.
Testing was mostly manual - connecting MetaMask, switching networks, executing bridge transactions, checking that balances update, verifying transaction history persistence across page refreshes. I tested on multiple browsers (Chrome, Brave) to make sure the wallet connections worked everywhere.
The whole thing runs client-side only, no backend needed. All state lives in React hooks or localStorage. This makes deployment dead simple - just build and throw it on Vercel or any static host.
If I had more time, I would've integrated real bridging via LI.FI (once they support my testnets) or deployed my own simple bridge contracts. But for a week-long hackathon, getting the UX right and making it feel polished was more important than having every feature be production-ready.

