Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2,267 changes: 1,552 additions & 715 deletions package-lock.json

Large diffs are not rendered by default.

30 changes: 26 additions & 4 deletions src/app/views/trade/components/SwapCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,29 @@ import { useTokenBalance } from "@/hooks/useTokenBalance";
import QuoteSkeleton from "./QuoteSkeleton";
import { getTokens, convertToUniToken } from "../../../../config/token";
import toast from "react-hot-toast";
import { Shield } from "lucide-react";
import { Shield, AlertTriangle } from "lucide-react";
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/TabsComponents";
import { useTxToasts } from "@/hooks/useTxToasts";
import { useChainId } from "wagmi";
import { getExplorerUrl, getTxnExplorerUrl } from "@/utils/explorer";
import { SwapCardProps } from "../SwapUI";
import { useQueryClient } from "@tanstack/react-query";
import { useRefreshContext } from "@/context/RefreshContext";
import { useValidChain } from "@/hooks/useValidChain";
import { defaultChain } from "@/lib/chains.config";


export default function SwapCard({
initialAmount = "",
onAmountChange,
}: SwapCardProps) {
const { address } = useAccount();
const chainId = useChainId();
// Use validated chain instead of direct useChainId
const { chainId, isMismatch } = useValidChain();
const queryClient = useQueryClient();
const { triggerRefresh, startPolling } = useRefreshContext();
const { trackSwapInitiated, trackSwapCompleted } = useAnalytics();
Expand All @@ -42,6 +45,8 @@ export default function SwapCard({
const [fromToken, setFromToken] = useState<Token>(tokenListCurrency[0]);
const [toToken, setToToken] = useState<Token>(tokenListRWAList[0]);



const [fromAmount, setFromAmount] = useState<string>(initialAmount);
const [toAmount, setToAmount] = useState<string>("");

Expand Down Expand Up @@ -449,7 +454,24 @@ export default function SwapCard({
const { text: buttonText, disabled: buttonDisabled } = getButtonState();

return (
<div className="w-full rounded-2xl bg-[#222325] p-6 shadow-xl border border-[#303136]">
<div className="w-full rounded-2xl bg-[#222325] p-6 shadow-xl border border-[#303136]" id="swap">
{/* Network Mismatch Warning */}
{isMismatch && (
<div className="rounded-xl p-4 mb-4 bg-yellow-500/10 border border-yellow-500/30">
<div className="flex items-start space-x-3">
<AlertTriangle className="h-5 w-5 text-yellow-500 flex-shrink-0 mt-0.5" />
<div className="flex-1">
<h4 className="text-sm font-medium text-yellow-500 mb-1">
Unsupported Network
</h4>
<p className="text-xs text-yellow-200/80">
You&apos;re connected to an unsupported network. Please switch to{" "}
<strong>{defaultChain.name}</strong> to continue trading.
</p>
</div>
</div>
</div>
)}
{/* Buy/Sell Tabs */}
<Tabs
defaultValue="buy"
Expand Down
15 changes: 12 additions & 3 deletions src/components/ConnectButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import React from "react";
import Image from "next/image";
import { ConnectButton } from "@rainbow-me/rainbowkit";
import { isDevelopment } from "@/lib/chains.config";

export const CustomConnectButton: React.FC = () => {
return (
Expand Down Expand Up @@ -68,7 +69,8 @@ export const CustomConnectButton: React.FC = () => {
type="button"
className="flex items-center gap-2 px-4 py-2 bg-red-600 text-white font-medium text-sm rounded-md hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
>
Wrong network
<span className="hidden sm:inline">Wrong network</span>
<span className="sm:hidden">Wrong net</span>
</button>
);
}
Expand Down Expand Up @@ -103,7 +105,14 @@ export const CustomConnectButton: React.FC = () => {
)}
</div>
)}
<span className="hidden sm:inline">{chain.name}</span>
<span className="hidden sm:inline">
{chain.name}
{isDevelopment && (
<span className="ml-1 text-yellow-400 text-xs">
(DEV)
</span>
)}
</span>
</button>

<button
Expand Down Expand Up @@ -136,4 +145,4 @@ export const CustomConnectButton: React.FC = () => {
}}
</ConnectButton.Custom>
);
};
};
8 changes: 5 additions & 3 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import Link from "next/link";
import { useChainId } from "wagmi";

const BASE_SEPOLIA_CHAIN_ID = 84532;
import { BASE_SEPOLIA_CHAIN_ID, isDevelopment } from "@/lib/chains.config";

