From 9d994f505f0a93a166df0759dad484d3e211f7c0 Mon Sep 17 00:00:00 2001 From: Qiwei Yang Date: Sat, 2 Mar 2024 22:11:52 +0800 Subject: [PATCH] feat: make local fork non persistent across sessions (#10315) --- packages/apps/src/Endpoints/index.tsx | 18 ++++++++++-------- packages/apps/src/overlays/LocalFork.tsx | 6 +++--- packages/react-api/src/Api.tsx | 17 ++++++++++------- packages/react-api/src/types.ts | 1 + packages/react-hooks/src/ctx/types.ts | 1 + 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/packages/apps/src/Endpoints/index.tsx b/packages/apps/src/Endpoints/index.tsx index 2018054fb6..fefe4f8038 100644 --- a/packages/apps/src/Endpoints/index.tsx +++ b/packages/apps/src/Endpoints/index.tsx @@ -11,6 +11,7 @@ import store from 'store'; import { createWsEndpoints, CUSTOM_ENDPOINT_KEY } from '@polkadot/apps-config'; import { Button, Input, Sidebar, styled } from '@polkadot/react-components'; +import { useApi } from '@polkadot/react-hooks'; import { settings } from '@polkadot/ui-settings'; import { isAscii } from '@polkadot/util'; @@ -118,9 +119,9 @@ function loadAffinities (groups: Group[]): Record { }), {}); } -function isSwitchDisabled (hasUrlChanged: boolean, apiUrl: string, isUrlValid: boolean): boolean { +function isSwitchDisabled (hasUrlChanged: boolean, apiUrl: string, isUrlValid: boolean, isLocalFork?: boolean): boolean { if (!hasUrlChanged) { - if (store.get('localFork') === apiUrl) { + if (isLocalFork) { return false; } else { return true; @@ -134,9 +135,9 @@ function isSwitchDisabled (hasUrlChanged: boolean, apiUrl: string, isUrlValid: b return true; } -function isLocalForkDisabled (hasUrlChanged: boolean, apiUrl: string, isUrlValid: boolean): boolean { +function isLocalForkDisabled (hasUrlChanged: boolean, apiUrl: string, isUrlValid: boolean, isLocalFork?: boolean): boolean { if (!hasUrlChanged) { - if (store.get('localFork') === apiUrl) { + if (isLocalFork) { return true; } else { return false; @@ -153,6 +154,7 @@ function isLocalForkDisabled (hasUrlChanged: boolean, apiUrl: string, isUrlValid function Endpoints ({ className = '', offset, onClose }: Props): React.ReactElement { const { t } = useTranslation(); const linkOptions = createWsEndpoints(t); + const { isLocalFork } = useApi(); const [groups, setGroups] = useState(() => combineEndpoints(linkOptions)); const [{ apiUrl, groupIndex, hasUrlChanged, isUrlValid }, setApiUrl] = useState(() => extractUrlState(settings.get().apiUrl, groups)); const [storedCustomEndpoints, setStoredCustomEndpoints] = useState(() => getCustomEndpoints()); @@ -285,13 +287,13 @@ function Endpoints ({ className = '', offset, onClose }: Props): React.ReactElem ); const canSwitch = useMemo( - () => isSwitchDisabled(hasUrlChanged, apiUrl, isUrlValid), - [hasUrlChanged, apiUrl, isUrlValid] + () => isSwitchDisabled(hasUrlChanged, apiUrl, isUrlValid, isLocalFork), + [hasUrlChanged, apiUrl, isUrlValid, isLocalFork] ); const canLocalFork = useMemo( - () => isLocalForkDisabled(hasUrlChanged, apiUrl, isUrlValid), - [hasUrlChanged, apiUrl, isUrlValid] + () => isLocalForkDisabled(hasUrlChanged, apiUrl, isUrlValid, isLocalFork), + [hasUrlChanged, apiUrl, isUrlValid, isLocalFork] ); return ( diff --git a/packages/apps/src/overlays/LocalFork.tsx b/packages/apps/src/overlays/LocalFork.tsx index 5d9ab035e9..a29f45bd85 100644 --- a/packages/apps/src/overlays/LocalFork.tsx +++ b/packages/apps/src/overlays/LocalFork.tsx @@ -2,9 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 import React from 'react'; -import store from 'store'; -import { settings } from '@polkadot/ui-settings'; +import { useApi } from '@polkadot/react-hooks'; import { useTranslation } from '../translate.js'; import BaseOverlay from './Base.js'; @@ -15,8 +14,9 @@ interface Props { function LocalFork ({ className }: Props): React.ReactElement | null { const { t } = useTranslation(); + const { isLocalFork } = useApi(); - if (store.get('localFork') === settings.get().apiUrl) { + if (isLocalFork) { return ( { /** * @internal */ -async function createApi (apiUrl: string, signer: ApiSigner, onError: (error: unknown) => void): Promise>> { +async function createApi (apiUrl: string, signer: ApiSigner, isLocalFork: boolean, onError: (error: unknown) => void): Promise>> { const types = getDevTypes(); const isLight = apiUrl.startsWith('light://'); let provider; @@ -238,7 +238,7 @@ async function createApi (apiUrl: string, signer: ApiSigner, onError: (error: un try { if (isLight) { provider = await getLightProvider(apiUrl.replace('light://', '')); - } else if (store.get('localFork') === apiUrl) { + } else if (isLocalFork) { provider = await ChopsticksProvider.fromEndpoint(apiUrl); await setStorage(provider.chain, { System: { @@ -277,6 +277,7 @@ export function ApiCtxRoot ({ apiUrl, children, isElectron, store: keyringStore const [isApiInitialized, setIsApiInitialized] = useState(false); const [apiError, setApiError] = useState(null); const [extensions, setExtensions] = useState(); + const [isLocalFork] = useState(store.get('localFork') === apiUrl); const apiEndpoint = useEndpoint(apiUrl); const relayUrls = useMemo( () => (apiEndpoint?.valueRelay && isNumber(apiEndpoint.paraId) && (apiEndpoint.paraId < 2000)) @@ -290,8 +291,8 @@ export function ApiCtxRoot ({ apiUrl, children, isElectron, store: keyringStore [apiUrl, isElectron] ); const value = useMemo( - () => objectSpread({}, state, { api: statics.api, apiEndpoint, apiError, apiRelay, apiUrl, createLink, extensions, isApiConnected, isApiInitialized, isElectron, isWaitingInjected: !extensions }), - [apiError, createLink, extensions, isApiConnected, isApiInitialized, isElectron, state, apiEndpoint, apiRelay, apiUrl] + () => objectSpread({}, state, { api: statics.api, apiEndpoint, apiError, apiRelay, apiUrl, createLink, extensions, isApiConnected, isApiInitialized, isElectron, isLocalFork, isWaitingInjected: !extensions }), + [apiError, createLink, extensions, isApiConnected, isApiInitialized, isElectron, isLocalFork, state, apiEndpoint, apiRelay, apiUrl] ); // initial initialization @@ -302,7 +303,7 @@ export function ApiCtxRoot ({ apiUrl, children, isElectron, store: keyringStore setApiError((error as Error).message); }; - createApi(apiUrl, new ApiSigner(statics.registry, queuePayload, queueSetTxStatus), onError) + createApi(apiUrl, new ApiSigner(statics.registry, queuePayload, queueSetTxStatus), isLocalFork, onError) .then((types): void => { statics.api.on('connected', () => setIsApiConnected(true)); statics.api.on('disconnected', () => setIsApiConnected(false)); @@ -321,7 +322,9 @@ export function ApiCtxRoot ({ apiUrl, children, isElectron, store: keyringStore .catch(onError); }); - if (store.get('localFork') === apiUrl) { + if (isLocalFork) { + // clear localFork from local storage onMount after api setup + store.set('localFork', ''); statics.api.connect() .catch(onError); } @@ -329,7 +332,7 @@ export function ApiCtxRoot ({ apiUrl, children, isElectron, store: keyringStore setIsApiInitialized(true); }) .catch(onError); - }, [apiEndpoint, apiUrl, queuePayload, queueSetTxStatus, keyringStore]); + }, [apiEndpoint, apiUrl, queuePayload, queueSetTxStatus, keyringStore, isLocalFork]); if (!value.isApiInitialized) { return null; diff --git a/packages/react-api/src/types.ts b/packages/react-api/src/types.ts index 8f5905c0a1..cab21016c0 100644 --- a/packages/react-api/src/types.ts +++ b/packages/react-api/src/types.ts @@ -42,6 +42,7 @@ export interface ApiProps extends ApiState { isApiInitialized: boolean; isElectron: boolean; isWaitingInjected: boolean; + isLocalFork?: boolean; } export interface OnChangeCbObs { diff --git a/packages/react-hooks/src/ctx/types.ts b/packages/react-hooks/src/ctx/types.ts index 9adb665dee..40a3dcce11 100644 --- a/packages/react-hooks/src/ctx/types.ts +++ b/packages/react-hooks/src/ctx/types.ts @@ -36,6 +36,7 @@ export interface ApiProps extends ApiState { isApiInitialized: boolean; isElectron: boolean; isWaitingInjected: boolean; + isLocalFork?: boolean; } export interface Accounts {