diff --git a/packages/apps-config/src/endpoints/productionRelayKusama.ts b/packages/apps-config/src/endpoints/productionRelayKusama.ts
index 2657a2d523..e1e6b4c208 100644
--- a/packages/apps-config/src/endpoints/productionRelayKusama.ts
+++ b/packages/apps-config/src/endpoints/productionRelayKusama.ts
@@ -24,7 +24,7 @@ export function createKusama (t: TFunction): EndpointOption {
OnFinality: 'wss://kusama.api.onfinality.io/public-ws',
'Patract Elara': 'wss://pub.elara.patract.io/kusama',
// 'Geometry Labs': 'wss://kusama.geometry.io/websockets', // https://github.com/polkadot-js/apps/pull/6746
- Dwellir: 'wss://kusama-rpc.dwellir.com',
+ // Dwellir: 'wss://kusama-rpc.dwellir.com', // https://github.com/polkadot-js/apps/issues/6753
'light client': 'light://substrate-connect/kusama'
// Pinknode: 'wss://rpc.pinknode.io/kusama/explorer' // https://github.com/polkadot-js/apps/issues/5721
},
diff --git a/packages/page-assets/src/Overview/Asset.tsx b/packages/page-assets/src/Overview/Asset.tsx
index 880b3f867b..0ce566ee35 100644
--- a/packages/page-assets/src/Overview/Asset.tsx
+++ b/packages/page-assets/src/Overview/Asset.tsx
@@ -30,8 +30,8 @@ function Asset ({ className, value: { details, id, isIssuerMe, metadata } }: Pro
{metadata?.name.toUtf8()} |
{details && } |
{details && } |
- {details && } |
- {details && } |
+ {details && } |
+ {details && } |
{details && (
{
[t('assets'), 'start', 2],
[t('owner'), 'address media--1000'],
[t('admin'), 'address media--1200'],
- [t('issuer'), 'address media--1300'],
- [t('freezer'), 'address media--1400'],
+ [t('issuer'), 'address media--1400'],
+ [t('freezer'), 'address media--1700'],
[t('supply')],
[]
]);
diff --git a/packages/react-api/src/Api.tsx b/packages/react-api/src/Api.tsx
index 0b48bed529..ec2d105484 100644
--- a/packages/react-api/src/Api.tsx
+++ b/packages/react-api/src/Api.tsx
@@ -17,11 +17,11 @@ import { ethereumChains, typesBundle, typesChain } from '@polkadot/apps-config';
import { web3Accounts, web3Enable } from '@polkadot/extension-dapp';
import { TokenUnit } from '@polkadot/react-components/InputNumber';
import { StatusContext } from '@polkadot/react-components/Status';
-import { useEndpoint } from '@polkadot/react-hooks';
+import { useApiUrl, useEndpoint } from '@polkadot/react-hooks';
import ApiSigner from '@polkadot/react-signer/signers/ApiSigner';
import { keyring } from '@polkadot/ui-keyring';
import { settings } from '@polkadot/ui-settings';
-import { formatBalance, isTestChain, objectSpread, stringify } from '@polkadot/util';
+import { formatBalance, isNumber, isTestChain, objectSpread, stringify } from '@polkadot/util';
import { defaults as addressDefaults } from '@polkadot/util-crypto/address/defaults';
import ApiContext from './ApiContext';
@@ -179,17 +179,24 @@ async function loadOnReady (api: ApiPromise, injectedPromise: Promise | null {
- const apiEndpoint = useEndpoint(apiUrl);
const { queuePayload, queueSetTxStatus } = useContext(StatusContext);
const [state, setState] = useState({ hasInjectedAccounts: false, isApiReady: false } as unknown as ApiState);
const [isApiConnected, setIsApiConnected] = useState(false);
const [isApiInitialized, setIsApiInitialized] = useState(false);
const [apiError, setApiError] = useState(null);
const [extensions, setExtensions] = useState();
+ const apiEndpoint = useEndpoint(apiUrl);
+ const relayUrls = useMemo(
+ () => (apiEndpoint && apiEndpoint.valueRelay && isNumber(apiEndpoint.paraId) && (apiEndpoint.paraId < 2000))
+ ? apiEndpoint.valueRelay
+ : null,
+ [apiEndpoint]
+ );
+ const apiRelay = useApiUrl(relayUrls);
const value = useMemo(
- () => objectSpread({}, state, { api, apiEndpoint, apiError, apiUrl, extensions, isApiConnected, isApiInitialized, isElectron, isWaitingInjected: !extensions }),
- [apiError, extensions, isApiConnected, isApiInitialized, isElectron, state, apiEndpoint, apiUrl]
+ () => objectSpread({}, state, { api, apiEndpoint, apiError, apiRelay, apiUrl, extensions, isApiConnected, isApiInitialized, isElectron, isWaitingInjected: !extensions }),
+ [apiError, extensions, isApiConnected, isApiInitialized, isElectron, state, apiEndpoint, apiRelay, apiUrl]
);
// initial initialization
diff --git a/packages/react-api/src/types.ts b/packages/react-api/src/types.ts
index 0e8ea65502..20fdab04be 100644
--- a/packages/react-api/src/types.ts
+++ b/packages/react-api/src/types.ts
@@ -33,6 +33,7 @@ export interface ApiProps extends ApiState {
api: ApiPromise;
apiEndpoint: LinkOption | null;
apiError: string | null;
+ apiRelay: ApiPromise | null;
apiUrl?: string;
extensions?: InjectedExtension[];
isApiConnected: boolean;
diff --git a/packages/react-hooks/src/useApiUrl.ts b/packages/react-hooks/src/useApiUrl.ts
index 088c0f18fb..5b7c171a3d 100644
--- a/packages/react-hooks/src/useApiUrl.ts
+++ b/packages/react-hooks/src/useApiUrl.ts
@@ -1,11 +1,11 @@
// Copyright 2017-2021 @polkadot/react-hooks authors & contributors
// SPDX-License-Identifier: Apache-2.0
-import { useCallback, useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { ApiPromise, WsProvider } from '@polkadot/api';
import { typesBundle, typesChain } from '@polkadot/apps-config';
-import { isString } from '@polkadot/util';
+import { arrayShuffle, isString } from '@polkadot/util';
import { createNamedHook } from './createNamedHook';
import { useIsMountedRef } from './useIsMountedRef';
@@ -14,10 +14,18 @@ function disconnect (api: ApiPromise | null): void {
api && api.disconnect().catch(console.error);
}
-function useApiUrlImpl (url?: string | string[]): ApiPromise | null {
+function useApiUrlImpl (url?: null | string | string[]): ApiPromise | null {
const apiRef = useRef(null);
const mountedRef = useIsMountedRef();
const [state, setState] = useState(null);
+ const urls = useMemo(
+ () => url
+ ? isString(url)
+ ? [url]
+ : arrayShuffle(url.filter((u) => !u.startsWith('light://')))
+ : [],
+ [url]
+ );
useEffect((): () => void => {
return (): void => {
@@ -41,16 +49,16 @@ function useApiUrlImpl (url?: string | string[]): ApiPromise | null {
useEffect((): void => {
_setApi(null);
- url && (isString(url) || url.length) &&
+ urls.length &&
ApiPromise
.create({
- provider: new WsProvider(url),
+ provider: new WsProvider(urls),
typesBundle,
typesChain
})
.then(_setApi)
.catch(console.error);
- }, [_setApi, url]);
+ }, [_setApi, urls]);
return state;
}
diff --git a/packages/react-hooks/src/useCall.ts b/packages/react-hooks/src/useCall.ts
index 400b9d4648..d72c5d64fd 100644
--- a/packages/react-hooks/src/useCall.ts
+++ b/packages/react-hooks/src/useCall.ts
@@ -45,6 +45,7 @@ type CallFn = (...params: unknown[]) => Promise;
export type TrackFn = PromiseResult | QueryFn;
export interface Tracker {
+ fn: TrackFn | undefined | null | false;
isActive: boolean;
serialized: string | null;
subscriber: TrackFnResult | null;
@@ -140,7 +141,7 @@ function subscribe (mountedRef: MountedRef, tracker: TrackerRef, fn: TrackFn
// FIXME This is generic, we cannot really use createNamedHook
export function useCall (fn: TrackFn | undefined | null | false, params?: CallParams | null, options?: CallOptions): T | undefined {
const mountedRef = useIsMountedRef();
- const tracker = useRef({ isActive: false, serialized: null, subscriber: null });
+ const tracker = useRef({ fn: null, isActive: false, serialized: null, subscriber: null });
const [value, setValue] = useState((options || {}).defaultValue);
// initial effect, we need an un-subscription
@@ -154,7 +155,8 @@ export function useCall (fn: TrackFn | undefined | null | false, params?: Ca
if (mountedRef.current && fn) {
const [serialized, mappedParams] = extractParams(fn, params || [], options);
- if (mappedParams && serialized !== tracker.current.serialized) {
+ if (mappedParams && ((fn !== tracker.current.fn) || (serialized !== tracker.current.serialized))) {
+ tracker.current.fn = fn;
tracker.current.serialized = serialized;
subscribe(mountedRef, tracker, fn, mappedParams, setValue, options);
diff --git a/packages/react-hooks/src/useCallMulti.ts b/packages/react-hooks/src/useCallMulti.ts
index 776d2cf30a..2daf41afc6 100644
--- a/packages/react-hooks/src/useCallMulti.ts
+++ b/packages/react-hooks/src/useCallMulti.ts
@@ -68,7 +68,7 @@ function subscribe (api: ApiPromise, mountedRef: MountedRef, tracker: Tracke
export function useCallMulti (calls?: QueryableStorageMultiArg<'promise'>[] | null | false, options?: CallOptions): T {
const { api } = useApi();
const mountedRef = useIsMountedRef();
- const tracker = useRef({ isActive: false, serialized: null, subscriber: null });
+ const tracker = useRef({ fn: null, isActive: false, serialized: null, subscriber: null });
const [value, setValue] = useState(() => (options || {}).defaultValue || [] as unknown as T);
// initial effect, we need an un-subscription
diff --git a/packages/react-hooks/src/useSystemApi.ts b/packages/react-hooks/src/useSystemApi.ts
index 01907931cd..4c7b6014ae 100644
--- a/packages/react-hooks/src/useSystemApi.ts
+++ b/packages/react-hooks/src/useSystemApi.ts
@@ -3,11 +3,15 @@
import type { ApiPromise } from '@polkadot/api';
+import { useMemo } from 'react';
+
import { createNamedHook } from './createNamedHook';
import { useApi } from './useApi';
function useSystemApiImpl (): ApiPromise {
- return useApi().api;
+ const { api, apiRelay } = useApi();
+
+ return useMemo(() => apiRelay || api, [apiRelay, api]);
}
export const useSystemApi = createNamedHook('useSystemApi', useSystemApiImpl);
|