Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e2fffc3
Add deposit element
shrinathprabhu Feb 18, 2026
5f13131
Try opportunities in monorepo
shrinathprabhu Feb 18, 2026
74b36f8
Fix css
shrinathprabhu Feb 18, 2026
551d3c7
Add logo to opportunity
shrinathprabhu Feb 18, 2026
6838777
use token address instead of token symbol for approval
shrinathprabhu Feb 18, 2026
0f66a5c
Use prefill for monadx
shrinathprabhu Feb 18, 2026
f735941
Don't disable on prefill
shrinathprabhu Feb 18, 2026
bedc7dc
Remove unused imports
shrinathprabhu Feb 18, 2026
dc37e76
Fix amount
shrinathprabhu Feb 18, 2026
dcf3101
Fix css
shrinathprabhu Feb 18, 2026
a26f15b
Auto trigger connect if not connected
shrinathprabhu Feb 18, 2026
101a0a1
Add opps in megaeth
shrinathprabhu Feb 20, 2026
4c12bdd
Add next
shrinathprabhu Feb 20, 2026
7641283
Add animated spinner
shrinathprabhu Feb 20, 2026
017812b
Add opportunity to megaeth
shrinathprabhu Feb 20, 2026
75a2daa
Update megaeth deposit element
shrinathprabhu Feb 20, 2026
93efd0d
Fix unused import
shrinathprabhu Feb 20, 2026
4fdf36e
Add update sdk for monad opps
shrinathprabhu Feb 25, 2026
21ce9e5
Update nexus sdk for swaps
shrinathprabhu Feb 27, 2026
5be404e
Try positions
shrinathprabhu Mar 3, 2026
5580d84
Log withdrawal amounts now
shrinathprabhu Mar 3, 2026
3ed2cf6
Add chain id
shrinathprabhu Mar 3, 2026
aad08dc
Display withdrawable
shrinathprabhu Mar 3, 2026
14ec577
Add refresh on deposit
shrinathprabhu Mar 3, 2026
fbcdc6f
Add write contract
shrinathprabhu Mar 3, 2026
b38e769
add switch chain logic
shrinathprabhu Mar 3, 2026
937bc9f
Add fixes
shrinathprabhu Mar 11, 2026
3604e8f
Log deposit widget props
shrinathprabhu Mar 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/megaeth/components.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"hooks": "@/hooks"
},
"registries": {
"@aceternity": "https://ui.aceternity.com/registry/{name}.json"
"@aceternity": "https://ui.aceternity.com/registry/{name}.json",
"@nexus-elements": "https://elements.nexus.availproject.org/r/{name}.json"
}
}
14 changes: 9 additions & 5 deletions apps/megaeth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
"preview": "vite preview --port 5173"
},
"dependencies": {
"@avail-project/nexus-core": "github:availproject/nexus-sdk#cca99c1a570a8598334e3e89453d39a27d70ede7",
"@avail-project/nexus-core": "^1.1.1",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-tooltip": "^1.2.8",
"@rainbow-me/rainbowkit": "^2.2.8",
"@tailwindcss/vite": "^4.1.16",
Expand All @@ -28,16 +30,18 @@
"decimal.js": "^10.6.0",
"lucide-react": "^0.544.0",
"motion": "^12.29.2",
"next": "^16.1.6",
"next-themes": "^0.4.6",
"posthog-js": "^1.336.4",
"react": "19.2.2",
"react-dom": "19.2.2",
"react-router-dom": "^7.13.0",
"sonner": "^2.0.7",
"tailwind-merge": "^3.3.1",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.13",
"viem": "^2.37.9",
"viem": "^2.45.1",
"vite-plugin-node-polyfills": "^0.24.0",
"wagmi": "^2.17.5"
"wagmi": "^2.19.5"
},
"devDependencies": {
"@eslint/js": "^9.36.0",
Expand Down
161 changes: 99 additions & 62 deletions apps/megaeth/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
import {
BrowserRouter,
Routes,
Route,
useNavigate,
useLocation,
} from "react-router-dom";
import Web3Provider from "@/providers/web3Provider";
import { Toaster } from "@/components/ui/sonner";
import Navbar from "@/components/navbar";
Expand All @@ -6,72 +13,102 @@ import FastBridgeShowcase from "@/components/fast-bridge-showcase";
import NexusProvider from "@/components/nexus/NexusProvider";
import config from "../config";
import { motion } from "motion/react";
import { NexusInitializer } from "@/components/NexusInitializer";
import { AnimatedTabs } from "@/components/ui/animated-tabs";
import Opportunities from "@/pages/Opportunities";
import { type NexusNetwork } from "@avail-project/nexus-core";

// @ts-expect-error - Environment is not exported from @avail-project/nexus-core
enum Environment {
FOLLY, // Dev with test-net tokens
CERISE, // Dev with main-net tokens
CORAL, // Test-net with main-net tokens
JADE, // Main-net with main-net tokens
}
function AppContent() {
const navigate = useNavigate();
const location = useLocation();

const tabs = [
{ id: "fastbridge", label: "Fast Bridge" },
{ id: "opportunities", label: "Opportunities" },
];

const activeTab = location.pathname.startsWith("/opportunities")
? "opportunities"
: "fastbridge";

const handleTabChange = (id: string) => {
if (id === "fastbridge") navigate("/");
else if (id === "opportunities") navigate("/opportunities");
};

export default function App() {
return (
<Web3Provider>
<NexusProvider
config={{
// network: {
// NETWORK_HINT: Environment.CERISE,
// COSMOS_GRPC_URL: "https://debugnet.availproject.org/grpc-web/",
// COSMOS_REST_URL: "https://debugnet.availproject.org",
// COSMOS_RPC_URL: "https://debugnet.availproject.org:26650",
// COSMOS_WS_URL: "wss://debugnet.availproject.org:26650/websocket",
// INTENT_EXPLORER_URL:
// "https://explorer.nexus-cerise.availproject.org",
// VSC_BASE_URL: "https://vsc-debugnet.availproject.org",
// VSC_WS_URL: "wss://vsc-debugnet.availproject.org",
// },
network: "mainnet",
debug: true,
}}
>
<div className="font-sans min-h-screen overflow-x-hidden w-full">
<Navbar />
<div className="min-h-full w-full max-w-full flex gap-4 md:gap-16 overflow-x-hidden">
<div
className="absolute inset-0 z-0"
style={{
background: `radial-gradient(125% 125% at 50% 10%, #fff 50%, ${config.primaryColor} 125%)`,
}}
<div className="font-sans min-h-screen overflow-x-hidden w-full flex flex-col">
<Navbar />
<div className="min-h-full flex-grow w-full max-w-full flex gap-4 md:gap-16 overflow-x-hidden relative">
<div
className="absolute inset-0 z-0"
style={{
background: `radial-gradient(125% 125% at 50% 10%, #fff 50%, ${config.primaryColor} 125%)`,
}}
/>
<main className="flex flex-col flex-1 min-w-0 max-w-full px-4 py-12 gap-8 relative z-10">
<div className="flex justify-center mb-8">
<AnimatedTabs
tabs={tabs}
activeTab={activeTab}
onTabChange={handleTabChange}
/>
<main className="flex flex-col flex-1 min-w-0 max-w-full px-4 py-12 gap-8">
<HeroSection />
<FastBridgeShowcase />
</main>
</div>
</div>
<Toaster />
<div className="sticky z-100 bottom-4 left-4 ml-4 flex flex-wrap items-center justify-start gap-3">
<motion.a
href="https://discord.com/invite/AvailProject"
target="_blank"
rel="noopener noreferrer"
className="inline-flex min-h-11 items-center rounded gap-2 border border-[#19191A] bg-transparent px-[14px] py-2 text-sm font-medium text-[#19191A] no-underline transition-[transform,background-color,border-color,box-shadow] duration-200 md:justify-self-start hover:bg-[#19191A] hover:text-white focus-visible:bg-[#19191A] focus-visible:text-white"
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.85 }}
whileHover={{
scale: 1.05,
y: -2,
}}
whileTap={{ scale: 0.98 }}
>
<span>
Reach out to us if <br /> you face any issues
</span>
</motion.a>
</div>
</NexusProvider>
</Web3Provider>

<Routes>
<Route
path="/"
element={
<>
<HeroSection />
<FastBridgeShowcase />
</>
}
/>
<Route path="/opportunities" element={<Opportunities />} />
</Routes>
</main>
</div>
</div>
);
}

