Integrate substrate connect with Apps (#5644)
* integrate apps with smoldot init * Add a new category for substrate connect light clients to be grouped under. Add translations; Alter Api.tsx in order to choose between light clients and/or url addresses * remove supportedLightClient array that was introduced. SubstrateConnect already has the information included and will return error if no supported network is found * rollback 'hacky' changes in order to proceed with better implementation * alter configuration of testing and production networks in order to introduce light client type * upgrade substrate connect to 0.3.7 * implementation for integrating substrate-connect * merge from latest master * Add substrate/connect version to 0.3.10 * fix merge conflicts * introduce function for correctly creating the provider URLs and update URLs * Fix mistaken typos * fix linter issue about rpc-provider@npm:^4.10.1 missing * move substrate-connect for react-api to dependencies * Fix lint issues * Add tests for substrate-connect light clients urls and fix for ws * Update packages/react-api/src/Api.tsx Co-authored-by: Jaco <jacogr@gmail.com> * Remove duplicated code * add exceptions in jest config (transformIgnorePatterns) * minor fixes * fix typo errors * minor yarn update * Alter urls to string | union type (revert urls for json-rpc) * fix erroneously changed url * fix yarn.lock * Stub mock for tests of substrate connect * fix yarn * Update yarn.lock * Update yarn.lock * Update packages/apps/src/Endpoints/index.tsx Co-authored-by: Jaco <jacogr@gmail.com> * Update packages/apps-config/src/endpoints/util.ts Co-authored-by: Jaco <jacogr@gmail.com> * Fix Pr comments * Fix function that was recreated in every rerender * Update packages/apps/src/Endpoints/index.tsx Co-authored-by: Jaco <jacogr@gmail.com> * Fix 2nd bundle of PR comments * Fix function on PR comment * filter light clients out of auto-selected sidebar networks * Update package.json Co-authored-by: Jaco <jacogr@gmail.com> * Update packages/react-api/package.json Co-authored-by: Jaco <jacogr@gmail.com> * run install * update yarn.lock from master * sync yarn.lock from master * Alter implementation to avoid white screen and make sure that API returned from substrate-connect works * Update packages/page-accounts/src/CreateAccount.slow.spec.tsx * Update packages/page-bounties/src/Bounties.slow.spec.tsx Co-authored-by: Jaco <jacogr@gmail.com>
This commit is contained in:
parent
23d65bc9b6
commit
e202dda584
@ -22,8 +22,9 @@ module.exports = {
|
||||
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'empty/object',
|
||||
'\\.(md)$': '<rootDir>/jest/mocks/empty.js'
|
||||
},
|
||||
modulePathIgnorePatterns: ['<rootDir>/packages/apps-config/build'],
|
||||
setupFilesAfterEnv: ['<rootDir>/jest/jest-setup.ts'],
|
||||
testEnvironment: 'jsdom',
|
||||
testTimeout: 90000,
|
||||
transformIgnorePatterns: ['/node_modules/(?!@polkadot|@babel/runtime/helpers/esm/)']
|
||||
transformIgnorePatterns: ['/node_modules/(?!@polkadot|@babel/runtime/helpers/esm/|@substrate|smoldot)']
|
||||
};
|
||||
|
||||
@ -10,14 +10,20 @@ interface Endpoint {
|
||||
ws: string;
|
||||
}
|
||||
|
||||
interface LightClientEndpoint {
|
||||
name: string;
|
||||
param: string;
|
||||
}
|
||||
|
||||
const allEndpoints = createWsEndpoints((k: string, v?: string) => v || k);
|
||||
|
||||
describe('urls are all valid', (): void => {
|
||||
describe('WS urls are all valid', (): void => {
|
||||
allEndpoints
|
||||
.filter(({ value }) =>
|
||||
value &&
|
||||
isString(value) &&
|
||||
!value.includes('127.0.0.1')
|
||||
!value.includes('127.0.0.1') &&
|
||||
!value.includes('substrate-connect')
|
||||
)
|
||||
.map(({ text, value }): Endpoint => ({
|
||||
name: text as string,
|
||||
@ -30,6 +36,24 @@ describe('urls are all valid', (): void => {
|
||||
);
|
||||
});
|
||||
|
||||
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'`);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
describe('urls are sorted', (): void => {
|
||||
let hasDevelopment = false;
|
||||
let lastHeader = '';
|
||||
|
||||
@ -5,6 +5,7 @@ import type { TFunction } from 'i18next';
|
||||
import type { EndpointOption } from './types';
|
||||
|
||||
import { KUSAMA_GENESIS } from '../api/constants';
|
||||
import { createProviderUrl } from './util';
|
||||
|
||||
/* eslint-disable sort-keys */
|
||||
|
||||
@ -22,7 +23,8 @@ export function createKusama (t: TFunction): EndpointOption {
|
||||
providers: {
|
||||
Parity: 'wss://kusama-rpc.polkadot.io',
|
||||
OnFinality: 'wss://kusama.api.onfinality.io/public-ws',
|
||||
'Patract Elara': 'wss://kusama.elara.patract.io'
|
||||
'Patract Elara': 'wss://kusama.elara.patract.io',
|
||||
'light client': createProviderUrl('kusama-substrate-connect', 'substrate-connect')
|
||||
// Pinknode: 'wss://rpc.pinknode.io/kusama/explorer' // https://github.com/polkadot-js/apps/issues/5721
|
||||
},
|
||||
teleport: [1000],
|
||||
|
||||
@ -5,6 +5,7 @@ import type { TFunction } from 'i18next';
|
||||
import type { EndpointOption } from './types';
|
||||
|
||||
import { POLKADOT_GENESIS } from '../api/constants';
|
||||
import { createProviderUrl } from './util';
|
||||
|
||||
/* eslint-disable sort-keys */
|
||||
|
||||
@ -22,7 +23,8 @@ export function createPolkadot (t: TFunction): EndpointOption {
|
||||
providers: {
|
||||
Parity: 'wss://rpc.polkadot.io',
|
||||
OnFinality: 'wss://polkadot.api.onfinality.io/public-ws',
|
||||
'Patract Elara': 'wss://polkadot.elara.patract.io'
|
||||
'Patract Elara': 'wss://polkadot.elara.patract.io',
|
||||
'light client': createProviderUrl('polkadot-substrate-connect', 'substrate-connect')
|
||||
// Pinknode: 'wss://rpc.pinknode.io/polkadot/explorer' // https://github.com/polkadot-js/apps/issues/5721
|
||||
},
|
||||
linked: [
|
||||
|
||||
@ -5,6 +5,7 @@ import type { TFunction } from 'i18next';
|
||||
import type { EndpointOption } from './types';
|
||||
|
||||
import { WESTEND_GENESIS } from '../api/constants';
|
||||
import { createProviderUrl } from './util';
|
||||
|
||||
/* eslint-disable sort-keys */
|
||||
|
||||
@ -24,7 +25,8 @@ export function createWestend (t: TFunction): EndpointOption {
|
||||
providers: {
|
||||
Parity: 'wss://westend-rpc.polkadot.io',
|
||||
'Patract Elara': 'wss://westend.elara.patract.io',
|
||||
OnFinality: 'wss://westend.api.onfinality.io/public-ws'
|
||||
OnFinality: 'wss://westend.api.onfinality.io/public-ws',
|
||||
'light client': createProviderUrl('westend-substrate-connect', 'substrate-connect')
|
||||
// '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
|
||||
},
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
|
||||
import type { Option } from '../settings/types';
|
||||
|
||||
import { Endpoint } from '@polkadot/ui-settings/types';
|
||||
|
||||
export interface EndpointOption {
|
||||
dnslink?: string;
|
||||
genesisHash?: string;
|
||||
@ -14,7 +16,7 @@ export interface EndpointOption {
|
||||
linked?: EndpointOption[];
|
||||
info?: string;
|
||||
paraId?: number;
|
||||
providers: Record<string, string>;
|
||||
providers: Record<string, string | Endpoint>;
|
||||
summary?: string;
|
||||
teleport?: number[];
|
||||
text: React.ReactNode;
|
||||
@ -27,6 +29,7 @@ export interface LinkOption extends Option {
|
||||
homepage?: string;
|
||||
isChild?: boolean;
|
||||
isDevelopment?: boolean;
|
||||
isLightClient?: boolean;
|
||||
isRelay?: boolean;
|
||||
isUnreachable?: boolean;
|
||||
isSpaced?: boolean;
|
||||
|
||||
@ -4,6 +4,9 @@
|
||||
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;
|
||||
}
|
||||
@ -52,9 +55,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',
|
||||
isRelay: false,
|
||||
textBy: t('rpc.hosted.by', 'via {{host}}', { ns: 'apps-config', replace: { host } }),
|
||||
value
|
||||
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
|
||||
}));
|
||||
|
||||
if (linked) {
|
||||
@ -78,3 +84,7 @@ 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 };
|
||||
}
|
||||
|
||||
@ -8,3 +8,16 @@ export interface Option {
|
||||
text: React.ReactNode;
|
||||
value: string | number;
|
||||
}
|
||||
|
||||
export interface LinkOption extends Option {
|
||||
dnslink?: string;
|
||||
genesisHash?: string;
|
||||
genesisHashRelay?: string;
|
||||
isChild?: boolean;
|
||||
isDevelopment?: boolean;
|
||||
isSpaced?: boolean;
|
||||
isLightClient?: boolean;
|
||||
linked?: LinkOption[];
|
||||
paraId?: number;
|
||||
textBy: string;
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
{
|
||||
"lightclient.experimental": "light client (experimental)",
|
||||
"lng.detect": "Default browser language (auto-detect)",
|
||||
"rpc.KlugDossier": "Klug Dossier",
|
||||
"rpc.dev.custom": "Custom environment",
|
||||
|
||||
@ -25,7 +25,11 @@ function NetworkDisplay ({ apiUrl, className = '', setApiUrl, value: { icon, isC
|
||||
);
|
||||
|
||||
const _selectUrl = useCallback(
|
||||
() => setApiUrl(name, providers[Math.floor(Math.random() * providers.length)].url),
|
||||
() => {
|
||||
const filteredProviders = providers.filter((p) => !p.name.startsWith('light client'));
|
||||
|
||||
return setApiUrl(name, filteredProviders[Math.floor(Math.random() * filteredProviders.length)].url);
|
||||
},
|
||||
[name, providers, setApiUrl]
|
||||
);
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ 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';
|
||||
@ -43,13 +44,21 @@ function isValidUrl (url: string): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
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) {
|
||||
result.push({ header: e.text, isDevelopment: e.isDevelopment, isSpaced: e.isSpaced, networks: [] });
|
||||
} else {
|
||||
const prev = result[result.length - 1];
|
||||
const prov = { name: e.textBy, url: e.value };
|
||||
const prov = { isLightClient: e.isLightClient, name: e.textBy, url: e.value };
|
||||
|
||||
if (prev.networks[prev.networks.length - 1] && e.text === prev.networks[prev.networks.length - 1].name) {
|
||||
prev.networks[prev.networks.length - 1].providers.push(prov);
|
||||
@ -118,6 +127,18 @@ function loadAffinities (groups: Group[]): Record<string, string> {
|
||||
}), {});
|
||||
}
|
||||
|
||||
function isSwitchDisabled (hasUrlChanged: boolean, apiType: EndpointType, isUrlValid: boolean): boolean {
|
||||
if (!hasUrlChanged) {
|
||||
return true;
|
||||
} else if (apiType === 'substrate-connect') {
|
||||
return false;
|
||||
} else if (isUrlValid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function Endpoints ({ className = '', offset, onClose }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const linkOptions = createWsEndpoints(t);
|
||||
@ -216,21 +237,24 @@ 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}?rpc=${encodeURIComponent(apiUrl)}${window.location.hash}`);
|
||||
window.location.assign(`${window.location.origin}${window.location.pathname}${getApiType(apiUrl).type === 'substrate-connect' ? '?sc=' : '?rpc='}${encodeURIComponent(apiUrl)}${window.location.hash}`);
|
||||
// window.location.reload();
|
||||
|
||||
onClose();
|
||||
},
|
||||
[apiUrl, onClose]
|
||||
);
|
||||
|
||||
const canSwitch = useMemo(
|
||||
() => isSwitchDisabled(hasUrlChanged, getApiType(apiUrl).type, isUrlValid),
|
||||
[hasUrlChanged, apiUrl, isUrlValid]
|
||||
);
|
||||
|
||||
return (
|
||||
<Sidebar
|
||||
button={
|
||||
<Button
|
||||
icon='sync'
|
||||
isDisabled={!(hasUrlChanged && isUrlValid)}
|
||||
isDisabled={canSwitch}
|
||||
label={t<string>('Switch')}
|
||||
onClick={_onApply}
|
||||
/>
|
||||
@ -251,7 +275,7 @@ function Endpoints ({ className = '', offset, onClose }: Props): React.ReactElem
|
||||
setGroup={_changeGroup}
|
||||
value={group}
|
||||
>
|
||||
{group.isDevelopment && (
|
||||
{group.isDevelopment && getApiType(apiUrl).type === 'json-rpc' && (
|
||||
<div className='endpointCustomWrapper'>
|
||||
<Input
|
||||
className='endpointCustom'
|
||||
|
||||
@ -6,6 +6,7 @@ import React from 'react';
|
||||
export interface Network {
|
||||
icon?: string;
|
||||
isChild?: boolean;
|
||||
isLightClient?: boolean;
|
||||
isUnreachable?: boolean;
|
||||
name: string;
|
||||
providers: {
|
||||
|
||||
@ -44,8 +44,8 @@ function Root ({ store }: Props): React.ReactElement<Props> {
|
||||
<ThemeProvider theme={theme}>
|
||||
<Queue>
|
||||
<Api
|
||||
apiType={settings.apiType}
|
||||
store={store}
|
||||
url={settings.apiUrl}
|
||||
>
|
||||
<BlockAuthors>
|
||||
<Events>
|
||||
|
||||
@ -7,9 +7,18 @@ 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 getApiUrl (): string {
|
||||
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 getApiType (): Endpoint {
|
||||
// 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
|
||||
@ -24,7 +33,15 @@ function getApiUrl (): string {
|
||||
|
||||
assert(url.startsWith('ws://') || url.startsWith('wss://'), 'Non-prefixed ws/wss url');
|
||||
|
||||
return 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' };
|
||||
}
|
||||
|
||||
const endpoints = createWsEndpoints(<T = string>(): T => ('' as unknown as T));
|
||||
@ -35,7 +52,7 @@ function getApiUrl (): string {
|
||||
const option = endpoints.find(({ dnslink }) => dnslink === ipnsChain);
|
||||
|
||||
if (option) {
|
||||
return option.value;
|
||||
return { param: option.value, type: 'json-rpc' };
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,16 +60,17 @@ function getApiUrl (): string {
|
||||
const fallbackUrl = endpoints.find(({ value }) => !!value);
|
||||
|
||||
// via settings, or the default chain
|
||||
return [stored.apiUrl, process.env.WS_URL].includes(settings.apiUrl)
|
||||
? settings.apiUrl // keep as-is
|
||||
return [stored.apiType, process.env.WS_URL].includes(settings.apiType)
|
||||
? settings.apiType // keep as-is
|
||||
: fallbackUrl
|
||||
? fallbackUrl.value // grab the fallback
|
||||
: 'ws://127.0.0.1:9944'; // nothing found, go local
|
||||
? { param: fallbackUrl.value, type: 'json-rpc' } // grab the fallback
|
||||
: { param: 'ws://127.0.0.1:9944', type: 'json-rpc' }; // nothing found, go local
|
||||
}
|
||||
|
||||
const apiUrl = getApiUrl();
|
||||
// There cannot be a Substrate Connect light client default (expect only jrpc EndpointType)
|
||||
const apiType = getApiType();
|
||||
|
||||
// set the default as retrieved here
|
||||
settings.set({ apiUrl });
|
||||
settings.set({ apiType });
|
||||
|
||||
console.log('WS endpoint=', apiUrl);
|
||||
networkOrUrl(apiType);
|
||||
|
||||
@ -9,8 +9,8 @@ import { settings } from '@polkadot/ui-settings';
|
||||
import { useTranslation } from '../translate';
|
||||
import BaseOverlay from './Base';
|
||||
|
||||
const wsUrl = settings.apiUrl;
|
||||
const isWs = typeof wsUrl === 'string' && wsUrl.startsWith('ws://');
|
||||
const wsUrl = settings.apiType.param;
|
||||
const isWs = settings.apiType.type === 'json-rpc' && typeof wsUrl === 'string' && wsUrl.startsWith('ws://');
|
||||
const isWsLocal = typeof wsUrl === 'string' && wsUrl.includes('127.0.0.1');
|
||||
const isHttps = window.location.protocol.startsWith('https:');
|
||||
|
||||
|
||||
@ -14,15 +14,19 @@ 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(
|
||||
<MemoryRouter>
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<Api store={memoryStore}
|
||||
url={`ws://127.0.0.1:${SUBSTRATE_PORT}`}>
|
||||
<Api
|
||||
apiType={apiType}
|
||||
store={memoryStore}
|
||||
>
|
||||
<WaitForApi>
|
||||
<div>
|
||||
<AccountsApp basePath='/accounts'
|
||||
|
||||
@ -17,18 +17,23 @@ 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(
|
||||
<Suspense fallback='...'>
|
||||
<MemoryRouter>
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<Api store={memoryStore}
|
||||
url={`ws://127.0.0.1:${SUBSTRATE_PORT}`}>
|
||||
<Api
|
||||
apiType={apiType}
|
||||
store={memoryStore}
|
||||
>
|
||||
<WaitForApi>
|
||||
<div>
|
||||
<BountiesApp basePath='/bounties' />
|
||||
|
||||
4
packages/react-api/__mocks__/@substrate/connect.js
vendored
Normal file
4
packages/react-api/__mocks__/@substrate/connect.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
// Copyright 2019-2020 @polkadot/extension authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
module.exports = '';
|
||||
@ -7,9 +7,11 @@ import type { ChainProperties, ChainType } from '@polkadot/types/interfaces';
|
||||
import type { KeyringStore } from '@polkadot/ui-keyring/types';
|
||||
import type { ApiProps, ApiState } from './types';
|
||||
|
||||
import { Detector } from '@substrate/connect';
|
||||
import React, { useContext, useEffect, useMemo, useState } from 'react';
|
||||
import store from 'store';
|
||||
|
||||
import { WsProvider } from '@polkadot/api';
|
||||
import { ApiPromise } from '@polkadot/api/promise';
|
||||
import { deriveMapCache, setDeriveCache } from '@polkadot/api-derive/util';
|
||||
import { ethereumChains, typesBundle, typesChain } from '@polkadot/apps-config';
|
||||
@ -17,9 +19,10 @@ 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 { WsProvider } from '@polkadot/rpc-provider';
|
||||
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';
|
||||
|
||||
@ -29,7 +32,7 @@ import { decodeUrlTypes } from './urlTypes';
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
url?: string;
|
||||
apiType: Endpoint;
|
||||
store?: KeyringStore;
|
||||
}
|
||||
|
||||
@ -177,7 +180,7 @@ async function loadOnReady (api: ApiPromise, injectedPromise: Promise<InjectedEx
|
||||
};
|
||||
}
|
||||
|
||||
function Api ({ children, store, url }: Props): React.ReactElement<Props> | null {
|
||||
function Api ({ apiType, children, store }: Props): React.ReactElement<Props> | null {
|
||||
const { queuePayload, queueSetTxStatus } = useContext(StatusContext);
|
||||
const [state, setState] = useState<ApiState>({ hasInjectedAccounts: false, isApiReady: false } as unknown as ApiState);
|
||||
const [isApiConnected, setIsApiConnected] = useState(false);
|
||||
@ -186,13 +189,24 @@ function Api ({ children, store, url }: Props): React.ReactElement<Props> | null
|
||||
const [extensions, setExtensions] = useState<InjectedExtension[] | undefined>();
|
||||
|
||||
const value = useMemo<ApiProps>(
|
||||
() => ({ ...state, api, apiError, apiUrl: url, extensions, isApiConnected, isApiInitialized, isWaitingInjected: !extensions }),
|
||||
[apiError, extensions, isApiConnected, isApiInitialized, state, url]
|
||||
() => ({ ...state, api, apiError, apiUrl: apiType.param, extensions, isApiConnected, isApiInitialized, isWaitingInjected: !extensions }),
|
||||
[apiError, extensions, isApiConnected, isApiInitialized, state, apiType]
|
||||
);
|
||||
|
||||
// initial initialization
|
||||
useEffect((): void => {
|
||||
const provider = new WsProvider(url);
|
||||
let provider;
|
||||
|
||||
if (apiType.type === 'substrate-connect') {
|
||||
const detect: Detector = new Detector('PolkadotJS apps');
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
provider = detect.provider(apiType.param) as ProviderInterface;
|
||||
provider.connect().catch(console.error);
|
||||
} else if (apiType.type === 'json-rpc') {
|
||||
provider = new WsProvider(apiType.param);
|
||||
}
|
||||
|
||||
const signer = new ApiSigner(registry, queuePayload, queueSetTxStatus);
|
||||
const types = getDevTypes();
|
||||
|
||||
@ -218,8 +232,7 @@ function Api ({ children, store, url }: Props): React.ReactElement<Props> | null
|
||||
});
|
||||
|
||||
setIsApiInitialized(true);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
}, [apiType, queuePayload, queueSetTxStatus, store]);
|
||||
|
||||
if (!value.isApiInitialized) {
|
||||
return null;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user