From 1f7316176510173b98a6111ffd7550b655f146b0 Mon Sep 17 00:00:00 2001 From: Dmitriy Molchanov Date: Mon, 20 Jun 2022 16:34:36 +0300 Subject: [PATCH 1/2] Fix multiples connections to Cere,Ethereum,Polygon --- .../EVMDestinationAdaptorProvider.tsx | 9 +++------ .../EVMAdaptors/EVMHomeAdaptorProvider.tsx | 3 ++- src/Contexts/Adaptors/EVMAdaptors/helpers.ts | 4 ++-- .../Adaptors/SubstrateDestinationAdaptor.tsx | 4 ++-- src/Contexts/Adaptors/SubstrateHomeAdaptor.tsx | 3 ++- src/Contexts/NetworkManagerContext.tsx | 18 ++++++++++++++++++ 6 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/Contexts/Adaptors/EVMAdaptors/EVMDestinationAdaptorProvider.tsx b/src/Contexts/Adaptors/EVMAdaptors/EVMDestinationAdaptorProvider.tsx index af43bd57..e40d6a9c 100644 --- a/src/Contexts/Adaptors/EVMAdaptors/EVMDestinationAdaptorProvider.tsx +++ b/src/Contexts/Adaptors/EVMAdaptors/EVMDestinationAdaptorProvider.tsx @@ -31,12 +31,9 @@ export const EVMDestinationAdaptorProvider = ({ setFallback, address, analytics, + destinationBridge, + setDestinationBridge, } = useNetworkManager(); - - const [destinationBridge, setDestinationBridge] = useState< - Bridge | undefined - >(undefined); - useEffect(() => { if (destinationBridge) return; const provider = getProvider(destinationChainConfig); @@ -48,7 +45,7 @@ export const EVMDestinationAdaptorProvider = ({ ); setDestinationBridge(bridge); } - }, [destinationChainConfig, destinationBridge, transactionStatus]); + }, [destinationChainConfig]); useEffect(() => { if ( diff --git a/src/Contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx b/src/Contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx index 50ce938e..dcb92203 100644 --- a/src/Contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx +++ b/src/Contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx @@ -88,6 +88,8 @@ export const EVMHomeAdaptorProvider = ({ fallback, analytics, setAddress, + setApi, + api, } = useNetworkManager(); const [homeBridge, setHomeBridge] = useState(undefined); @@ -103,7 +105,6 @@ export const EVMHomeAdaptorProvider = ({ const [wrapTokenConfig, setWrapperConfig] = useState( undefined ); - const [api, setApi] = useState(); const [initialising, setInitialising] = useState(false); const [walletSelected, setWalletSelected] = useState(false); diff --git a/src/Contexts/Adaptors/EVMAdaptors/helpers.ts b/src/Contexts/Adaptors/EVMAdaptors/helpers.ts index 8c9efcc0..c21c2926 100644 --- a/src/Contexts/Adaptors/EVMAdaptors/helpers.ts +++ b/src/Contexts/Adaptors/EVMAdaptors/helpers.ts @@ -19,9 +19,9 @@ const getRpcProviderFromHttpUrl = (url: string) => { user: urlInstance.username, password: urlInstance.password, }; - return new ethers.providers.JsonRpcProvider(urlInfo); + return new ethers.providers.StaticJsonRpcProvider(urlInfo); } - return new ethers.providers.JsonRpcProvider(url); + return new ethers.providers.StaticJsonRpcProvider(url); }; export function getProvider(destinationChainConfig?: any) { diff --git a/src/Contexts/Adaptors/SubstrateDestinationAdaptor.tsx b/src/Contexts/Adaptors/SubstrateDestinationAdaptor.tsx index 7e7b731d..e8b73698 100644 --- a/src/Contexts/Adaptors/SubstrateDestinationAdaptor.tsx +++ b/src/Contexts/Adaptors/SubstrateDestinationAdaptor.tsx @@ -34,10 +34,10 @@ export const SubstrateDestinationAdaptorProvider = ({ fallback, address, analytics, + api, + setApi, } = useNetworkManager(); - const [api, setApi] = useState(); - const [initiaising, setInitialising] = useState(false); useEffect(() => { // Once the chain ID has been set in the network context, the destination configuration will be automatically diff --git a/src/Contexts/Adaptors/SubstrateHomeAdaptor.tsx b/src/Contexts/Adaptors/SubstrateHomeAdaptor.tsx index cbbbd19c..6654b638 100644 --- a/src/Contexts/Adaptors/SubstrateHomeAdaptor.tsx +++ b/src/Contexts/Adaptors/SubstrateHomeAdaptor.tsx @@ -23,7 +23,6 @@ export const SubstrateHomeAdaptorProvider = ({ children, }: IHomeBridgeProviderProps) => { const registry = new TypeRegistry(); - const [api, setApi] = useState(); const [isReady, setIsReady] = useState(false); const [accounts, setAccounts] = useState([]); @@ -41,6 +40,8 @@ export const SubstrateHomeAdaptorProvider = ({ address, setAddress, analytics, + api, + setApi, } = useNetworkManager(); const [relayerThreshold, setRelayerThreshold] = useState( diff --git a/src/Contexts/NetworkManagerContext.tsx b/src/Contexts/NetworkManagerContext.tsx index 32f0bc9c..3e50327d 100644 --- a/src/Contexts/NetworkManagerContext.tsx +++ b/src/Contexts/NetworkManagerContext.tsx @@ -28,6 +28,8 @@ import { import { blockchainChainIds } from "../Constants/constants"; import { Fallback } from "../Utils/Fallback"; import AnalyticsService from "../Services/Analytics"; +import { Bridge } from "@chainsafe/chainbridge-contracts"; +import { ApiPromise } from "@polkadot/api"; interface INetworkManagerProviderProps { children: React.ReactNode | React.ReactNode[]; @@ -103,6 +105,12 @@ interface NetworkManagerContext { address: string | undefined; analytics: AnalyticsService; + + setDestinationBridge: (input: Bridge | undefined) => void; + destinationBridge: Bridge | undefined; + + setApi: (input: ApiPromise | undefined) => void; + api: ApiPromise | undefined; } const NetworkManagerContext = React.createContext< @@ -158,6 +166,12 @@ const NetworkManagerProvider = ({ children }: INetworkManagerProviderProps) => { }) ); + const [destinationBridge, setDestinationBridge] = useState< + Bridge | undefined + >(undefined); + + const [api, setApi] = useState(); + const handleSetHomeChain = useCallback( (chainId: number | undefined) => { if (!chainId && chainId !== 0) { @@ -294,6 +308,10 @@ const NetworkManagerProvider = ({ children }: INetworkManagerProviderProps) => { address, setAddress, analytics, + destinationBridge, + setDestinationBridge, + api, + setApi, }} > {walletType === "Ethereum" ? ( From 80f7de2b9587f0065f5aca0dfb9a2c00aa2dfba0 Mon Sep 17 00:00:00 2001 From: Dmitriy Molchanov Date: Wed, 22 Jun 2022 14:52:42 +0300 Subject: [PATCH 2/2] Fix multiple events subscriptions --- src/Components/Pages/TransferPage.tsx | 4 +-- .../EVMAdaptors/EVMHomeAdaptorProvider.tsx | 18 +----------- .../Adaptors/SubstrateDestinationAdaptor.tsx | 28 ++++++++----------- .../Adaptors/SubstrateHomeAdaptor.tsx | 21 ++++++-------- src/Contexts/NetworkManagerContext.tsx | 7 +++++ 5 files changed, 30 insertions(+), 48 deletions(-) diff --git a/src/Components/Pages/TransferPage.tsx b/src/Components/Pages/TransferPage.tsx index 93b593c3..09d119b2 100644 --- a/src/Components/Pages/TransferPage.tsx +++ b/src/Components/Pages/TransferPage.tsx @@ -588,12 +588,12 @@ const TransferPage = () => { className={classes.changeButton} variant="body1" onClick={async () => { + handleSetHomeChain(undefined); + setDestinationChain(undefined); await Promise.all([ destinationBridge.disconnect(), disconnect(), ]); - handleSetHomeChain(undefined); - setDestinationChain(undefined); setWalletType("unset"); }} > diff --git a/src/Contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx b/src/Contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx index dcb92203..49068b7c 100644 --- a/src/Contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx +++ b/src/Contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx @@ -18,7 +18,7 @@ import { HomeBridgeContext } from "../../HomeBridgeContext"; import { parseUnits } from "ethers/lib/utils"; import { decodeAddress } from "@polkadot/util-crypto"; import { getPriceCompatibility } from "./helpers"; -import { createApi, hasTokenSupplies } from "../SubstrateApis/ChainBridgeAPI"; +import { hasTokenSupplies } from "../SubstrateApis/ChainBridgeAPI"; import { ApiPromise } from "@polkadot/api"; export const EVMHomeAdaptorProvider = ({ @@ -88,7 +88,6 @@ export const EVMHomeAdaptorProvider = ({ fallback, analytics, setAddress, - setApi, api, } = useNetworkManager(); @@ -108,21 +107,6 @@ export const EVMHomeAdaptorProvider = ({ const [initialising, setInitialising] = useState(false); const [walletSelected, setWalletSelected] = useState(false); - useEffect(() => { - if (destinationChainConfig?.type !== "Substrate" || initialising || api) - return; - setInitialising(true); - createApi( - destinationChainConfig.rpcUrl, - destinationChainConfig.rpcFallbackUrls - ) - .then((api) => { - setApi(api); - setInitialising(false); - }) - .catch(console.error); - }, [destinationChainConfig, initialising]); - useEffect(() => { if (network) { const chain = homeChains.find((chain) => chain.networkId === network); diff --git a/src/Contexts/Adaptors/SubstrateDestinationAdaptor.tsx b/src/Contexts/Adaptors/SubstrateDestinationAdaptor.tsx index e8b73698..db00f2a3 100644 --- a/src/Contexts/Adaptors/SubstrateDestinationAdaptor.tsx +++ b/src/Contexts/Adaptors/SubstrateDestinationAdaptor.tsx @@ -9,7 +9,6 @@ import { import { IDestinationBridgeProviderProps } from "./interfaces"; import { ApiPromise } from "@polkadot/api"; -import { UnsubscribePromise } from "@polkadot/api/types"; import { SubstrateBridgeConfig, getСhainTransferFallbackConfig, @@ -36,29 +35,27 @@ export const SubstrateDestinationAdaptorProvider = ({ analytics, api, setApi, + listenerActive, + setListenerActive, } = useNetworkManager(); - const [initiaising, setInitialising] = useState(false); + const [initialising, setInitialising] = useState(false); useEffect(() => { // Once the chain ID has been set in the network context, the destination configuration will be automatically // set thus triggering this - if (!destinationChainConfig || initiaising || api) return; + if (!destinationChainConfig || initialising || api) return; setInitialising(true); createApi( destinationChainConfig.rpcUrl, destinationChainConfig.rpcFallbackUrls ) - .then((api) => { + .then(async (api) => { + await api.isReady; setApi(api); setInitialising(false); }) .catch(console.error); - }, [destinationChainConfig, api, initiaising, transactionStatus]); - - const [listenerActive, setListenerActive] = useState< - UnsubscribePromise | undefined - >(undefined); - + }, [destinationChainConfig, initialising]); useEffect(() => { if (api && !listenerActive && depositNonce) { // Wire up event listeners @@ -121,19 +118,15 @@ export const SubstrateDestinationAdaptorProvider = ({ } }); }); - setListenerActive(unsubscribe); + setListenerActive(true); } else if (listenerActive && !depositNonce) { - const unsubscribeCall = async () => { - setListenerActive(undefined); - }; - unsubscribeCall(); + setListenerActive(false); } }, [ api, depositNonce, depositVotes, destinationChainConfig, - listenerActive, setDepositVotes, setTransactionStatus, tokensDispatch, @@ -219,7 +212,8 @@ export const SubstrateDestinationAdaptorProvider = ({ { - await api?.disconnect(); + if (api?.isConnected) await api?.disconnect(); + setApi(undefined); }, }} > diff --git a/src/Contexts/Adaptors/SubstrateHomeAdaptor.tsx b/src/Contexts/Adaptors/SubstrateHomeAdaptor.tsx index 6654b638..a72c11e9 100644 --- a/src/Contexts/Adaptors/SubstrateHomeAdaptor.tsx +++ b/src/Contexts/Adaptors/SubstrateHomeAdaptor.tsx @@ -22,7 +22,6 @@ import { hasTokenSupplies } from "./EVMAdaptors/helpers"; export const SubstrateHomeAdaptorProvider = ({ children, }: IHomeBridgeProviderProps) => { - const registry = new TypeRegistry(); const [isReady, setIsReady] = useState(false); const [accounts, setAccounts] = useState([]); @@ -58,18 +57,20 @@ export const SubstrateHomeAdaptorProvider = ({ handleConnect(); }); - const [initiaising, setInitialising] = useState(false); + const [initialising, setInitialising] = useState(false); useEffect(() => { // Once the chain ID has been set in the network context, the homechain configuration will be automatically set thus triggering this - if (!homeChainConfig || initiaising || api) return; + if (!homeChainConfig || initialising || api) return; setInitialising(true); createApi(homeChainConfig.rpcUrl, homeChainConfig.rpcFallbackUrls) - .then((api) => { + .then(async (api) => { + await api.isReady; setApi(api); + setIsReady(true); setInitialising(false); }) .catch(console.error); - }, [homeChainConfig, registry, api, initiaising]); + }, [homeChainConfig, initialising]); const getRelayerThreshold = useCallback(async () => { if (api) { @@ -209,12 +210,6 @@ export const SubstrateHomeAdaptorProvider = ({ } }, [isReady, handleSetHomeChain, homeChains]); - useEffect(() => { - // This is a simple check - // The reason for having a isReady is that the UI can lazy load data from this point - api?.isReady.then(() => setIsReady(true)); - }, [api, setIsReady]); - const selectAccount = useCallback( (index: number) => { setAddress(accounts[index].address); @@ -345,7 +340,9 @@ export const SubstrateHomeAdaptorProvider = ({ value={{ connect: handleConnect, disconnect: async () => { - await api?.disconnect(); + if (api?.isConnected) await api?.disconnect(); + setApi(undefined); + setIsReady(false); }, getNetworkName: () => homeChainConfig?.name || "undefined", bridgeFee, diff --git a/src/Contexts/NetworkManagerContext.tsx b/src/Contexts/NetworkManagerContext.tsx index 3e50327d..4345d947 100644 --- a/src/Contexts/NetworkManagerContext.tsx +++ b/src/Contexts/NetworkManagerContext.tsx @@ -111,6 +111,9 @@ interface NetworkManagerContext { setApi: (input: ApiPromise | undefined) => void; api: ApiPromise | undefined; + + setListenerActive: (input: boolean) => void; + listenerActive: boolean; } const NetworkManagerContext = React.createContext< @@ -172,6 +175,8 @@ const NetworkManagerProvider = ({ children }: INetworkManagerProviderProps) => { const [api, setApi] = useState(); + const [listenerActive, setListenerActive] = useState(false); + const handleSetHomeChain = useCallback( (chainId: number | undefined) => { if (!chainId && chainId !== 0) { @@ -312,6 +317,8 @@ const NetworkManagerProvider = ({ children }: INetworkManagerProviderProps) => { setDestinationBridge, api, setApi, + listenerActive, + setListenerActive, }} > {walletType === "Ethereum" ? (