export function Footer() {
const chainId = useChainId();
const isBaseSepolia = chainId === BASE_SEPOLIA_CHAIN_ID;

// Only show faucet link in development mode when connected to Base Sepolia
const showFaucet = isDevelopment && isBaseSepolia;

return (
<footer className="border-t border-white/10">
<div className="max-w-7xl mx-auto px-6 py-6">
Expand Down Expand Up @@ -43,7 +45,7 @@ export function Footer() {
>
Github
</Link>
{isBaseSepolia && (
{showFaucet && (
<Link
href="/faucet"
className="text-sm text-gray-400 hover:underline"
Expand Down
39 changes: 21 additions & 18 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,10 @@ export const Navbar: React.FC = () => {
onMouseLeave={handleMouseLeave}
>
<button
className={`px-3 py-2 text-sm font-medium transition-colors ${
isMint || isUnderwrite
className={`px-3 py-2 text-sm font-medium transition-colors ${isMint || isUnderwrite
? "text-white"
: "text-white/50 hover:text-white"
}`}
}`}
>
Pool
</button>
Expand All @@ -88,23 +87,30 @@ export const Navbar: React.FC = () => {
{isPoolHovered && (
<div className="absolute top-full left-0 pt-1">
<div className="bg-[#222325] rounded-lg shadow-xl border border-[#303136] p-2 min-w-[160px]">
<Link
href="/#swap"
className={`block mt-1 px-3 py-2 text-sm font-medium rounded-md transition-colors ${isUnderwrite
? "text-white bg-[#303136]"
: "text-white/70 hover:text-white hover:bg-[#303136]"
}`}
>
Swap
</Link>
<Link
href="/mint/ai7"
className={`block px-3 py-2 text-sm font-medium rounded-md transition-colors ${
isMint
className={`block px-3 py-2 text-sm font-medium rounded-md transition-colors ${isMint
? "text-white bg-[#303136]"
: "text-white/70 hover:text-white hover:bg-[#303136]"
}`}
}`}
>
Mint AI7
</Link>
<Link
href="/underwrite/ai7"
className={`block mt-1 px-3 py-2 text-sm font-medium rounded-md transition-colors ${
isUnderwrite
className={`block mt-1 px-3 py-2 text-sm font-medium rounded-md transition-colors ${isUnderwrite
? "text-white bg-[#303136]"
: "text-white/70 hover:text-white hover:bg-[#303136]"
}`}
}`}
>
Underwrite AI7
</Link>
Expand Down Expand Up @@ -151,9 +157,8 @@ export const Navbar: React.FC = () => {

{/* Mobile Side Menu */}
<div
className={`fixed top-0 right-0 h-full w-72 bg-[#19191B] z-50 transform transition-transform duration-300 ease-in-out md:hidden ${
isMobileMenuOpen ? "translate-x-0" : "translate-x-full"
}`}
className={`fixed top-0 right-0 h-full w-72 bg-[#19191B] z-50 transform transition-transform duration-300 ease-in-out md:hidden ${isMobileMenuOpen ? "translate-x-0" : "translate-x-full"
}`}
>
{/* Menu Header */}
<div className="flex items-center justify-between px-6 h-16 border-b border-[#303136]">
Expand All @@ -171,21 +176,19 @@ export const Navbar: React.FC = () => {
<nav className="px-4 py-6 flex flex-col gap-2">
<Link
href="/mint/ai7"
className={`px-4 py-3 text-base font-medium rounded-lg transition-colors ${
isMint
className={`px-4 py-3 text-base font-medium rounded-lg transition-colors ${isMint
? "text-white bg-[#303136]"
: "text-white/70 hover:text-white hover:bg-[#222325]"
}`}
}`}
>
Mint AI7
</Link>
<Link
href="/underwrite/ai7"
className={`px-4 py-3 text-base font-medium rounded-lg transition-colors ${
isUnderwrite
className={`px-4 py-3 text-base font-medium rounded-lg transition-colors ${isUnderwrite
? "text-white bg-[#303136]"
: "text-white/70 hover:text-white hover:bg-[#222325]"
}`}
}`}
>
Underwrite AI7
</Link>
Expand Down
94 changes: 75 additions & 19 deletions src/config/contracts.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
// src/config/contracts.ts
import { baseSepolia, base } from "viem/chains";
import {
supportedChains,
BASE_MAINNET_CHAIN_ID,
BASE_SEPOLIA_CHAIN_ID,
defaultChain,
} from "@/lib/chains.config";
import { Address } from "viem";

export interface ContractConfig {
Expand All @@ -12,50 +17,75 @@ export interface ChainContracts {
protocolRegistry: ContractConfig;
}

export const contracts: Record<number, ChainContracts> = {
[base.id]: {
// All contract addresses (both environments)
const ALL_CONTRACTS: Record<number, ChainContracts> = {
[BASE_MAINNET_CHAIN_ID]: {
assetPoolFactory: {
address: "0xC8e4cc79da89FCFaF4436f5e9F9fFCE0D2850378" as Address,
chainId: base.id,
chainId: BASE_MAINNET_CHAIN_ID,
},
protocolRegistry: {
address: "0xBB9f34413f48aE7520acdedC4f07b110860c1534" as Address,
chainId: base.id,
chainId: BASE_MAINNET_CHAIN_ID,
},
},
[baseSepolia.id]: {
[BASE_SEPOLIA_CHAIN_ID]: {
assetPoolFactory: {
address: "0xC0166Fd0F9269B7031477C8098E27E8dDb761D54" as Address,
chainId: baseSepolia.id,
chainId: BASE_SEPOLIA_CHAIN_ID,
},
protocolRegistry: {
address: "0xdE65370F905999eaEC9a3612874752C301324cF7" as Address,
chainId: baseSepolia.id,
chainId: BASE_SEPOLIA_CHAIN_ID,
},
},
};

export const getContractConfig = (chainId: number): ChainContracts => {
const chainContracts = contracts[chainId];
// Export only contracts for supported chains in current environment
export const contracts: Record<number, ChainContracts> = supportedChains.reduce(
(acc, chain) => {
const chainContracts = ALL_CONTRACTS[chain.id];
if (chainContracts) {
acc[chain.id] = chainContracts;
}
return acc;
},
{} as Record<number, ChainContracts>,
);

export const getContractConfig = (
chainId: number,
fallbackToDefault: boolean = true,
): ChainContracts => {
let chainContracts = contracts[chainId];

// Fallback to default chain if requested chain not available
if (!chainContracts && fallbackToDefault) {
console.warn(
`Chain ${chainId} not supported in current environment. Using default chain ${defaultChain.id}`,
);
chainContracts = contracts[defaultChain.id];
}

if (!chainContracts) {
throw new Error(`No contracts configured for chain ${chainId}`);
}

return chainContracts;
};

export const UNISWAP_CONTRACTS: Record<number, Record<string, string>> = {
8453: {
// Base
// v3 specific
// Uniswap contracts configuration
const ALL_UNISWAP_CONTRACTS: Record<number, Record<string, string>> = {
[BASE_MAINNET_CHAIN_ID]: {
// Base Mainnet - v3 specific
quoter: "0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a",
factory: "0x33128a8fC17869897dcE68Ed026d694621f6FDfD",
swapRouter: "0x2626664c2603336E57B271c5C0b26F421741e481",
universalRouter: "0x6ff5693b99212da76ad316178a184ab56d299b43",
permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
},
84532: {
// Base Sepolia
// v4 specific
[BASE_SEPOLIA_CHAIN_ID]: {
// Base Sepolia - v4 specific
quoter: "0x4a6513c898fe1b2d0e78d3b0e0a4a151589b1cba",
positionDescriptor: "0x571291b572ed32ce6751a2cb2486ebee8defb9b4",
poolManager: "0x05E73354cFDd6745C338b50BcFDfA3Aa6fA03408",
Expand All @@ -67,14 +97,40 @@ export const UNISWAP_CONTRACTS: Record<number, Record<string, string>> = {
// more chains later...
};

// Export only Uniswap contracts for supported chains
export const UNISWAP_CONTRACTS: Record<
number,
Record<string, string>
> = supportedChains.reduce(
(acc, chain) => {
const uniswapContracts = ALL_UNISWAP_CONTRACTS[chain.id];
if (uniswapContracts) {
acc[chain.id] = uniswapContracts;
}
return acc;
},
{} as Record<number, Record<string, string>>,
);

// Helper to determine which pool version to use
export const getPoolVersion = (chainId: number): "v3" | "v4" => {
switch (chainId) {
case 8453: // Base Mainnet
case BASE_MAINNET_CHAIN_ID: // Base Mainnet
return "v3";
case 84532: // Base Sepolia
case BASE_SEPOLIA_CHAIN_ID: // Base Sepolia
return "v4";
default:
return "v3";
}
};

// Helper to get Uniswap contracts for a specific chain
export const getUniswapContracts = (
chainId: number,
): Record<string, string> => {
const contracts = UNISWAP_CONTRACTS[chainId];
if (!contracts) {
throw new Error(`No Uniswap contracts configured for chain ${chainId}`);
}
return contracts;
};
Loading
Loading