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
115 changes: 115 additions & 0 deletions app/commons/ChainContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { createContext, useContext, useMemo, ReactNode } from 'react';
import { Chain } from 'viem/chains';
import { c } from './common';
import { _chains } from './_chains';

interface ChainContextType {
chainIdToChain: { [chainId: number]: Chain };
erc3770ShortNameToChain: { [shortName: string]: Chain };
chainIdToImage: { [chainId: number]: string };
}

const ChainContext = createContext<ChainContextType | null>(null);

export function ChainProvider({ children }: { children: ReactNode }) {
// Memoize chainIdToChain object
const chainIdToChain = useMemo(() => {
let res: {
[chainId: number]: Chain;
} = {};

Object.values(c).map((chain) => {
res[chain.id] = chain;
});

return res;
}, []);

// Memoize erc3770ShortNameToChain object
const erc3770ShortNameToChain = useMemo(() => {
let res: {
[shortName: string]: Chain;
} = {};

Object.entries(c).forEach(([key, chain]) => {
const chainInfo = _chains.find(
(c: { chainId: number; shortName: string }) => c.chainId === chain.id
);

if (chainInfo) {
res[chainInfo.shortName] = chain;
}
});

return res;
}, []);

// Memoize chainIdToImage object
const chainIdToImage = useMemo(() => {
const basePath = "/chainIcons";

let res: {
[chainId: number]: string;
} = {
[c.arbitrum.id]: `${basePath}/arbitrum.svg`,
[c.avalanche.id]: `${basePath}/avalanche.svg`,
[c.base.id]: `${basePath}/base.svg`,
[c.bsc.id]: `${basePath}/bsc.svg`,
[c.cronos.id]: `${basePath}/cronos.svg`,
[c.goerli.id]: `${basePath}/ethereum.svg`,
[c.mainnet.id]: `${basePath}/ethereum.svg`,
[c.optimism.id]: `${basePath}/optimism.svg`,
[c.polygon.id]: `${basePath}/polygon.svg`,
[c.sepolia.id]: `${basePath}/ethereum.svg`,
[c.zora.id]: `${basePath}/zora.svg`,
};

Object.keys(chainIdToChain).map((_chainId) => {
const chainId = Number(_chainId);

if (!res[chainId]) {
res[
chainId
] = `https://t2.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&size=128&url=${chainIdToChain[chainId].blockExplorers?.default.url}`;
}
});

return res;
}, [chainIdToChain]);

const value = useMemo(() => ({
chainIdToChain,
erc3770ShortNameToChain,
chainIdToImage,
}), [chainIdToChain, erc3770ShortNameToChain, chainIdToImage]);

return (
<ChainContext.Provider value={value}>
{children}
</ChainContext.Provider>
);
}

// Hooks for convenient access to context data
export function useChainContext() {
const context = useContext(ChainContext);
if (!context) {
throw new Error('useChainContext must be used within a ChainProvider');
}
return context;
}

export function useChainIdToChain() {
const { chainIdToChain } = useChainContext();
return chainIdToChain;
}

export function useErc3770ShortNameToChain() {
const { erc3770ShortNameToChain } = useChainContext();
return erc3770ShortNameToChain;
}

export function useChainIdToImage() {
const { chainIdToImage } = useChainContext();
return chainIdToImage;
}
9 changes: 6 additions & 3 deletions app/commons/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,9 @@ export const etherscanChains: { [name: string]: Chain } = {
// xaiTestnet,
};

// TODO: these should be placed in provider and memoized
// @deprecated Use useChainIdToChain() hook instead
export const chainIdToChain = (() => {
console.warn('Direct import of chainIdToChain is deprecated. Use useChainIdToChain() hook from ChainContext instead.');
let res: {
[chainId: number]: Chain;
} = {};
Expand All @@ -229,8 +230,9 @@ export const chainIdToChain = (() => {
return res;
})();

// TODO: these should be placed in provider and memoized
// @deprecated Use useErc3770ShortNameToChain() hook instead
export const erc3770ShortNameToChain = (() => {
console.warn('Direct import of erc3770ShortNameToChain is deprecated. Use useErc3770ShortNameToChain() hook from ChainContext instead.');
let res: {
[shortName: string]: Chain;
} = {};
Expand All @@ -248,8 +250,9 @@ export const erc3770ShortNameToChain = (() => {
return res;
})();

// TODO: these should be placed in provider and memoized
// @deprecated Use useChainIdToImage() hook instead
export const chainIdToImage = (() => {
console.warn('Direct import of chainIdToImage is deprecated. Use useChainIdToImage() hook from ChainContext instead.');
const basePath = "/chainIcons";

let res: {
Expand Down
11 changes: 9 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { ReactNode } from 'react';
import { ChainProvider } from './commons/ChainContext';

export const metadata = {
title: 'Next.js',
description: 'Generated by Next.js',
Expand All @@ -6,11 +9,15 @@ export const metadata = {
export default function RootLayout({
children,
}: {
children: React.ReactNode
children: ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
<body>
<ChainProvider>
{children}
</ChainProvider>
</body>
</html>
)
}
Loading