Skip to content
Closed
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
89 changes: 45 additions & 44 deletions src/app/providers.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,61 @@
"use client";
'use client';

import React, { createContext, useContext, useState, useCallback, useEffect } from "react";
import { connectWallet, getPublicKey, isFreighterInstalled } from "@/lib/wallet";
import { useState, useEffect, createContext, useContext, ReactNode } from 'react';

interface WalletContextType {
address: string | null;
isConnected: boolean;
isFreighterAvailable: boolean;
connect: () => Promise<void>;
disconnect: () => void;
type Network = 'testnet' | 'mainnet';

interface NetworkContextType {
network: Network;
setNetwork: (network: Network) => void;
isLoading: boolean;
}

const WalletContext = createContext<WalletContextType>({
address: null,
isConnected: false,
isFreighterAvailable: false,
connect: async () => {},
disconnect: () => {},
});
const NetworkContext = createContext<NetworkContextType | undefined>(undefined);

export const useNetwork = () => {
const context = useContext(NetworkContext);
if (context === undefined) {
throw new Error('useNetwork must be used within a NetworkProvider');
}
return context;
};

export function useWallet() {
return useContext(WalletContext);
interface NetworkProviderProps {
children: ReactNode;
}

export function Providers({ children }: { children: React.ReactNode }) {
const [address, setAddress] = useState<string | null>(null);
const [isFreighterAvailable, setIsFreighterAvailable] = useState(false);
export const NetworkProvider = ({ children }: NetworkProviderProps) => {
const [network, setNetworkState] = useState<Network>('testnet');
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
isFreighterInstalled().then(setIsFreighterAvailable);
// Try to reconnect on load
getPublicKey().then((key) => {
if (key) setAddress(key);
});
const savedNetwork = localStorage.getItem('preferred-network') as Network;
if (savedNetwork && (savedNetwork === 'testnet' || savedNetwork === 'mainnet')) {
setNetworkState(savedNetwork);
}
setIsLoading(false);
}, []);

const connect = useCallback(async () => {
const addr = await connectWallet();
if (addr) setAddress(addr);
}, []);

const disconnect = useCallback(() => {
setAddress(null);
}, []);
const setNetwork = (newNetwork: Network) => {
setNetworkState(newNetwork);
localStorage.setItem('preferred-network', newNetwork);
};

return (
<WalletContext.Provider
value={{
address,
isConnected: !!address,
isFreighterAvailable,
connect,
disconnect,
}}
>
<NetworkContext.Provider value={{ network, setNetwork, isLoading }}>
{children}
</WalletContext.Provider>
</NetworkContext.Provider>
);
};

interface ProvidersProps {
children: ReactNode;
}

export default function Providers({ children }: ProvidersProps) {
return (
<NetworkProvider>
{children}
</NetworkProvider>
);
}
112 changes: 110 additions & 2 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,73 @@
"use client";

import Link from "next/link";
import { useState } from "react";
import { ConnectWallet } from "./ConnectWallet";

type Network = "testnet" | "mainnet";

interface ConfirmationDialogProps {
isOpen: boolean;
onConfirm: () => void;
onCancel: () => void;
targetNetwork: Network;
}

function ConfirmationDialog({ isOpen, onConfirm, onCancel, targetNetwork }: ConfirmationDialogProps) {
if (!isOpen) return null;

return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg p-6 max-w-md mx-4">
<h3 className="text-lg font-semibold mb-4">Switch Network</h3>
<p className="text-gray-600 mb-6">
Are you sure you want to switch to {targetNetwork === "testnet" ? "Testnet" : "Mainnet"}?
This will disconnect your current wallet session.
</p>
<div className="flex space-x-3">
<button
onClick={onCancel}
className="flex-1 px-4 py-2 text-gray-600 border border-gray-300 rounded-md hover:bg-gray-50"
>
Cancel
</button>
<button
onClick={onConfirm}
className="flex-1 px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700"
>
Switch Network
</button>
</div>
</div>
</div>
);
}

export function Navbar() {
const [currentNetwork, setCurrentNetwork] = useState<Network>("testnet");
const [showConfirmation, setShowConfirmation] = useState(false);
const [targetNetwork, setTargetNetwork] = useState<Network>("testnet");
const [showNetworkDropdown, setShowNetworkDropdown] = useState(false);

const handleNetworkSelect = (network: Network) => {
if (network !== currentNetwork) {
setTargetNetwork(network);
setShowConfirmation(true);
}
setShowNetworkDropdown(false);
};

const handleConfirmNetworkSwitch = () => {
setCurrentNetwork(targetNetwork);
setShowConfirmation(false);
// Add network switching logic here
console.log(`Switched to ${targetNetwork}`);
};

const handleCancelNetworkSwitch = () => {
setShowConfirmation(false);
};

return (
<nav className="bg-white shadow-sm border-b">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
Expand All @@ -27,9 +91,53 @@ export function Navbar() {
</Link>
</div>
</div>
<ConnectWallet />
<div className="flex items-center space-x-4">
<div className="relative">
<button
onClick={() => setShowNetworkDropdown(!showNetworkDropdown)}
className="flex items-center space-x-2 px-3 py-2 text-sm font-medium text-gray-600 hover:text-gray-900 border border-gray-300 rounded-md hover:bg-gray-50"
>
<div className={`w-2 h-2 rounded-full ${currentNetwork === "testnet" ? "bg-yellow-500" : "bg-green-500"}`}></div>
<span>{currentNetwork === "testnet" ? "Testnet" : "Mainnet"}</span>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</button>

{showNetworkDropdown && (
<div className="absolute right-0 mt-2 w-40 bg-white border border-gray-200 rounded-md shadow-lg z-10">
<button
onClick={() => handleNetworkSelect("testnet")}
className={`w-full text-left px-4 py-2 text-sm hover:bg-gray-50 flex items-center space-x-2 ${
currentNetwork === "testnet" ? "bg-gray-100" : ""
}`}
>
<div className="w-2 h-2 rounded-full bg-yellow-500"></div>
<span>Testnet</span>
</button>
<button
onClick={() => handleNetworkSelect("mainnet")}
className={`w-full text-left px-4 py-2 text-sm hover:bg-gray-50 flex items-center space-x-2 ${
currentNetwork === "mainnet" ? "bg-gray-100" : ""
}`}
>
<div className="w-2 h-2 rounded-full bg-green-500"></div>
<span>Mainnet</span>
</button>
</div>
)}
</div>
<ConnectWallet />
</div>
</div>
</div>

<ConfirmationDialog
isOpen={showConfirmation}
onConfirm={handleConfirmNetworkSwitch}
onCancel={handleCancelNetworkSwitch}
targetNetwork={targetNetwork}
/>
</nav>
);
}
}
Loading