ghost-lite/src/hooks/useUnstableProvider.tsx
Uncle Fatso a7833d9a5b
initial version
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
2025-07-22 12:55:56 +03:00

111 lines
3.6 KiB
TypeScript

import { type ReactNode, createContext, useContext, useState, useMemo } from "react"
import { Unstable } from "@substrate/connect-discovery"
import { createClient, SubstrateClient } from "@polkadot-api/substrate-client"
import { getObservableClient, ObservableClient } from "@polkadot-api/observable-client"
import { createClient as createFullClient } from "polkadot-api"
import useSWR from "swr"
type Context = {
providerDetails?: Unstable.SubstrateConnectProviderDetail[]
providerDetail?: Unstable.SubstrateConnectProviderDetail
connectProviderDetail(detail: Unstable.SubstrateConnectProviderDetail): void
disconnectProviderDetail(): void
accounts?: Unstable.Account[]
account?: Unstable.Account
connectAccount(account: Unstable.Account): void
disconnectAccount(): void
provider?: Unstable.Provider
chainId: string
setChainId: (chainId: string) => void
client?: SubstrateClient
observableClient?: ObservableClient
chainHead$?: any
clientFull?: any
}
const UnstableProvider = createContext<Context>(null!)
export const useUnstableProvider = () => useContext(UnstableProvider)
export const UnstableProviderProvider = ({
children,
defaultChainId,
}: {
children: ReactNode
defaultChainId: string
}) => {
const { data: providerDetails } = useSWR("getProviders", () =>
Unstable.getSubstrateConnectExtensionProviders(),
)
const [providerDetail, setProviderDetail] =
useState<Unstable.SubstrateConnectProviderDetail>()
const { data: provider } = useSWR(
() => `providerDetail.${providerDetail!.info.uuid}.provider`,
() => providerDetail!.provider,
)
const [chainId, setChainId_] = useState(defaultChainId)
const { data: accounts } = useSWR(
() =>
`providerDetail.${providerDetail!.info.uuid}.provider.getAccounts(${chainId})`,
async () => (await providerDetail!.provider).getAccounts(chainId),
)
const client = useMemo(() => {
if (!provider || !chainId) return undefined
const chain = provider?.getChains()[chainId]
if (!chain) return undefined
return createClient(chain.connect)
}, [provider, chainId])
const clientFull = useMemo(() => {
if (!provider || !chainId) return undefined
const chain = provider?.getChains()[chainId]
if (!chain) return undefined
return createFullClient(chain.connect)
}, [provider, chainId])
const observableClient = useMemo(() => {
return client ? getObservableClient(client) : undefined
}, [client])
const chainHead$ = useMemo(() => {
return observableClient ? observableClient.chainHead$() : undefined
}, [observableClient])
const [account, setAccount] = useState<Unstable.Account>()
const disconnectAccount = () => setAccount(undefined)
const disconnectProviderDetail = () => {
disconnectAccount()
setProviderDetail(undefined)
}
const setChainId = (chainId: string) => {
setChainId_(chainId)
disconnectAccount()
}
return (
<UnstableProvider.Provider
value={{
providerDetails,
providerDetail,
connectProviderDetail: setProviderDetail,
disconnectProviderDetail,
accounts,
account,
connectAccount: setAccount,
disconnectAccount,
provider,
chainId,
setChainId,
client,
clientFull,
observableClient,
chainHead$
}}
>
{children}
</UnstableProvider.Provider>
)
}