stabilize connection state of the ghost connect
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
parent
fe71618369
commit
c2d81bc229
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ghost-dao-interface",
|
"name": "ghost-dao-interface",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.7.9",
|
"version": "0.7.10",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@ -92,7 +92,7 @@ function SelectNetwork({ chainId, wrongNetworkToastId, setWrongNetworkToastId, s
|
|||||||
return (
|
return (
|
||||||
<MenuItem key={chain.name} value={chain.id}>
|
<MenuItem key={chain.name} value={chain.id}>
|
||||||
<Box gap="10px" display="flex" flexDirection="row" alignItems="center">
|
<Box gap="10px" display="flex" flexDirection="row" alignItems="center">
|
||||||
<SvgIcon component={parseKnownToken(chain?.nativeCurrency?.symbol)} inheritViewBox />
|
<SvgIcon sx={{ width: 22 }} component={parseKnownToken(chain?.nativeCurrency?.symbol)} inheritViewBox />
|
||||||
{!small && <Typography>{chain.name}</Typography>}
|
{!small && <Typography>{chain.name}</Typography>}
|
||||||
</Box>
|
</Box>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|||||||
@ -1,14 +1,19 @@
|
|||||||
import { createContext, useEffect, useContext, useState, useMemo, useCallback } from "react"
|
import { createContext, useEffect, useContext, useState, useMemo, useCallback, useRef } from "react"
|
||||||
import { Unstable } from "@substrate/connect-discovery"
|
import { Unstable } from "@substrate/connect-discovery"
|
||||||
import { createClient } from "@polkadot-api/substrate-client"
|
import { createClient } from "@polkadot-api/substrate-client"
|
||||||
import { getObservableClient } from "@polkadot-api/observable-client"
|
import { getObservableClient } from "@polkadot-api/observable-client"
|
||||||
import useSWR from "swr"
|
import useSWR from "swr"
|
||||||
|
|
||||||
|
const MAX_BLOCK_TIMEOUT = 15000
|
||||||
const DEFAULT_CHAIN_ID = "0x475e48fab52f3d0587b6b03101d224560c549e984d1dee197b7d8b55830e7da3"
|
const DEFAULT_CHAIN_ID = "0x475e48fab52f3d0587b6b03101d224560c549e984d1dee197b7d8b55830e7da3"
|
||||||
const UnstableProvider = createContext(null)
|
const UnstableProvider = createContext(null)
|
||||||
export const useUnstableProvider = () => useContext(UnstableProvider)
|
export const useUnstableProvider = () => useContext(UnstableProvider)
|
||||||
|
|
||||||
export const UnstableProviderProvider = ({ children }) => {
|
export const UnstableProviderProvider = ({ children }) => {
|
||||||
|
const [chainId, setChainId] = useState(DEFAULT_CHAIN_ID);
|
||||||
|
const [isConnected, setIsConnected] = useState(false);
|
||||||
|
const [reconnectTicket, setReconnectTicket] = useState(0);
|
||||||
|
|
||||||
const { data: providerDetails } = useSWR("getGhostProviders", () =>
|
const { data: providerDetails } = useSWR("getGhostProviders", () =>
|
||||||
Unstable.getSubstrateConnectExtensionProviders()
|
Unstable.getSubstrateConnectExtensionProviders()
|
||||||
);
|
);
|
||||||
@ -19,60 +24,66 @@ export const UnstableProviderProvider = ({ children }) => {
|
|||||||
() => providerDetail ? providerDetail.provider : null
|
() => providerDetail ? providerDetail.provider : null
|
||||||
);
|
);
|
||||||
|
|
||||||
const [chainId, setChainId] = useState(DEFAULT_CHAIN_ID);
|
|
||||||
const [isConnected, setIsConnected] = useState(false);
|
|
||||||
const [reconnectTicket, setReconnectTicket] = useState(0);
|
|
||||||
|
|
||||||
const reconnect = () => setReconnectTicket(prev => prev + 1);
|
|
||||||
const createConnectWithStatus = (originalConnect, onConnect) => {
|
|
||||||
return (observer) => {
|
|
||||||
onConnect(true);
|
|
||||||
return originalConnect(observer);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const client = useMemo(() => {
|
const client = useMemo(() => {
|
||||||
if (!provider || !chainId) return undefined;
|
if (!provider || !chainId) return undefined;
|
||||||
|
|
||||||
const chain = provider.getChains()[chainId];
|
const chain = provider.getChains()[chainId];
|
||||||
if (!chain) return undefined;
|
if (!chain) return undefined;
|
||||||
const wrappedConnect = createConnectWithStatus(chain.connect, setIsConnected);
|
|
||||||
return createClient(wrappedConnect);
|
return createClient(chain.connect)
|
||||||
}, [provider, chainId, reconnectTicket]);
|
}, [provider, chainId, reconnectTicket]);
|
||||||
|
|
||||||
const observableClient = useMemo(() => {
|
const observableClient = useMemo(() => client ? getObservableClient(client) : undefined, [client]);
|
||||||
return client ? getObservableClient(client) : undefined;
|
const chainHead$ = useMemo(() => observableClient?.chainHead$(), [observableClient]);
|
||||||
}, [client]);
|
|
||||||
|
|
||||||
const chainHead$ = useMemo(() => {
|
const lastBlockNumber = useRef(0);
|
||||||
return observableClient ? observableClient.chainHead$() : undefined;
|
|
||||||
}, [observableClient]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!chainHead$) return;
|
if (!chainHead$) return;
|
||||||
const sub = chainHead$.runtime$.subscribe({
|
|
||||||
next: () => setIsConnected(true),
|
lastBlockNumber.current = 0;
|
||||||
|
let timeoutId;
|
||||||
|
|
||||||
|
const sub = chainHead$.bestBlocks$.subscribe({
|
||||||
|
next: (blocks) => {
|
||||||
|
const currentHeight = blocks.at(0)?.number ?? -1;
|
||||||
|
|
||||||
|
if (currentHeight > lastBlockNumber.current) {
|
||||||
|
lastBlockNumber.current = currentHeight;
|
||||||
|
setIsConnected(true);
|
||||||
|
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
setIsConnected(false);
|
||||||
|
setReconnectTicket(t => t + 1);
|
||||||
|
}, MAX_BLOCK_TIMEOUT);
|
||||||
|
}
|
||||||
|
},
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
setIsConnected(false);
|
setIsConnected(false);
|
||||||
setTimeout(reconnect, 3000);
|
setTimeout(() => setReconnectTicket(t => t + 1), 1000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return () => sub.unsubscribe();
|
|
||||||
}, [chainHead$, reconnect]);
|
return () => {
|
||||||
|
sub.unsubscribe();
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
};
|
||||||
|
}, [chainHead$]);
|
||||||
|
|
||||||
|
const value = useMemo(() => ({
|
||||||
|
isConnected,
|
||||||
|
providerDetails,
|
||||||
|
providerDetail,
|
||||||
|
connectProviderDetail: setProviderDetail,
|
||||||
|
chainId,
|
||||||
|
client,
|
||||||
|
setChainId,
|
||||||
|
chainHead$
|
||||||
|
}), [isConnected, providerDetails, providerDetail, chainId, client, chainHead$]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UnstableProvider.Provider
|
<UnstableProvider.Provider value={value}>
|
||||||
value={{
|
|
||||||
isConnected,
|
|
||||||
providerDetails,
|
|
||||||
providerDetail,
|
|
||||||
connectProviderDetail: setProviderDetail,
|
|
||||||
provider,
|
|
||||||
chainId,
|
|
||||||
client,
|
|
||||||
setChainId,
|
|
||||||
chainHead$
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</UnstableProvider.Provider>
|
</UnstableProvider.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user