Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactors network selector #25

Merged
merged 1 commit into from
Jan 21, 2025
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
2 changes: 1 addition & 1 deletion apps/flame-defi/app/bridge/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const Tab: React.FC<TabProps> = ({ label, isActive, onClick }) => (
>
<a
onClick={() => {}}
className={`px-6 py-4 font-mono font-medium transition-all duration-100 ease-in ${
className={`px-6 py-4 font-mono font-medium transition ease-in ${
isActive
? "text-white font-bold"
: "text-[#9B9B9B] hover:text-[#D9D9D9]"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";

import React, { useMemo } from "react";
import { ConnectCosmosWalletButton } from "features/CosmosWallet";
import { ConnectEvmWalletButton } from "features/EvmWallet";
import { ConnectEvmWalletButton, SingleWalletButton } from "features/EvmWallet";
import {
Button,
Popover,
PopoverContent,
PopoverTrigger,
} from "@repo/ui/shadcn-primitives";
import { usePathname } from "next/navigation";

interface ConnectWalletsButtonProps {
// Label to show before the user is connected to any wallets.
Expand All @@ -20,70 +20,39 @@ interface ConnectWalletsButtonProps {
export default function ConnectWalletsButton({
labelBeforeConnected,
}: ConnectWalletsButtonProps) {
// information dropdown
const [isDropdownActive, setIsDropdownActive] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
const toggleDropdown = useCallback(() => {
setIsDropdownActive(!isDropdownActive);
}, [isDropdownActive]);

// handle clicking outside dropdown to close it
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
setIsDropdownActive(false);
}
};
const pathname = usePathname();

document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);

// ui
const label = useMemo(() => {
return labelBeforeConnected ?? "Connect";
}, [labelBeforeConnected]);

return (
<div
ref={dropdownRef}
className={`connect-wallet-dropdown ${isDropdownActive ? "is-active" : ""}`}
>
<div className="connect-wallet-button-container">
<button
type="button"
key="connect-evm-wallet-button"
onClick={toggleDropdown}
className="button is-ghost is-rounded-hover"
>
<span className="connect-wallet-button-label">{label}</span>
<span className="icon icon-right is-small">
{isDropdownActive ? (
<i className="fas fa-angle-up" />
) : (
<i className="fas fa-angle-down" />
)}
</span>
</button>
</div>

{/* Dropdown element */}
{isDropdownActive && (
<div className="dropdown-card card">
<div className="">
<div>
<div>
{pathname === "/" ? (
<Popover>
<PopoverTrigger asChild>
<Button
variant="default"
className="rounded-md bg-button-gradient text-white transition border border-button-gradient hover:border-white w-[156px] text-base"
>
<span>{label}</span>
</Button>
</PopoverTrigger>
<PopoverContent
className="flex flex-col w-30 mr-12 text-white gap-3 p-5 bg-radial-dark"
side="bottom"
>
<div className="hover:text-orange-soft transition">
<ConnectEvmWalletButton labelBeforeConnected="Connect to Flame wallet" />
</div>
<div>
<hr className="border-border" />
<div className="hover:text-orange-soft transition">
<ConnectCosmosWalletButton labelBeforeConnected="Connect to Cosmos wallet" />
</div>
</div>
</div>
</PopoverContent>
</Popover>
) : (
<SingleWalletButton />
)}
</div>
);
Expand Down
11 changes: 4 additions & 7 deletions apps/flame-defi/app/components/Navbar/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function Navbar() {
const { brandURL } = useConfig();

const navLinkClasses = (path: string) => `
relative px-4 py-2 text-[#9CA3AF] hover:text-white
relative px-4 py-2 text-grey-light hover:text-white
hover:after:content-[''] hover:after:absolute hover:after:bottom-[-22px]
hover:after:left-1/2 hover:after:transform hover:after:-translate-x-1/2
hover:after:w-[85%] hover:after:h-1 hover:after:bg-[#9CA3AF]
Expand All @@ -39,14 +39,14 @@ function Navbar() {

return (
<nav
className="flex border-b border-[#2A2A2A] px-8 py-4 w-full"
className="flex border-b border-[#2A2A2A] px-12 py-4 w-full"
aria-label="main navigation"
>
<div className="flex items-center">
<a
target="_blank"
href={brandURL}
className="flex items-center p-2 px-3"
className="flex items-center pl-0 p-2 px-3 w-[290px]"
rel="noreferrer"
>
<Image
Expand Down Expand Up @@ -76,7 +76,6 @@ function Navbar() {
<span className="block w-6 h-0.5 bg-white" aria-hidden="true" />
</button>
</div>

<div
id="topNavbar"
className={`flex-1 ${isMobileMenuActive ? "block" : "hidden md:block"}`}
Expand All @@ -93,9 +92,7 @@ function Navbar() {
</Link>
</div>
</div>

<div className="w-[185px]" />
<div className="navbar-end">
<div className="navbar-end flex gap-6 items-center ">
<NetworkSelector />
<ConnectWalletsButton />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export const cosmosChains: CosmosChains = {
};

const FlameChainInfo: EvmChainInfo = {
chainId: 912559,
chainId: 53,
chainName: "Flame (local)",
rpcUrls: ["http://localhost:8545"], // TODO
currencies: [
Expand All @@ -209,7 +209,7 @@ const FlameChainInfo: EvmChainInfo = {
};

const FakeChainInfo: EvmChainInfo = {
chainId: 912559,
chainId: 530,
chainName: "FakeChain (local)",
rpcUrls: ["http://localhost:8545"], // TODO
currencies: [
Expand Down
99 changes: 76 additions & 23 deletions apps/flame-defi/app/config/chainConfigs/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
"use client";

import type { CosmosChains, EvmChainInfo, EvmChains } from "./types";

export enum FlameNetwork {
Expand All @@ -9,57 +7,112 @@ export enum FlameNetwork {
MAINNET = "mainnet",
}

export interface ChainConfigs {
export interface FlameNetworkConfig {
name: FlameNetwork;
evmChains: EvmChains;
cosmosChains: CosmosChains;
}

export interface ChainConfigsObject {
evmChains: EvmChains;
cosmosChains: CosmosChains;
}

export type NetworkConfigs = Record<FlameNetwork, FlameNetworkConfig>;

import * as dawn from "./ChainConfigsDawn";
import * as dusk from "./ChainConfigsDusk";
import * as local from "./ChainConfigsLocal";
import * as mainnet from "./ChainConfigsMainnet";

const NETWORK_CONFIGS: Record<FlameNetwork, ChainConfigs> = {
[FlameNetwork.LOCAL]: local,
[FlameNetwork.DUSK]: dusk,
[FlameNetwork.DAWN]: dawn,
[FlameNetwork.MAINNET]: mainnet,
const NETWORK_CONFIGS: NetworkConfigs = {
[FlameNetwork.LOCAL]: {
name: FlameNetwork.LOCAL,
evmChains: local.evmChains,
cosmosChains: local.cosmosChains,
},
[FlameNetwork.DUSK]: {
name: FlameNetwork.DUSK,
evmChains: dusk.evmChains,
cosmosChains: dusk.cosmosChains,
},
[FlameNetwork.DAWN]: {
name: FlameNetwork.DAWN,
evmChains: dawn.evmChains,
cosmosChains: dawn.cosmosChains,
},
[FlameNetwork.MAINNET]: {
name: FlameNetwork.MAINNET,
evmChains: mainnet.evmChains,
cosmosChains: mainnet.cosmosChains,
},
};

/**
* Gets the chain ID for a Flame network.
*/
export function getFlameChainId(network: FlameNetwork): number {
const config = NETWORK_CONFIGS[network];
const evmChain = Object.values(config.evmChains)[0];
if (!evmChain) {
throw new Error(`No EVM chain found for network ${network}`);
}
return evmChain.chainId;
}

/**
* Gets the Flame network for a chain ID.
*/
export function getFlameNetworkByChainId(chainId: number): FlameNetwork {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const network = Object.entries(NETWORK_CONFIGS).find(([_, config]) => {
const evmChain = Object.values(config.evmChains)[0];
return evmChain && evmChain.chainId === chainId;
});

if (!network) {
throw new Error(`No Flame network found for chain ID ${chainId}`);
}

return network[0] as FlameNetwork;
}

/**
* Gets chain configurations for the specified network.
* Falls back to local network config if specified network is not found.
*/
export function getChainConfigs(network: FlameNetwork): ChainConfigs {
export function getChainConfigs(network: FlameNetwork): FlameNetworkConfig {
return NETWORK_CONFIGS[network] || NETWORK_CONFIGS[FlameNetwork.LOCAL];
}

/**
* Gets all chain configurations.
* This was needed to instantiate the cosmoskit and rainbowkit configs to support s
* Returns merged configurations to maintain compatibility with existing code.
*/
export function getAllChainConfigs(): ChainConfigs {
export function getAllChainConfigs(): ChainConfigsObject {
const evmChains: EvmChains = {};
const cosmosChains: CosmosChains = {};

for (const config of Object.values(NETWORK_CONFIGS)) {
Object.assign(evmChains, config.evmChains);
Object.assign(cosmosChains, config.cosmosChains);
}

return {
evmChains: {
...local.evmChains,
...dusk.evmChains,
...dawn.evmChains,
...mainnet.evmChains,
},
cosmosChains: {
...local.cosmosChains,
...dusk.cosmosChains,
...dawn.cosmosChains,
...mainnet.cosmosChains,
},
evmChains,
cosmosChains,
};
}

/**
* Gets EVM chain configuration by chain ID.
*/
export function getEvmChainByChainId(chainId: number): EvmChainInfo {
const allChainConfigs = getAllChainConfigs();
const found = Object.values(allChainConfigs.evmChains).find(
(chainConfig) => chainConfig.chainId === chainId,
);

if (!found) {
throw new Error(`Chain with chainId ${chainId} not found`);
}
Expand Down
Loading
Loading