export default function App() {
return (
<BrowserRouter basename="/megaeth">
<Web3Provider>
<NexusProvider
config={{
network: config.nexusNetwork as NexusNetwork,
debug: true,
}}
>
<NexusInitializer>
<AppContent />
<Toaster />
<div className="sticky z-100 bottom-4 left-4 ml-4 flex flex-wrap items-center justify-start gap-3">
<motion.a
href="https://discord.com/invite/AvailProject"
target="_blank"
rel="noopener noreferrer"
className="inline-flex min-h-11 items-center rounded gap-2 border border-[#19191A] bg-transparent px-[14px] py-2 text-sm font-medium text-[#19191A] no-underline transition-[transform,background-color,border-color,box-shadow] duration-200 md:justify-self-start hover:bg-[#19191A] hover:text-white focus-visible:bg-[#19191A] focus-visible:text-white"
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.85 }}
whileHover={{
scale: 1.05,
y: -2,
}}
whileTap={{ scale: 0.98 }}
>
<span>
Reach out to us if <br /> you face any issues
</span>
</motion.a>
</div>
</NexusInitializer>
</NexusProvider>
</Web3Provider>
</BrowserRouter>
);
}
102 changes: 102 additions & 0 deletions apps/megaeth/src/components/NexusInitializer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"use client";
import * as React from "react";
import type { EthereumProvider } from "@avail-project/nexus-core";
import { useAccount } from "wagmi";
import { useNexus } from "./nexus/NexusProvider";
import { toast } from "sonner";

