111 lines
3.6 KiB
TypeScript
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>
|
|
)
|
|
}
|