From 99de1dd7b89204281074e406f8cc9ed3e447724f Mon Sep 17 00:00:00 2001 From: Nikos Kontakis Date: Tue, 20 Aug 2024 23:38:21 +0200 Subject: [PATCH 1/3] Add light client support --- src/contexts/NetworkContext.tsx | 38 +++++++++++++++++++++++++++------ src/header.tsx | 32 ++++++++++++++------------- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/src/contexts/NetworkContext.tsx b/src/contexts/NetworkContext.tsx index 6b0354d..7720985 100644 --- a/src/contexts/NetworkContext.tsx +++ b/src/contexts/NetworkContext.tsx @@ -4,6 +4,10 @@ import { dot, ksm } from '@polkadot-api/descriptors' import { PolkadotClient, TypedApi, createClient } from 'polkadot-api' import { getWsProvider } from 'polkadot-api/ws-provider/web' +import { getSmProvider } from 'polkadot-api/sm-provider' +import SmWorker from 'polkadot-api/smoldot/worker?worker' +import { startFromWorker } from 'polkadot-api/smoldot/from-worker' + type NetworkContextProps = { children: React.ReactNode | React.ReactNode[] } @@ -11,7 +15,7 @@ type NetworkContextProps = { // const polakdotEndpoints = ['wss://rpc.ibp.network/polkadot'] // const kusamaEndpoints = ['wss://rpc.ibp.network/kusama'] -export type NetworkProps = 'polkadot' | 'kusama' +export type NetworkProps = 'polkadot' | 'kusama' | 'polkadot-lc' | 'kusama-lc' export interface INetworkContext { network: NetworkProps @@ -30,12 +34,32 @@ const NetworkContextProvider = ({ children }: NetworkContextProps) => { useEffect(() => { let cl: PolkadotClient let typedApi: TypedApi - if (network === 'polkadot') { - cl = createClient(getWsProvider('wss://rpc.ibp.network/polkadot')) - typedApi = cl.getTypedApi(dot) - } else { - cl = createClient(getWsProvider('wss://rpc.ibp.network/kusama')) - typedApi = cl.getTypedApi(ksm) + switch (network) { + case 'kusama': + cl = createClient(getWsProvider('wss://rpc.ibp.network/kusama')) + typedApi = cl.getTypedApi(ksm) + break + case 'polkadot-lc': { + const smoldot = startFromWorker(new SmWorker()) + const dotRelayChain = import('polkadot-api/chains/polkadot').then( + ({ chainSpec }) => smoldot.addChain({ chainSpec }), + ) + cl = createClient(getSmProvider(dotRelayChain)) + typedApi = cl.getTypedApi(dot) + break + } + case 'kusama-lc': { + const smoldot = startFromWorker(new SmWorker()) + const ksmRelayChain = import('polkadot-api/chains/ksmcc3').then( + ({ chainSpec }) => smoldot.addChain({ chainSpec }), + ) + cl = createClient(getSmProvider(ksmRelayChain)) + typedApi = cl.getTypedApi(ksm) + break + } + default: + cl = createClient(getWsProvider('wss://rpc.ibp.network/polkadot')) + typedApi = cl.getTypedApi(dot) } setClient(cl) setApi(typedApi) diff --git a/src/header.tsx b/src/header.tsx index 4bd5437..d658543 100644 --- a/src/header.tsx +++ b/src/header.tsx @@ -23,7 +23,14 @@ import { Settings2, PanelLeft } from 'lucide-react' // } from '@/components/ui/menubar' import { useAccounts } from './contexts/AccountsContext' import { useEffect } from 'react' -import { useNetwork } from './contexts/NetworkContext' +import { NetworkProps, useNetwork } from './contexts/NetworkContext' + +const networkList = [ + 'Polkadot|polkadot', + 'Polkadot Light Client|polkadot-lc', + 'Kusama|kusama', + 'Kusama Light Client|kusama-lc', +] export const Header = () => { const { network, setNetwork } = useNetwork() @@ -94,20 +101,15 @@ export const Header = () => { - setNetwork('polkadot')} - > - Polkadot - - setNetwork('kusama')} - > - Kusama - + {networkList.map((n) => ( + setNetwork(n.split('|')[1] as NetworkProps)} + > + {n.split('|')[0]} + + ))} {!accounts.length && ( From 0b250e59ebc004d275b492eb3c86553d3aecfea5 Mon Sep 17 00:00:00 2001 From: Nikos Kontakis Date: Tue, 20 Aug 2024 23:58:53 +0200 Subject: [PATCH 2/3] Beautify light client case --- src/Content.tsx | 8 ++++++- src/contexts/NetworkContext.tsx | 21 +++++++++++++++++- src/header.tsx | 7 ------ src/navigation.tsx | 38 ++++++++++++++++++++++----------- 4 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/Content.tsx b/src/Content.tsx index 2fcadd3..c07591c 100644 --- a/src/Content.tsx +++ b/src/Content.tsx @@ -1,7 +1,9 @@ import { Route, Routes } from 'react-router-dom' import { Home } from '@/pages/Home' - +import { toast } from 'sonner' +import { useEffect } from 'react' +import { useNetwork } from './contexts/NetworkContext' const pages = [ { path: '', @@ -14,6 +16,10 @@ const pages = [ ] export const Content = () => { + const { lightClientLoaded, isLight } = useNetwork() + useEffect(() => { + isLight && lightClientLoaded && toast.success('Light client: Synced') + }, [isLight, lightClientLoaded]) return ( <> diff --git a/src/contexts/NetworkContext.tsx b/src/contexts/NetworkContext.tsx index 7720985..f29f5d4 100644 --- a/src/contexts/NetworkContext.tsx +++ b/src/contexts/NetworkContext.tsx @@ -18,6 +18,8 @@ type NetworkContextProps = { export type NetworkProps = 'polkadot' | 'kusama' | 'polkadot-lc' | 'kusama-lc' export interface INetworkContext { + lightClientLoaded: boolean + isLight: boolean network: NetworkProps setNetwork: React.Dispatch> client: PolkadotClient | undefined @@ -27,6 +29,8 @@ export interface INetworkContext { const NetworkContext = createContext(undefined) const NetworkContextProvider = ({ children }: NetworkContextProps) => { + const [lightClientLoaded, setLightClientLoaded] = useState(false) + const [isLight, setIsLight] = useState(false) const [client, setClient] = useState() const [api, setApi] = useState>() const [network, setNetwork] = useState('polkadot') @@ -36,10 +40,12 @@ const NetworkContextProvider = ({ children }: NetworkContextProps) => { let typedApi: TypedApi switch (network) { case 'kusama': + setIsLight(false) cl = createClient(getWsProvider('wss://rpc.ibp.network/kusama')) typedApi = cl.getTypedApi(ksm) break case 'polkadot-lc': { + setIsLight(true) const smoldot = startFromWorker(new SmWorker()) const dotRelayChain = import('polkadot-api/chains/polkadot').then( ({ chainSpec }) => smoldot.addChain({ chainSpec }), @@ -49,6 +55,7 @@ const NetworkContextProvider = ({ children }: NetworkContextProps) => { break } case 'kusama-lc': { + setIsLight(true) const smoldot = startFromWorker(new SmWorker()) const ksmRelayChain = import('polkadot-api/chains/ksmcc3').then( ({ chainSpec }) => smoldot.addChain({ chainSpec }), @@ -58,6 +65,7 @@ const NetworkContextProvider = ({ children }: NetworkContextProps) => { break } default: + setIsLight(false) cl = createClient(getWsProvider('wss://rpc.ibp.network/polkadot')) typedApi = cl.getTypedApi(dot) } @@ -65,8 +73,19 @@ const NetworkContextProvider = ({ children }: NetworkContextProps) => { setApi(typedApi) }, [network]) + useEffect(() => { + isLight && + client?.finalizedBlock$.subscribe((finalizedBlock) => { + if (finalizedBlock.number && !lightClientLoaded) { + setLightClientLoaded(true) + } + }) + }, [client?.finalizedBlock$, isLight, lightClientLoaded]) + return ( - + {children} ) diff --git a/src/header.tsx b/src/header.tsx index d658543..2af2db7 100644 --- a/src/header.tsx +++ b/src/header.tsx @@ -64,13 +64,6 @@ export const Header = () => { {r.name} ))} - - - Settings - diff --git a/src/navigation.tsx b/src/navigation.tsx index 53a5cc4..2f3e687 100644 --- a/src/navigation.tsx +++ b/src/navigation.tsx @@ -7,10 +7,13 @@ import { import { routes } from '@/lib/utils' import { useLocation } from 'react-router-dom' import PolkadotIcon from '@/assets/img/polkadotIcon.svg?react' +import { TbLoaderQuarter } from 'react-icons/tb' +import { FaCheckCircle } from 'react-icons/fa' import { Github, Moon, Sun } from 'lucide-react' import { Button } from '@/components/ui/button' import { useTheme } from '@/components/theme-provider' +import { useNetwork } from './contexts/NetworkContext' const linkStyle = (pathname: string, link: string) => { return `link ${ @@ -21,6 +24,7 @@ const linkStyle = (pathname: string, link: string) => { } export const Navigation = () => { + const { lightClientLoaded, isLight } = useNetwork() const { pathname } = useLocation() const { theme, setTheme } = useTheme() @@ -51,6 +55,28 @@ export const Navigation = () => { ))} ) From 3dbe420135f4649436083d3b6939127637413716 Mon Sep 17 00:00:00 2001 From: Nikos Kontakis Date: Tue, 20 Aug 2024 23:59:39 +0200 Subject: [PATCH 3/3] lint --- src/header.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/header.tsx b/src/header.tsx index 2af2db7..b2d8ad2 100644 --- a/src/header.tsx +++ b/src/header.tsx @@ -10,7 +10,7 @@ import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet' import { Button } from '@/components/ui/button' import { routes } from '@/lib/utils' import { useWalletDisconnector } from '@reactive-dot/react' -import { Settings2, PanelLeft } from 'lucide-react' +import { PanelLeft } from 'lucide-react' // import { // Menubar,