Skip to content
Merged
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
10 changes: 9 additions & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,12 @@ const nextConfig = {
},
};

export default nextConfig;
// export default nextConfig;


// /** @type {import('next').NextConfig} */
// const nextConfig = {};

// module.exports = nextConfig;


10 changes: 10 additions & 0 deletions public/Avater.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 5 additions & 2 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { Metadata } from "next";
import "./globals.css";
import NavBar from "@/components/landingpage/NavBar";
import { Providers } from "@/components/blockchain/Providers";
import Footer from "@/components/landingpage/Footer";
import { WalletProvider } from "../components/blockchain/WalletProvider";
import { StarknetProvider } from "../components/blockchain/Providers";

export const metadata: Metadata = {
title: "ChainLib",
Expand All @@ -18,7 +19,9 @@ export default function RootLayout({
<html lang="en">
<body>
<NavBar />
<Providers>{children}</Providers>
<StarknetProvider>
<WalletProvider>{children}</WalletProvider>
</StarknetProvider>
<Footer />
</body>
</html>
Expand Down
60 changes: 49 additions & 11 deletions src/components/blockchain/Providers.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,70 @@

// "use client";
// import { ReactNode } from "react";

// import { sepolia } from "@starknet-react/chains";
// import {
// StarknetConfig,
// argent,
// braavos,
// useInjectedConnectors,
// jsonRpcProvider,
// voyager,
// } from "@starknet-react/core";

// export function Providers({ children }: { children: ReactNode }) {
// const { connectors } = useInjectedConnectors({
// // Show these connectors if the user has no connector installed.
// recommended: [argent(), braavos()],
// // Hide recommended connectors if the user has any connector installed.
// includeRecommended: "onlyIfNoConnectors",
// // Randomize the order of the connectors.
// order: "random",
// });
// return (
// <StarknetConfig
// chains={[sepolia]}
// // i was having issues with the provider then i changed the provider to this
// // provider={jsonRpcProvider({ rpc: (chain) => ({ nodeUrl: process.env.NEXT_PUBLIC_RPC_URL }) })}
// provider={jsonRpcProvider({ rpc: () => ({ nodeUrl: process.env.NEXT_PUBLIC_RPC_URL }) })}
// connectors={connectors}
// explorer={voyager}
// >
// {children}
// </StarknetConfig>
// );
// }

"use client";
import { ReactNode } from "react";
import React from "react";

import { sepolia } from "@starknet-react/chains";
import { sepolia, mainnet } from "@starknet-react/chains";
import {
StarknetConfig,
publicProvider,
argent,
braavos,
useInjectedConnectors,
jsonRpcProvider,
voyager,
voyager
} from "@starknet-react/core";

export function Providers({ children }: { children: ReactNode }) {
export function StarknetProvider({ children }: { children: React.ReactNode }) {
const { connectors } = useInjectedConnectors({
// Show these connectors if the user has no connector installed.
recommended: [argent(), braavos()],
recommended: [
argent(),
braavos(),
],
// Hide recommended connectors if the user has any connector installed.
includeRecommended: "onlyIfNoConnectors",
// Randomize the order of the connectors.
order: "random",
order: "random"
});

return (
<StarknetConfig
chains={[sepolia]}
// i was having issues with the provider then i changed the provider to this
// provider={jsonRpcProvider({ rpc: (chain) => ({ nodeUrl: process.env.NEXT_PUBLIC_RPC_URL }) })}
provider={jsonRpcProvider({ rpc: () => ({ nodeUrl: process.env.NEXT_PUBLIC_RPC_URL }) })}
chains={[mainnet, sepolia]}
provider={publicProvider()}
connectors={connectors}
explorer={voyager}
>
Expand Down
184 changes: 184 additions & 0 deletions src/components/blockchain/Wallet-connect-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
"use client";

import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { X } from "lucide-react";
import Image from "next/image";
import AnimationWrapper from "../motion/Animation-wrapper";
import { useWalletContext } from "./WalletProvider";
import { useRouter } from "next/navigation";

// interface WalletOption {
// id: string;
// name: string;
// icon: string;
// }

interface WalletConnectModalProps {
isOpen: boolean;
onClose: () => void;
onSelect: (wallet: string) => void;
}

export default function WalletConnectModal({
isOpen,
onClose,
}: WalletConnectModalProps) {
const [selectedWallet, setSelectedWallet] = useState<string | null>(null);
const { connectors, connectAsync} = useWalletContext();
const router = useRouter();



const handleSelect = (walletId: string) => {
setSelectedWallet(walletId);
};

// ② On confirm, look up the connector object and call connectWallet
const handleConfirm = async () => {
if (!selectedWallet) return;

const connector = connectors.find((c) => c.id === selectedWallet);
if (!connector) {
console.error("Connector not found:", selectedWallet);
return;
}

try {
await connectAsync({ connector }); // ■ await the wallet prompt
router.push("/sign-in"); // ■ now safe to navigate
onClose();
} catch (err) {
console.error("Wallet connection failed:", err); // ■ handle rejections
}
};

const modalVariants = {
hidden: { opacity: 0, scale: 0.9 },
visible: {
opacity: 1,
scale: 1,
transition: {
duration: 0.2,
ease: "easeOut",
},
},
exit: {
opacity: 0,
scale: 0.9,
transition: {
duration: 0.2,
ease: "easeIn",
},
},
};

const backdropVariants = {
hidden: { opacity: 0 },
visible: { opacity: 1 },
exit: { opacity: 0 },
};

// helper to get icon source
function getIconSource(
icon: string | { dark: string; light: string }
): string {
if (typeof icon === "string") {
// If it's a string, use it directly
return icon;
} else {
// If it's an object, use the dark variant (or light, as needed)
return icon.dark; // Or icon.light, depending on your theme
}
}

return (
<AnimatePresence>
{isOpen && (
<div className="fixed inset-0 z-50 flex items-center justify-center">
<motion.div
className="fixed inset-0 bg-black/50 backdrop-blur-sm"
variants={backdropVariants}
initial="hidden"
animate="visible"
exit="exit"
onClick={onClose}
/>

<motion.div
className="relative w-full max-w-md rounded-2xl bg-blue-600 p-6 shadow-xl"
variants={modalVariants}
initial="hidden"
animate="visible"
exit="exit"
>
<div className="flex items-center justify-between mb-4">
<h2 className="text-xl font-semibold text-white">
Connect Wallet
</h2>
<button
onClick={onClose}
className="text-gray-400 hover:text-white transition-colors"
>
<X size={20} />
</button>
</div>

<p className="text-gray-300 mb-4 text-center">
Choose a wallet you want to connect to Chain Lib
</p>

<div className="space-y-3 mb-6">
{connectors.map((wallet, index) => (
<AnimationWrapper
key={wallet?.id}
variant="slideRight"
delay={index * 0.1}
>
<button
className={`w-full flex items-center gap-3 p-3 rounded-full border border-gray-700 hover:border-gray-500 transition-colors ${
selectedWallet === wallet.id
? "border-teal-500 bg-[#0d0e24]"
: ""
}`}
onClick={() => handleSelect(wallet.id)}
>
<div
className={`w-8 h-8 rounded-full flex items-center justify-center`}
>
<div className="">
<Image
src={getIconSource(wallet.icon)}
alt={wallet.name}
width={30}
height={30}
className="object-contain"
/>
</div>
</div>
<span className="text-white">{wallet.name}</span>
</button>
</AnimationWrapper>
))}
</div>

{/* ③ Confirmation button */}
<AnimationWrapper variant="slideUp" delay={0.3}>
<button
onClick={handleConfirm}
disabled={!selectedWallet}
className={`w-full py-3 rounded-full text-white font-medium transition-colors ${
selectedWallet
? "bg-blue-500 hover:bg-blue-900"
: "bg-gray-700 cursor-not-allowed"
}`}
>
Connect
</button>
</AnimationWrapper>
</motion.div>
</div>
)}
</AnimatePresence>
);
}
Loading
Loading