Skip to content

Commit

Permalink
Add light client support (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
wirednkod authored and Tbaut committed Aug 20, 2024
1 parent 3050eb2 commit 0c04fd7
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 44 deletions.
8 changes: 7 additions & 1 deletion src/Content.tsx
Original file line number Diff line number Diff line change
@@ -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: '',
Expand All @@ -14,6 +16,10 @@ const pages = [
]

export const Content = () => {
const { lightClientLoaded, isLight } = useNetwork()
useEffect(() => {
isLight && lightClientLoaded && toast.success('Light client: Synced')
}, [isLight, lightClientLoaded])
return (
<>
<Routes>
Expand Down
59 changes: 51 additions & 8 deletions src/contexts/NetworkContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,23 @@ 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[]
}

// 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 type ApiType = TypedApi<typeof dot | typeof ksm>

export interface INetworkContext {
lightClientLoaded: boolean
isLight: boolean
network: NetworkProps
setNetwork: React.Dispatch<React.SetStateAction<NetworkProps>>
client: PolkadotClient | undefined
Expand All @@ -24,26 +30,63 @@ export interface INetworkContext {
const NetworkContext = createContext<INetworkContext | undefined>(undefined)

const NetworkContextProvider = ({ children }: NetworkContextProps) => {
const [lightClientLoaded, setLightClientLoaded] = useState<boolean>(false)
const [isLight, setIsLight] = useState<boolean>(false)
const [client, setClient] = useState<PolkadotClient>()
const [api, setApi] = useState<ApiType>()
const [network, setNetwork] = useState<NetworkProps>('polkadot')

useEffect(() => {
let cl: PolkadotClient
let typedApi: ApiType
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':
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 }),
)
cl = createClient(getSmProvider(dotRelayChain))
typedApi = cl.getTypedApi(dot)
break
}
case 'kusama-lc': {
setIsLight(true)
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:
setIsLight(false)
cl = createClient(getWsProvider('wss://rpc.ibp.network/polkadot'))
typedApi = cl.getTypedApi(dot)
}
setClient(cl)
setApi(typedApi)
}, [network])

useEffect(() => {
isLight &&
client?.finalizedBlock$.subscribe((finalizedBlock) => {
if (finalizedBlock.number && !lightClientLoaded) {
setLightClientLoaded(true)
}
})
}, [client?.finalizedBlock$, isLight, lightClientLoaded])

return (
<NetworkContext.Provider value={{ network, setNetwork, client, api }}>
<NetworkContext.Provider
value={{ lightClientLoaded, isLight, network, setNetwork, client, api }}
>
{children}
</NetworkContext.Provider>
)
Expand Down
41 changes: 18 additions & 23 deletions src/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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()
Expand Down Expand Up @@ -57,13 +64,6 @@ export const Header = () => {
{r.name}
</a>
))}
<a
href="#"
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
>
<Settings2 className="h-5 w-5" />
Settings
</a>
</nav>
</SheetContent>
</Sheet>
Expand Down Expand Up @@ -94,20 +94,15 @@ export const Header = () => {
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem
className="cursor-pointer"
key={'polkadot'}
onClick={() => setNetwork('polkadot')}
>
Polkadot
</DropdownMenuItem>
<DropdownMenuItem
className="cursor-pointer"
key={'polkadot'}
onClick={() => setNetwork('kusama')}
>
Kusama
</DropdownMenuItem>
{networkList.map((n) => (
<DropdownMenuItem
className="cursor-pointer"
key={n}
onClick={() => setNetwork(n.split('|')[1] as NetworkProps)}
>
{n.split('|')[0]}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
{!accounts.length && (
Expand Down
38 changes: 26 additions & 12 deletions src/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 ${
Expand All @@ -21,6 +24,7 @@ const linkStyle = (pathname: string, link: string) => {
}

export const Navigation = () => {
const { lightClientLoaded, isLight } = useNetwork()
const { pathname } = useLocation()
const { theme, setTheme } = useTheme()

Expand Down Expand Up @@ -51,6 +55,28 @@ export const Navigation = () => {
))}
</nav>
<nav className="mt-auto flex flex-col items-center gap-4 px-2 sm:py-5">
{isLight && (
<Tooltip>
<TooltipTrigger asChild>
<a
href="#"
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
>
{!lightClientLoaded ? (
<TbLoaderQuarter className="h-5 w-5 animate-spin" />
) : (
<FaCheckCircle className="text-[#00b300]" />
)}
<span className="sr-only">
Light Client {!lightClientLoaded ? `syncing` : `synced`}
</span>
</a>
</TooltipTrigger>
<TooltipContent side="right">
Light Client {!lightClientLoaded ? `syncing` : `synced`}
</TooltipContent>
</Tooltip>
)}
<Tooltip>
<TooltipTrigger asChild>
<a
Expand Down Expand Up @@ -78,18 +104,6 @@ export const Navigation = () => {
</TooltipTrigger>
<TooltipContent side="right">Toggle theme</TooltipContent>
</Tooltip>
{/* <Tooltip>
<TooltipTrigger asChild>
<a
href="#"
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
>
<Settings className="h-5 w-5" />
<span className="sr-only">Settings</span>
</a>
</TooltipTrigger>
<TooltipContent side="right">Settings</TooltipContent>
</Tooltip> */}
</nav>
</aside>
)
Expand Down

0 comments on commit 0c04fd7

Please sign in to comment.