diff --git a/packages/apps-config/src/endpoints/index.ts b/packages/apps-config/src/endpoints/index.ts index d5db8b4bf8..178d4b6a4a 100644 --- a/packages/apps-config/src/endpoints/index.ts +++ b/packages/apps-config/src/endpoints/index.ts @@ -10,24 +10,8 @@ import { createTesting } from './testing'; export { CUSTOM_ENDPOINT_KEY } from './development'; -function expand (input: LinkOption[]): LinkOption[] { - return input.reduce((result: LinkOption[], entry): LinkOption[] => { - result.push(entry); - - return entry.linked - ? result.concat( - expand(entry.linked).map((entry): LinkOption => { - entry.isChild = true; - - return entry; - }) - ) - : result; - }, []); -} - export function createWsEndpoints (t: TFunction): LinkOption[] { - return expand([ + return [ ...createCustom(t), { isDisabled: false, @@ -55,5 +39,5 @@ export function createWsEndpoints (t: TFunction): LinkOption[] { }, ...createDev(t), ...createOwn(t) - ]).filter(({ isDisabled }) => !isDisabled); + ].filter(({ isDisabled }) => !isDisabled); } diff --git a/packages/apps-config/src/endpoints/production.ts b/packages/apps-config/src/endpoints/production.ts index 81b015cff7..8eecd12e51 100644 --- a/packages/apps-config/src/endpoints/production.ts +++ b/packages/apps-config/src/endpoints/production.ts @@ -4,6 +4,10 @@ import type { TFunction } from 'i18next'; import type { LinkOption } from '../settings/types'; +import { expandEndpoints } from './util'; + +/* eslint-disable sort-keys */ + // The available endpoints that will show in the dropdown. For the most part (with the exception of // Polkadot) we try to keep this to live chains only, with RPCs hosted by the community/chain vendor // info: The chain logo name as defined in ../ui/logos/index.ts in namedLogos (this also needs to align with @polkadot/networks) @@ -13,63 +17,30 @@ import type { LinkOption } from '../settings/types'; export function createProduction (t: TFunction): LinkOption[] { return [ // fixed, polkadot - { - dnslink: 'polkadot', - info: 'polkadot', - text: t('rpc.polkadot.parity', 'Polkadot', { ns: 'apps-config' }), - textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host: 'Parity' } }), - value: 'wss://rpc.polkadot.io' - }, - { - info: 'polkadot', - text: t('rpc.polkadot.w3f', 'Polkadot', { ns: 'apps-config' }), - textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host: 'Web3 Foundation' } }), - value: 'wss://cc1-1.polkadot.network' - }, - { - info: 'polkadot', - text: t('rpc.polkadot.onfinality', 'Polkadot', { ns: 'apps-config' }), - textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host: 'OnFinality' } }), - value: 'wss://polkadot.api.onfinality.io/public-ws' - }, - { - info: 'polkadot', - text: t('rpc.polkadot.patractlabs', 'Polkadot', { ns: 'apps-config' }), - textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host: 'Patract Elara' } }), - value: 'wss://polkadot.elara.patract.io' - }, - { - dnslink: 'kusama', - info: 'kusama', - text: t('rpc.kusama.parity', 'Kusama', { ns: 'apps-config' }), - textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host: 'Parity' } }), - value: 'wss://kusama-rpc.polkadot.io' - }, - { - info: 'kusama', - text: t('rpc.kusama.w3f', 'Kusama', { ns: 'apps-config' }), - textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host: 'Web3 Foundation' } }), - value: 'wss://cc3-5.kusama.network' - }, - { - info: 'kusama', - text: t('rpc.kusama.onfinality', 'Kusama', { ns: 'apps-config' }), - textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host: 'OnFinality' } }), - value: 'wss://kusama.api.onfinality.io/public-ws' - }, - { - info: 'kusama', - text: t('rpc.kusama.patractlabs', 'Kusama', { ns: 'apps-config' }), - textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host: 'Patract Elara' } }), - value: 'wss://kusama.elara.patract.io' - }, - { - info: 'kusama', - isDisabled: true, - text: t('rpc.kusama.ava', 'Kusama', { ns: 'apps-config' }), - textBy: t('rpc.ava.summary', 'user-run public nodes; see https://status.cloud.ava.do/', { ns: 'apps-config' }), - value: 'wss://kusama.polkadot.cloud.ava.do' - }, + ...expandEndpoints(t, [ + { + dnslink: 'polkadot', + info: 'polkadot', + text: t('rpc.polkadot.parity', 'Polkadot', { ns: 'apps-config' }), + providers: { + Parity: 'wss://rpc.polkadot.io', + 'Web3 Foundation': 'wss://cc1-1.polkadot.network', + OnFinality: 'wss://polkadot.api.onfinality.io/public-ws', + 'Patract Elara': 'wss://polkadot.elara.patract.io' + } + }, + { + dnslink: 'kusama', + info: 'kusama', + text: t('rpc.kusama.parity', 'Kusama', { ns: 'apps-config' }), + providers: { + Parity: 'wss://kusama-rpc.polkadot.io', + 'Web3 Foundation': 'wss://cc3-5.kusama.network', + OnFinality: 'wss://kusama.api.onfinality.io/public-ws', + 'Patract Elara': 'wss://kusama.elara.patract.io' + } + } + ]), // alphabetical based on chain name { dnslink: 'centrifuge', diff --git a/packages/apps-config/src/endpoints/testing.ts b/packages/apps-config/src/endpoints/testing.ts index b6ce03137a..50fd2fb853 100644 --- a/packages/apps-config/src/endpoints/testing.ts +++ b/packages/apps-config/src/endpoints/testing.ts @@ -15,7 +15,7 @@ import { createRococo } from './testingRococo'; export function createTesting (t: TFunction): LinkOption[] { return [ // polkadot test relays - createRococo(t), + ...createRococo(t), // alphabetical based on chain name { info: 'centrifuge', diff --git a/packages/apps-config/src/endpoints/testingRococo.ts b/packages/apps-config/src/endpoints/testingRococo.ts index 13179304a1..b29115ae46 100644 --- a/packages/apps-config/src/endpoints/testingRococo.ts +++ b/packages/apps-config/src/endpoints/testingRococo.ts @@ -4,6 +4,10 @@ import type { TFunction } from 'i18next'; import type { LinkOption } from '../settings/types'; +import { expandEndpoint } from './util'; + +/* eslint-disable sort-keys */ + // The available endpoints that will show in the dropdown. For the most part (with the exception of // Polkadot) we try to keep this to live chains only, with RPCs hosted by the community/chain vendor // info: The chain logo name as defined in ../ui/logos/index.ts in namedLogos (this also needs to align with @polkadot/networks) @@ -11,35 +15,39 @@ import type { LinkOption } from '../settings/types'; // value: The actual hosted secure websocket endpoint // Based on history, this will expand so keep it as a singular chunk -export function createRococo (t: TFunction): LinkOption { - return { +export function createRococo (t: TFunction): LinkOption[] { + return expandEndpoint(t, { dnslink: 'rococo', info: 'rococo', text: t('rpc.rococo', 'Rococo', { ns: 'apps-config' }), - textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host: 'Parity' } }), - value: 'wss://rococo-rpc.polkadot.io', - // eslint-disable-next-line sort-keys + providers: { + Parity: 'wss://rococo-rpc.polkadot.io', + OnFinality: 'wss://rococo.api.onfinality.io/public-ws' + }, linked: [ // these are the base chains { info: 'rococoTick', text: t('rpc.rococo.tick', 'Tick', { ns: 'apps-config' }), - textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host: 'Parity' } }), - value: 'wss://tick-rpc.polkadot.io' + providers: { + Parity: 'wss://tick-rpc.polkadot.io' + } }, { info: 'rococoTrick', text: t('rpc.rococo.trick', 'Trick', { ns: 'apps-config' }), - textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host: 'Parity' } }), - value: 'wss://trick-rpc.polkadot.io' + providers: { + Parity: 'wss://trick-rpc.polkadot.io' + } }, { info: 'rococoTrack', text: t('rpc.rococo.track', 'Track', { ns: 'apps-config' }), - textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host: 'Parity' } }), - value: 'wss://track-rpc.polkadot.io' + providers: { + Parity: 'wss://track-rpc.polkadot.io' + } } // add any additional parachains here, alphabetical ] - }; + }); } diff --git a/packages/apps-config/src/endpoints/types.ts b/packages/apps-config/src/endpoints/types.ts new file mode 100644 index 0000000000..d2bce08e20 --- /dev/null +++ b/packages/apps-config/src/endpoints/types.ts @@ -0,0 +1,13 @@ +// Copyright 2017-2021 @polkadot/apps-config authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +export interface EndpointOption { + dnslink?: string; + isChild?: boolean; + isDevelopment?: boolean; + isDisabled?: boolean; + linked?: EndpointOption[]; + info?: string; + providers: Record; + text: React.ReactNode; +} diff --git a/packages/apps-config/src/endpoints/util.ts b/packages/apps-config/src/endpoints/util.ts new file mode 100644 index 0000000000..a27937149e --- /dev/null +++ b/packages/apps-config/src/endpoints/util.ts @@ -0,0 +1,53 @@ +// Copyright 2017-2021 @polkadot/apps-config authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import type { TFunction } from 'i18next'; +import type { LinkOption } from '../settings/types'; +import type { EndpointOption } from './types'; + +export function expandLinked (input: LinkOption[]): LinkOption[] { + return input.reduce((result: LinkOption[], entry): LinkOption[] => { + result.push(entry); + + return entry.linked + ? result.concat( + expandLinked(entry.linked).map((entry): LinkOption => { + entry.isChild = true; + + return entry; + }) + ) + : result; + }, []); +} + +export function expandEndpoint (t: TFunction, input: EndpointOption): LinkOption[] { + const { dnslink, info, isChild, isDisabled, linked, providers, text } = input; + const base = { + info, + isChild, + isDisabled, + text + }; + + const result = Object.entries(providers).map(([host, value], index): LinkOption => ({ + ...base, + dnslink: index === 0 ? dnslink : undefined, + textBy: t('rpc.hosted.by', 'hosted by {{host}}', { ns: 'apps-config', replace: { host } }), + value + })); + + if (linked) { + const last = result[result.length - 1]; + const options: LinkOption[] = []; + + linked.forEach((o) => options.push(...expandEndpoint(t, o))); + last.linked = options; + } + + return expandLinked(result); +} + +export function expandEndpoints (t: TFunction, input: EndpointOption[]): LinkOption[] { + return input.reduce((result: LinkOption[], input) => result.concat(expandEndpoint(t, input)), []); +}