API cleanups (#2139)
* API cleanups * Revert ready setting * ... oops * Adjust dropdown right margin * API -> functional
This commit is contained in:
parent
f95cb193ce
commit
e9de3cf489
@ -245,7 +245,6 @@ export default styled(Playground)`
|
||||
}
|
||||
|
||||
.js--Dropdown {
|
||||
margin-right: 100px;
|
||||
position: relative;
|
||||
z-index: 200;
|
||||
|
||||
|
||||
@ -2,14 +2,12 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ProviderInterface } from '@polkadot/rpc-provider/types';
|
||||
import { QueueTxPayloadAdd, QueueTxMessageSetStatus } from '@polkadot/react-components/Status/types';
|
||||
import { ApiProps } from './types';
|
||||
import { ApiState } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import ApiPromise from '@polkadot/api/promise';
|
||||
import { isWeb3Injected, web3Accounts, web3Enable } from '@polkadot/extension-dapp';
|
||||
import defaults from '@polkadot/rpc-provider/defaults';
|
||||
import { WsProvider } from '@polkadot/rpc-provider';
|
||||
import { TokenUnit } from '@polkadot/react-components/InputNumber';
|
||||
import keyring from '@polkadot/ui-keyring';
|
||||
@ -31,7 +29,7 @@ interface Props {
|
||||
url?: string;
|
||||
}
|
||||
|
||||
interface State extends ApiProps {
|
||||
interface State extends ApiState {
|
||||
chain?: string | null;
|
||||
}
|
||||
|
||||
@ -50,163 +48,100 @@ let api: ApiPromise;
|
||||
|
||||
export { api };
|
||||
|
||||
export default class Api extends React.PureComponent<Props, State> {
|
||||
public state: State = {} as unknown as State;
|
||||
async function loadOnReady (api: ApiPromise): Promise<State> {
|
||||
const [properties, _systemChain, _systemName, _systemVersion, injectedAccounts] = await Promise.all([
|
||||
api.rpc.system.properties(),
|
||||
api.rpc.system.chain(),
|
||||
api.rpc.system.name(),
|
||||
api.rpc.system.version(),
|
||||
web3Accounts().then((accounts): InjectedAccountExt[] =>
|
||||
accounts.map(({ address, meta }): InjectedAccountExt => ({
|
||||
address,
|
||||
meta: {
|
||||
...meta,
|
||||
name: `${meta.name} (${meta.source === 'polkadot-js' ? 'extension' : meta.source})`
|
||||
}
|
||||
}))
|
||||
)
|
||||
]);
|
||||
const ss58Format = uiSettings.prefix === -1
|
||||
? properties.ss58Format.unwrapOr(DEFAULT_SS58).toNumber()
|
||||
: uiSettings.prefix;
|
||||
const tokenSymbol = properties.tokenSymbol.unwrapOr('DEV').toString();
|
||||
const tokenDecimals = properties.tokenDecimals.unwrapOr(DEFAULT_DECIMALS).toNumber();
|
||||
const systemChain = _systemChain
|
||||
? _systemChain.toString()
|
||||
: '<unknown>';
|
||||
const isDevelopment = isTestChain(systemChain);
|
||||
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
console.log('api: found chain', systemChain, JSON.stringify(properties));
|
||||
|
||||
const { queuePayload, queueSetTxStatus, url } = props;
|
||||
// first setup the UI helpers
|
||||
formatBalance.setDefaults({
|
||||
decimals: tokenDecimals,
|
||||
unit: tokenSymbol
|
||||
});
|
||||
TokenUnit.setAbbr(tokenSymbol);
|
||||
|
||||
// finally load the keyring
|
||||
keyring.loadAll({
|
||||
addressPrefix: ss58Format,
|
||||
genesisHash: api.genesisHash,
|
||||
isDevelopment,
|
||||
ss58Format,
|
||||
type: 'ed25519'
|
||||
}, injectedAccounts);
|
||||
|
||||
const defaultSection = Object.keys(api.tx)[0];
|
||||
const defaultMethod = Object.keys(api.tx[defaultSection])[0];
|
||||
const apiDefaultTx = api.tx[defaultSection][defaultMethod];
|
||||
const apiDefaultTxSudo = (api.tx.system && api.tx.system.setCode) || apiDefaultTx;
|
||||
const isSubstrateV2 = !!Object.keys(api.consts).length;
|
||||
|
||||
return {
|
||||
apiDefaultTx,
|
||||
apiDefaultTxSudo,
|
||||
isApiReady: true,
|
||||
isDevelopment,
|
||||
isSubstrateV2,
|
||||
systemChain,
|
||||
systemName: _systemName.toString(),
|
||||
systemVersion: _systemVersion.toString()
|
||||
} as State;
|
||||
}
|
||||
|
||||
export default function Api ({ children, queuePayload, queueSetTxStatus, url }: Props): React.ReactElement<Props> | null {
|
||||
const [state, setState] = useState<State>({ isApiReady: false } as Partial<State> as State);
|
||||
const [isApiConnected, setIsApiConnected] = useState(false);
|
||||
const [isWaitingInjected, setIsWaitingInjected] = useState(isWeb3Injected);
|
||||
|
||||
// initial initialization
|
||||
useEffect((): void => {
|
||||
const provider = new WsProvider(url);
|
||||
const signer = new ApiSigner(queuePayload, queueSetTxStatus);
|
||||
|
||||
const setApi = (provider: ProviderInterface): void => {
|
||||
api = this.createApi(provider, signer);
|
||||
|
||||
this.setState({ api }, (): void => {
|
||||
this.subscribeEvents();
|
||||
});
|
||||
};
|
||||
const setApiUrl = (url: string = defaults.WS_URL): void =>
|
||||
setApi(new WsProvider(url));
|
||||
|
||||
api = this.createApi(provider, signer);
|
||||
|
||||
this.state = {
|
||||
api,
|
||||
isApiConnected: false,
|
||||
isApiReady: false,
|
||||
isSubstrateV2: true,
|
||||
isWaitingInjected: isWeb3Injected,
|
||||
setApiUrl
|
||||
} as unknown as State;
|
||||
}
|
||||
|
||||
private createApi (provider: ProviderInterface, signer: ApiSigner): ApiPromise {
|
||||
return new ApiPromise({
|
||||
provider,
|
||||
registry,
|
||||
signer,
|
||||
typesChain,
|
||||
typesSpec
|
||||
});
|
||||
}
|
||||
|
||||
public componentDidMount (): void {
|
||||
this.subscribeEvents();
|
||||
|
||||
injectedPromise
|
||||
.then((): void => this.setState({ isWaitingInjected: false }))
|
||||
.catch((error: Error) => console.error(error));
|
||||
}
|
||||
|
||||
private subscribeEvents (): void {
|
||||
const { api } = this.state;
|
||||
|
||||
api.on('connected', (): void => {
|
||||
this.setState({ isApiConnected: true });
|
||||
});
|
||||
|
||||
api.on('disconnected', (): void => {
|
||||
this.setState({ isApiConnected: false });
|
||||
});
|
||||
api = new ApiPromise({ provider, registry, signer, typesChain, typesSpec });
|
||||
|
||||
api.on('connected', (): void => setIsApiConnected(true));
|
||||
api.on('disconnected', (): void => setIsApiConnected(false));
|
||||
api.on('ready', async (): Promise<void> => {
|
||||
try {
|
||||
await this.loadOnReady(api);
|
||||
setState(await loadOnReady(api));
|
||||
} catch (error) {
|
||||
console.error('Unable to load chain', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async loadOnReady (api: ApiPromise): Promise<void> {
|
||||
const [properties, _systemChain, _systemName, _systemVersion, injectedAccounts] = await Promise.all([
|
||||
api.rpc.system.properties(),
|
||||
api.rpc.system.chain(),
|
||||
api.rpc.system.name(),
|
||||
api.rpc.system.version(),
|
||||
web3Accounts().then((accounts): InjectedAccountExt[] =>
|
||||
accounts.map(({ address, meta }): InjectedAccountExt => ({
|
||||
address,
|
||||
meta: {
|
||||
...meta,
|
||||
name: `${meta.name} (${meta.source === 'polkadot-js' ? 'extension' : meta.source})`
|
||||
}
|
||||
}))
|
||||
)
|
||||
]);
|
||||
const ss58Format = uiSettings.prefix === -1
|
||||
? properties.ss58Format.unwrapOr(DEFAULT_SS58).toNumber()
|
||||
: uiSettings.prefix;
|
||||
const tokenSymbol = properties.tokenSymbol.unwrapOr('DEV').toString();
|
||||
const tokenDecimals = properties.tokenDecimals.unwrapOr(DEFAULT_DECIMALS).toNumber();
|
||||
const systemChain = _systemChain
|
||||
? _systemChain.toString()
|
||||
: '<unknown>';
|
||||
const isDevelopment = isTestChain(systemChain);
|
||||
injectedPromise
|
||||
.then((): void => setIsWaitingInjected(false))
|
||||
.catch((error: Error) => console.error(error));
|
||||
}, []);
|
||||
|
||||
console.log('api: found chain', systemChain, JSON.stringify(properties));
|
||||
|
||||
// first setup the UI helpers
|
||||
formatBalance.setDefaults({
|
||||
decimals: tokenDecimals,
|
||||
unit: tokenSymbol
|
||||
});
|
||||
TokenUnit.setAbbr(tokenSymbol);
|
||||
|
||||
// finally load the keyring
|
||||
keyring.loadAll({
|
||||
addressPrefix: ss58Format,
|
||||
genesisHash: api.genesisHash,
|
||||
isDevelopment,
|
||||
ss58Format,
|
||||
type: 'ed25519'
|
||||
}, injectedAccounts);
|
||||
|
||||
const defaultSection = Object.keys(api.tx)[0];
|
||||
const defaultMethod = Object.keys(api.tx[defaultSection])[0];
|
||||
const apiDefaultTx = api.tx[defaultSection][defaultMethod];
|
||||
const apiDefaultTxSudo =
|
||||
(api.tx.system && api.tx.system.setCode) || // 2.x
|
||||
(api.tx.consensus && api.tx.consensus.setCode) || // 1.x
|
||||
apiDefaultTx; // other
|
||||
const isSubstrateV2 = !!Object.keys(api.consts).length;
|
||||
|
||||
this.setState({
|
||||
apiDefaultTx,
|
||||
apiDefaultTxSudo,
|
||||
isApiReady: true,
|
||||
isDevelopment,
|
||||
isSubstrateV2,
|
||||
systemChain,
|
||||
systemName: _systemName.toString(),
|
||||
systemVersion: _systemVersion.toString()
|
||||
});
|
||||
}
|
||||
|
||||
public render (): React.ReactNode {
|
||||
const { api, apiDefaultTx, apiDefaultTxSudo, isApiConnected, isApiReady, isDevelopment, isSubstrateV2, isWaitingInjected, setApiUrl, systemChain, systemName, systemVersion } = this.state;
|
||||
|
||||
return (
|
||||
<ApiContext.Provider
|
||||
value={{
|
||||
api,
|
||||
apiDefaultTx,
|
||||
apiDefaultTxSudo,
|
||||
isApiConnected,
|
||||
isApiReady: isApiReady && !!systemChain,
|
||||
isDevelopment,
|
||||
isSubstrateV2,
|
||||
isWaitingInjected,
|
||||
setApiUrl,
|
||||
systemChain,
|
||||
systemName,
|
||||
systemVersion
|
||||
}}
|
||||
>
|
||||
{this.props.children}
|
||||
return api
|
||||
? (
|
||||
<ApiContext.Provider value={{ ...state, api, isApiConnected, isWaitingInjected }}>
|
||||
{children}
|
||||
</ApiContext.Provider>
|
||||
);
|
||||
}
|
||||
)
|
||||
: null;
|
||||
}
|
||||
|
||||
@ -15,21 +15,23 @@ export interface BareProps {
|
||||
style?: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface ApiProps {
|
||||
api: ApiPromise;
|
||||
export interface ApiState {
|
||||
apiDefaultTx: SubmittableExtrinsicFunction;
|
||||
apiDefaultTxSudo: SubmittableExtrinsicFunction;
|
||||
isApiConnected: boolean;
|
||||
isApiReady: boolean;
|
||||
isDevelopment: boolean;
|
||||
isSubstrateV2: boolean;
|
||||
isWaitingInjected: boolean;
|
||||
setApiUrl: (url?: string) => void;
|
||||
systemChain: string;
|
||||
systemName: string;
|
||||
systemVersion: string;
|
||||
}
|
||||
|
||||
export interface ApiProps extends ApiState {
|
||||
api: ApiPromise;
|
||||
isWaitingInjected: boolean;
|
||||
isApiConnected: boolean;
|
||||
}
|
||||
|
||||
export interface OnChangeCbObs {
|
||||
next: (value?: any) => any;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user