/**
* NexusInitializer - Lives at App level to initialize Nexus once.
* This component handles Nexus SDK initialization/deinitialization
* based on wallet connection status. Since it's mounted at the App level,
* it won't re-initialize when routes change.
*/
export function NexusInitializer({ children }: { children: React.ReactNode }) {
const [loading, setLoading] = React.useState(false);
const [initError, setInitError] = React.useState<string | null>(null);
const { status, connector, address } = useAccount();
const { nexusSDK, handleInit, deinitializeNexus } = useNexus();
const prevAddressRef = React.useRef<string | undefined>(undefined);
const initializingRef = React.useRef(false);

const initializeNexus = React.useCallback(async () => {
// Prevent multiple simultaneous initialization attempts
if (loading || nexusSDK || initializingRef.current) return;

initializingRef.current = true;
setLoading(true);
setInitError(null);

try {
const provider = (await connector?.getProvider()) as EthereumProvider;
if (!provider) {
throw new Error("No provider available");
}

await handleInit(provider);
} catch (error) {
console.error("Nexus initialization failed:", error);
const errorMessage = (error as Error)?.message || "Unknown error";
setInitError(errorMessage);
toast.error(`Failed to initialize Nexus: ${errorMessage}`);
} finally {
setLoading(false);
initializingRef.current = false;
}
}, [connector, handleInit, loading, nexusSDK]);

// Handle wallet disconnection - clear Nexus state
React.useEffect(() => {
if (status === "disconnected" && nexusSDK) {
deinitializeNexus();
prevAddressRef.current = undefined;
location.reload();
} // reload page to free the resources
}, [status, nexusSDK, deinitializeNexus]);

// Handle account change - reinitialize Nexus when account address changes
React.useEffect(() => {
if (
status === "connected" &&
address &&
address !== prevAddressRef.current
) {
const previousAddress = prevAddressRef.current;
prevAddressRef.current = address;

// If account changed and Nexus is initialized, reinitialize with new account
if (nexusSDK && previousAddress !== undefined) {
deinitializeNexus().then(() => {
setTimeout(() => {
if (
address === prevAddressRef.current &&
!initializingRef.current
) {
initializeNexus();
}
}, 100);
});
}
} else if (status === "connected" && address && !prevAddressRef.current) {
prevAddressRef.current = address;
}
}, [status, nexusSDK, address, initializeNexus, deinitializeNexus]);

// Auto-initialize Nexus when wallet is connected (first time)
React.useEffect(() => {
if (
status === "connected" &&
!nexusSDK &&
!loading &&
!initError &&
address &&
!initializingRef.current
) {
initializeNexus();
}
}, [status, nexusSDK, initError, address, initializeNexus, loading]);

// Expose initialization state via context or just render children
// The actual loading UI is handled by PreviewPanel
return <>{children}</>;
}
Loading