From aa6ea3a48631ac288defb63b33ece93da791b078 Mon Sep 17 00:00:00 2001 From: Jaco Date: Fri, 16 Jul 2021 12:33:03 +0300 Subject: [PATCH] Rework API urls (#5840) * Rework API urls * Adjust * Fix build --- packages/apps-config/src/ci/util.ts | 2 +- .../apps-config/src/endpoints/index.spec.ts | 36 +++------------- .../src/endpoints/productionRelayKusama.ts | 3 +- .../src/endpoints/productionRelayPolkadot.ts | 3 +- .../src/endpoints/testingRelayWestend.ts | 3 +- packages/apps-config/src/endpoints/types.ts | 4 +- packages/apps-config/src/endpoints/util.ts | 17 +++----- packages/apps/src/Endpoints/Network.tsx | 2 +- packages/apps/src/Endpoints/index.tsx | 21 +++------- packages/apps/src/Root.tsx | 2 +- packages/apps/src/initSettings.ts | 41 ++++++++----------- .../src/CreateAccount.slow.spec.tsx | 4 +- .../page-bounties/src/Bounties.slow.spec.tsx | 5 +-- packages/react-api/src/Api.tsx | 23 +++++------ 14 files changed, 52 insertions(+), 114 deletions(-) diff --git a/packages/apps-config/src/ci/util.ts b/packages/apps-config/src/ci/util.ts index 2c80fff21c..86606b501f 100644 --- a/packages/apps-config/src/ci/util.ts +++ b/packages/apps-config/src/ci/util.ts @@ -30,7 +30,7 @@ export function checkEndpoints (issueFile: string, failures: string[]): void { value && isString(value) && !value.includes('127.0.0.1') && - !value.includes('substrate-connect') + !value.startsWith('light://') ) .map(({ text, value }): Partial => ({ name: text as string, diff --git a/packages/apps-config/src/endpoints/index.spec.ts b/packages/apps-config/src/endpoints/index.spec.ts index 0ac8c24557..0b4bed1aac 100644 --- a/packages/apps-config/src/endpoints/index.spec.ts +++ b/packages/apps-config/src/endpoints/index.spec.ts @@ -7,12 +7,7 @@ import { createWsEndpoints } from '.'; interface Endpoint { name: string; - ws: string; -} - -interface LightClientEndpoint { - name: string; - param: string; + value: string; } const allEndpoints = createWsEndpoints((k: string, v?: string) => v || k); @@ -22,34 +17,15 @@ describe('WS urls are all valid', (): void => { .filter(({ value }) => value && isString(value) && - !value.includes('127.0.0.1') && - !value.includes('substrate-connect') + !value.includes('127.0.0.1') ) .map(({ text, value }): Endpoint => ({ name: text as string, - ws: value + value })) - .forEach(({ name, ws }) => - it(`${name} @ ${ws}`, (): void => { - assert(ws.startsWith('wss://'), `${name} @ ${ws} should start with wss://`); - }) - ); -}); - -describe('light client urls are all valid', (): void => { - allEndpoints - .filter(({ value }) => - value && - isString(value) && - value.includes('substrate-connect') - ) - .map(({ text, value }): LightClientEndpoint => ({ - name: text as string, - param: value - })) - .forEach(({ name, param }) => - it(`${name} @ ${param}`, (): void => { - assert(param.substr(param.indexOf('-')) === '-substrate-connect', `${name} @ ${param} should end with '-substrate-connect'`); + .forEach(({ name, value }) => + it(`${name} @ ${value}`, (): void => { + assert(value.startsWith('wss://') || value.startsWith('light://substrate-connect/'), `${name} @ ${value} should start with wss:// or light://`); }) ); }); diff --git a/packages/apps-config/src/endpoints/productionRelayKusama.ts b/packages/apps-config/src/endpoints/productionRelayKusama.ts index 4080fef1aa..0b2ab129a3 100644 --- a/packages/apps-config/src/endpoints/productionRelayKusama.ts +++ b/packages/apps-config/src/endpoints/productionRelayKusama.ts @@ -5,7 +5,6 @@ import type { TFunction } from 'i18next'; import type { EndpointOption } from './types'; import { KUSAMA_GENESIS } from '../api/constants'; -import { createProviderUrl } from './util'; /* eslint-disable sort-keys */ @@ -24,7 +23,7 @@ export function createKusama (t: TFunction): EndpointOption { Parity: 'wss://kusama-rpc.polkadot.io', OnFinality: 'wss://kusama.api.onfinality.io/public-ws', 'Patract Elara': 'wss://kusama.elara.patract.io', - 'light client': createProviderUrl('kusama-substrate-connect', 'substrate-connect') + 'light client': 'light://substrate-connect/kusama' // Pinknode: 'wss://rpc.pinknode.io/kusama/explorer' // https://github.com/polkadot-js/apps/issues/5721 }, teleport: [1000], diff --git a/packages/apps-config/src/endpoints/productionRelayPolkadot.ts b/packages/apps-config/src/endpoints/productionRelayPolkadot.ts index 360d187c0e..bbf6086a0f 100644 --- a/packages/apps-config/src/endpoints/productionRelayPolkadot.ts +++ b/packages/apps-config/src/endpoints/productionRelayPolkadot.ts @@ -5,7 +5,6 @@ import type { TFunction } from 'i18next'; import type { EndpointOption } from './types'; import { POLKADOT_GENESIS } from '../api/constants'; -import { createProviderUrl } from './util'; /* eslint-disable sort-keys */ @@ -24,7 +23,7 @@ export function createPolkadot (t: TFunction): EndpointOption { Parity: 'wss://rpc.polkadot.io', OnFinality: 'wss://polkadot.api.onfinality.io/public-ws', 'Patract Elara': 'wss://polkadot.elara.patract.io', - 'light client': createProviderUrl('polkadot-substrate-connect', 'substrate-connect') + 'light client': 'light://substrate-connect/polkadot' // Pinknode: 'wss://rpc.pinknode.io/polkadot/explorer' // https://github.com/polkadot-js/apps/issues/5721 }, linked: [ diff --git a/packages/apps-config/src/endpoints/testingRelayWestend.ts b/packages/apps-config/src/endpoints/testingRelayWestend.ts index 1b4fee62eb..4b1814499b 100644 --- a/packages/apps-config/src/endpoints/testingRelayWestend.ts +++ b/packages/apps-config/src/endpoints/testingRelayWestend.ts @@ -5,7 +5,6 @@ import type { TFunction } from 'i18next'; import type { EndpointOption } from './types'; import { WESTEND_GENESIS } from '../api/constants'; -import { createProviderUrl } from './util'; /* eslint-disable sort-keys */ @@ -26,7 +25,7 @@ export function createWestend (t: TFunction): EndpointOption { Parity: 'wss://westend-rpc.polkadot.io', 'Patract Elara': 'wss://westend.elara.patract.io', OnFinality: 'wss://westend.api.onfinality.io/public-ws', - 'light client': createProviderUrl('westend-substrate-connect', 'substrate-connect') + 'light client': 'light://substrate-connect/westend' // 'NodeFactory(Vedran)': 'wss://westend.vedran.nodefactory.io/ws', // https://github.com/polkadot-js/apps/issues/5580 // Pinknode: 'wss://rpc.pinknode.io/westend/explorer' // https://github.com/polkadot-js/apps/issues/5721 }, diff --git a/packages/apps-config/src/endpoints/types.ts b/packages/apps-config/src/endpoints/types.ts index ca5a2d0eaf..fa39ae2a2d 100644 --- a/packages/apps-config/src/endpoints/types.ts +++ b/packages/apps-config/src/endpoints/types.ts @@ -3,8 +3,6 @@ import type { Option } from '../settings/types'; -import { Endpoint } from '@polkadot/ui-settings/types'; - export interface EndpointOption { dnslink?: string; genesisHash?: string; @@ -16,7 +14,7 @@ export interface EndpointOption { linked?: EndpointOption[]; info?: string; paraId?: number; - providers: Record; + providers: Record; summary?: string; teleport?: number[]; text: React.ReactNode; diff --git a/packages/apps-config/src/endpoints/util.ts b/packages/apps-config/src/endpoints/util.ts index 84c2cc6b06..44dd0267ab 100644 --- a/packages/apps-config/src/endpoints/util.ts +++ b/packages/apps-config/src/endpoints/util.ts @@ -4,9 +4,6 @@ import type { TFunction } from 'i18next'; import type { EndpointOption, LinkOption } from './types'; -import { Endpoint, EndpointType } from '@polkadot/ui-settings/types'; -import { isString } from '@polkadot/util'; - interface SortOption { isUnreachable?: boolean; } @@ -55,12 +52,12 @@ export function expandEndpoint (t: TFunction, { dnslink, genesisHash, homepage, .map(([host, value], index): LinkOption => ({ ...base, dnslink: index === 0 ? dnslink : undefined, - isLightClient: isString(value) ? false : value.type === 'substrate-connect', + isLightClient: value.startsWith('light://'), isRelay: false, - textBy: isString(value) - ? t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host } }) - : t('lightclient.experimental', 'light client (experimental)', { ns: 'apps-config' }), - value: isString(value) ? value : value.param + textBy: value.startsWith('light://') + ? t('lightclient.experimental', 'light client (experimental)', { ns: 'apps-config' }) + : t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host } }), + value })); if (linked) { @@ -84,7 +81,3 @@ export function expandEndpoint (t: TFunction, { dnslink, genesisHash, homepage, export function expandEndpoints (t: TFunction, input: EndpointOption[], firstOnly?: boolean): LinkOption[] { return input.sort(sortLinks).reduce((result: LinkOption[], input) => result.concat(expandEndpoint(t, input, firstOnly)), []); } - -export function createProviderUrl (param: string, type: EndpointType): Endpoint { - return { param, type }; -} diff --git a/packages/apps/src/Endpoints/Network.tsx b/packages/apps/src/Endpoints/Network.tsx index 2ebecb91c6..b65aab32d0 100644 --- a/packages/apps/src/Endpoints/Network.tsx +++ b/packages/apps/src/Endpoints/Network.tsx @@ -26,7 +26,7 @@ function NetworkDisplay ({ apiUrl, className = '', setApiUrl, value: { icon, isC const _selectUrl = useCallback( () => { - const filteredProviders = providers.filter((p) => !p.name.startsWith('light client')); + const filteredProviders = providers.filter(({ url }) => !url.startsWith('light://')); return setApiUrl(name, filteredProviders[Math.floor(Math.random() * filteredProviders.length)].url); }, diff --git a/packages/apps/src/Endpoints/index.tsx b/packages/apps/src/Endpoints/index.tsx index e06ed36064..9dde70ae79 100644 --- a/packages/apps/src/Endpoints/index.tsx +++ b/packages/apps/src/Endpoints/index.tsx @@ -14,7 +14,6 @@ import styled from 'styled-components'; import { createWsEndpoints, CUSTOM_ENDPOINT_KEY } from '@polkadot/apps-config'; import { Button, Input, Sidebar } from '@polkadot/react-components'; import { settings } from '@polkadot/ui-settings'; -import { Endpoint, EndpointType } from '@polkadot/ui-settings/types'; import { isAscii } from '@polkadot/util'; import { useTranslation } from '../translate'; @@ -40,18 +39,10 @@ function isValidUrl (url: string): boolean { // some random length... we probably want to parse via some lib (url.length >= 7) && // check that it starts with a valid ws identifier - (url.startsWith('ws://') || url.startsWith('wss://')) + (url.startsWith('ws://') || url.startsWith('wss://') || url.startsWith('light://')) ); } -function getApiType (param: string): Endpoint { - if (param.includes('-substrate-connect')) { - return { param, type: 'substrate-connect' }; - } - - return { param, type: 'json-rpc' }; -} - function combineEndpoints (endpoints: LinkOption[]): Group[] { return endpoints.reduce((result: Group[], e): Group[] => { if (e.isHeader) { @@ -127,10 +118,10 @@ function loadAffinities (groups: Group[]): Record { }), {}); } -function isSwitchDisabled (hasUrlChanged: boolean, apiType: EndpointType, isUrlValid: boolean): boolean { +function isSwitchDisabled (hasUrlChanged: boolean, apiUrl: string, isUrlValid: boolean): boolean { if (!hasUrlChanged) { return true; - } else if (apiType === 'substrate-connect') { + } else if (apiUrl.startsWith('light://')) { return false; } else if (isUrlValid) { return false; @@ -237,7 +228,7 @@ function Endpoints ({ className = '', offset, onClose }: Props): React.ReactElem const _onApply = useCallback( (): void => { settings.set({ ...(settings.get()), apiUrl }); - window.location.assign(`${window.location.origin}${window.location.pathname}${getApiType(apiUrl).type === 'substrate-connect' ? '?sc=' : '?rpc='}${encodeURIComponent(apiUrl)}${window.location.hash}`); + window.location.assign(`${window.location.origin}${window.location.pathname}?rpc=${encodeURIComponent(apiUrl)}${window.location.hash}`); // window.location.reload(); onClose(); }, @@ -245,7 +236,7 @@ function Endpoints ({ className = '', offset, onClose }: Props): React.ReactElem ); const canSwitch = useMemo( - () => isSwitchDisabled(hasUrlChanged, getApiType(apiUrl).type, isUrlValid), + () => isSwitchDisabled(hasUrlChanged, apiUrl, isUrlValid), [hasUrlChanged, apiUrl, isUrlValid] ); @@ -275,7 +266,7 @@ function Endpoints ({ className = '', offset, onClose }: Props): React.ReactElem setGroup={_changeGroup} value={group} > - {group.isDevelopment && getApiType(apiUrl).type === 'json-rpc' && ( + {group.isDevelopment && (
{ diff --git a/packages/apps/src/initSettings.ts b/packages/apps/src/initSettings.ts index f26cf0bee3..060bb6768f 100644 --- a/packages/apps/src/initSettings.ts +++ b/packages/apps/src/initSettings.ts @@ -7,18 +7,17 @@ import store from 'store'; import { createWsEndpoints } from '@polkadot/apps-config'; import { extractIpfsDetails } from '@polkadot/react-hooks/useIpfs'; import { settings } from '@polkadot/ui-settings'; -import { Endpoint } from '@polkadot/ui-settings/types'; import { assert } from '@polkadot/util'; -function networkOrUrl (apiType: Endpoint): void { - if (apiType.type === 'json-rpc') { - console.log('WS endpoint=', apiType.param); - } else if (apiType.type === 'substrate-connect') { - console.log('Chain of light client is =', apiType.param); +function networkOrUrl (apiUrl: string): void { + if (apiUrl.startsWith('light://')) { + console.log('Light endpoint=', apiUrl.replace('light://', '')); + } else { + console.log('WS endpoint=', apiUrl); } } -function getApiType (): Endpoint { +function getApiUrl (): string { // we split here so that both these forms are allowed // - http://localhost:3000/?rpc=wss://substrate-rpc.parity.io/#/explorer // - http://localhost:3000/#/explorer?rpc=wss://substrate-rpc.parity.io @@ -31,17 +30,9 @@ function getApiType (): Endpoint { // https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:9944#/explorer; const url = decodeURIComponent(urlOptions.rpc.split('#')[0]); - assert(url.startsWith('ws://') || url.startsWith('wss://'), 'Non-prefixed ws/wss url'); + assert(url.startsWith('ws://') || url.startsWith('wss://') || url.startsWith('light://'), 'Non-prefixed ws/wss/light url'); - return { param: url, type: 'json-rpc' }; - } else if (urlOptions.sc) { - assert(!Array.isArray(urlOptions.sc), 'Invalid network specified'); - - // https://polkadot.js.org/apps/?sc=kusama#/explorer; - const network = decodeURIComponent(urlOptions.sc.split('#')[0]); - const chain = network.split('-')[0]; - - return { param: chain, type: 'substrate-connect' }; + return url; } const endpoints = createWsEndpoints((): T => ('' as unknown as T)); @@ -52,7 +43,7 @@ function getApiType (): Endpoint { const option = endpoints.find(({ dnslink }) => dnslink === ipnsChain); if (option) { - return { param: option.value, type: 'json-rpc' }; + return option.value; } } @@ -60,17 +51,17 @@ function getApiType (): Endpoint { const fallbackUrl = endpoints.find(({ value }) => !!value); // via settings, or the default chain - return [stored.apiType, process.env.WS_URL].includes(settings.apiType) - ? settings.apiType // keep as-is + return [stored.apiUrl, process.env.WS_URL].includes(settings.apiUrl) + ? settings.apiUrl // keep as-is : fallbackUrl - ? { param: fallbackUrl.value, type: 'json-rpc' } // grab the fallback - : { param: 'ws://127.0.0.1:9944', type: 'json-rpc' }; // nothing found, go local + ? fallbackUrl.value // grab the fallback + : 'ws://127.0.0.1:9944'; // nothing found, go local } // There cannot be a Substrate Connect light client default (expect only jrpc EndpointType) -const apiType = getApiType(); +const apiUrl = getApiUrl(); // set the default as retrieved here -settings.set({ apiType }); +settings.set({ apiUrl }); -networkOrUrl(apiType); +networkOrUrl(apiUrl); diff --git a/packages/page-accounts/src/CreateAccount.slow.spec.tsx b/packages/page-accounts/src/CreateAccount.slow.spec.tsx index b1e8002fe3..2df1213f0a 100644 --- a/packages/page-accounts/src/CreateAccount.slow.spec.tsx +++ b/packages/page-accounts/src/CreateAccount.slow.spec.tsx @@ -14,17 +14,15 @@ import { Api } from '@polkadot/react-api'; import { MemoryStore } from '@polkadot/test-support/keyring'; import { WaitForApi } from '@polkadot/test-support/react'; import { SUBSTRATE_PORT } from '@polkadot/test-support/substrate'; -import { Endpoint } from '@polkadot/ui-settings/types'; const renderAccounts = () => { const memoryStore = new MemoryStore(); - const apiType: Endpoint = { param: `ws://127.0.0.1:${SUBSTRATE_PORT}`, type: 'json-rpc' }; return render( diff --git a/packages/page-bounties/src/Bounties.slow.spec.tsx b/packages/page-bounties/src/Bounties.slow.spec.tsx index de8bb9d32b..89abc58e49 100644 --- a/packages/page-bounties/src/Bounties.slow.spec.tsx +++ b/packages/page-bounties/src/Bounties.slow.spec.tsx @@ -17,21 +17,18 @@ import { MemoryStore } from '@polkadot/test-support/keyring'; import { aliceSigner } from '@polkadot/test-support/keyring/signers'; import { WaitForApi } from '@polkadot/test-support/react'; import { execute } from '@polkadot/test-support/transaction/execute'; -import { Endpoint } from '@polkadot/ui-settings/types'; const SUBSTRATE_PORT = Number.parseInt(process.env.TEST_SUBSTRATE_PORT || '30333'); const renderBounties = () => { const memoryStore = new MemoryStore(); - const apiType: Endpoint = { param: `ws://127.0.0.1:${SUBSTRATE_PORT}`, type: 'json-rpc' }; - return render( diff --git a/packages/react-api/src/Api.tsx b/packages/react-api/src/Api.tsx index d58ed4f72b..19111a3a28 100644 --- a/packages/react-api/src/Api.tsx +++ b/packages/react-api/src/Api.tsx @@ -19,10 +19,8 @@ import { web3Accounts, web3Enable } from '@polkadot/extension-dapp'; import { TokenUnit } from '@polkadot/react-components/InputNumber'; import { StatusContext } from '@polkadot/react-components/Status'; import ApiSigner from '@polkadot/react-signer/signers/ApiSigner'; -import { ProviderInterface } from '@polkadot/rpc-provider/types'; import { keyring } from '@polkadot/ui-keyring'; import { settings } from '@polkadot/ui-settings'; -import { Endpoint } from '@polkadot/ui-settings/types'; import { formatBalance, isTestChain } from '@polkadot/util'; import { defaults as addressDefaults } from '@polkadot/util-crypto/address/defaults'; @@ -32,7 +30,7 @@ import { decodeUrlTypes } from './urlTypes'; interface Props { children: React.ReactNode; - apiType: Endpoint; + apiUrl: string; store?: KeyringStore; } @@ -180,7 +178,7 @@ async function loadOnReady (api: ApiPromise, injectedPromise: Promise | null { +function Api ({ apiUrl, children, store }: Props): React.ReactElement | null { const { queuePayload, queueSetTxStatus } = useContext(StatusContext); const [state, setState] = useState({ hasInjectedAccounts: false, isApiReady: false } as unknown as ApiState); const [isApiConnected, setIsApiConnected] = useState(false); @@ -189,22 +187,21 @@ function Api ({ apiType, children, store }: Props): React.ReactElement | const [extensions, setExtensions] = useState(); const value = useMemo( - () => ({ ...state, api, apiError, apiUrl: apiType.param, extensions, isApiConnected, isApiInitialized, isWaitingInjected: !extensions }), - [apiError, extensions, isApiConnected, isApiInitialized, state, apiType] + () => ({ ...state, api, apiError, apiUrl, extensions, isApiConnected, isApiInitialized, isWaitingInjected: !extensions }), + [apiError, extensions, isApiConnected, isApiInitialized, state, apiUrl] ); // initial initialization useEffect((): void => { let provider; - if (apiType.type === 'substrate-connect') { - const detect: Detector = new Detector('PolkadotJS apps'); + if (apiUrl.startsWith('light://')) { + const detect = new Detector('polkadot-js/apps'); - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - provider = detect.provider(apiType.param) as ProviderInterface; + provider = detect.provider(apiUrl.replace('light://substrate-connect/', '')); provider.connect().catch(console.error); - } else if (apiType.type === 'json-rpc') { - provider = new WsProvider(apiType.param); + } else { + provider = new WsProvider(apiUrl); } const signer = new ApiSigner(registry, queuePayload, queueSetTxStatus); @@ -232,7 +229,7 @@ function Api ({ apiType, children, store }: Props): React.ReactElement | }); setIsApiInitialized(true); - }, [apiType, queuePayload, queueSetTxStatus, store]); + }, [apiUrl, queuePayload, queueSetTxStatus, store]); if (!value.isApiInitialized) { return null;