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(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() 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() const disconnectAccount = () => setAccount(undefined) const disconnectProviderDetail = () => { disconnectAccount() setProviderDetail(undefined) } const setChainId = (chainId: string) => { setChainId_(chainId) disconnectAccount() } return ( {children} ) }