Add endpoint fallbacks option and handling of consts to ui-api (#1416)
* Add `fallback` option to ui-api to pass more than one endpoint for backwards compatibility * set correct endpoint * remove console.logs * linting issues * const -> consts typo * changed query example to blockPeriod * turn `fallback`: string[] | string into fallbacks array * turn while loop into map * less params & removed let * Adjust withCall typing, don't allow voting in treasury
This commit is contained in:
parent
bfdb6d6cd7
commit
7d451c6f88
@ -16,7 +16,7 @@ import translate from '../translate';
|
||||
|
||||
type Props = ApiProps & I18nProps & {
|
||||
codeHash?: string | null;
|
||||
contract_codeStorage?: Option<PrefabWasmModule>;
|
||||
contracts_codeStorage?: Option<PrefabWasmModule>;
|
||||
onChange: (isValid: boolean) => void;
|
||||
};
|
||||
|
||||
@ -33,9 +33,9 @@ class ValidateCode extends React.PureComponent<Props> {
|
||||
isValid: false
|
||||
};
|
||||
|
||||
public static getDerivedStateFromProps ({ codeHash, contract_codeStorage, onChange }: Props): State {
|
||||
public static getDerivedStateFromProps ({ codeHash, contracts_codeStorage, onChange }: Props): State {
|
||||
const isValidHex = !!codeHash && isHex(codeHash) && codeHash.length === 66;
|
||||
const isStored = !!contract_codeStorage && contract_codeStorage.isSome;
|
||||
const isStored = !!contracts_codeStorage && contracts_codeStorage.isSome;
|
||||
const isValid = isValidHex && isStored;
|
||||
|
||||
// FIXME Really not convinced this is the correct place to do this type of callback?
|
||||
@ -70,7 +70,6 @@ class ValidateCode extends React.PureComponent<Props> {
|
||||
|
||||
export default translate(
|
||||
withCalls<Props>(
|
||||
['query.contracts.codeStorage', { paramName: 'codeHash' }], // 2.x
|
||||
['query.contract.codeStorage', { paramName: 'codeHash' }] // 1.x
|
||||
['query.contracts.codeStorage', { fallbacks: ['query.contract.codeStorage'], paramName: 'codeHash' }]
|
||||
)(ValidateCode)
|
||||
);
|
||||
|
||||
@ -16,7 +16,7 @@ import translate from '../translate';
|
||||
|
||||
type Props = ApiProps & I18nProps & {
|
||||
address?: string | null;
|
||||
contract_contractInfoOf?: Option<ContractInfo>;
|
||||
contracts_contractInfoOf?: Option<ContractInfo>;
|
||||
onChange: (isValid: boolean) => void;
|
||||
};
|
||||
|
||||
@ -33,7 +33,7 @@ class ValidateAddr extends React.PureComponent<Props> {
|
||||
isValid: false
|
||||
};
|
||||
|
||||
public static getDerivedStateFromProps ({ address, contract_contractInfoOf, onChange }: Props): State {
|
||||
public static getDerivedStateFromProps ({ address, contracts_contractInfoOf, onChange }: Props): State {
|
||||
let isValidAddr = false;
|
||||
|
||||
try {
|
||||
@ -45,7 +45,7 @@ class ValidateAddr extends React.PureComponent<Props> {
|
||||
}
|
||||
|
||||
const isStored = (
|
||||
(!!contract_contractInfoOf && contract_contractInfoOf.isSome)
|
||||
(!!contracts_contractInfoOf && contracts_contractInfoOf.isSome)
|
||||
// (!!contract_codeHashOf && contract_codeHashOf.isSome)
|
||||
);
|
||||
const isValid = isValidAddr && isStored;
|
||||
@ -82,7 +82,6 @@ class ValidateAddr extends React.PureComponent<Props> {
|
||||
|
||||
export default translate(
|
||||
withCalls<Props>(
|
||||
['query.contracts.contractInfoOf', { paramName: 'address' }], // 2.x
|
||||
['query.contract.contractInfoOf', { paramName: 'address' }] // 1.x
|
||||
['query.contracts.contractInfoOf', { fallbacks: ['query.contract.contractInfoOf'], paramName: 'address' }]
|
||||
)(ValidateAddr)
|
||||
);
|
||||
|
||||
@ -29,7 +29,7 @@ interface Props extends I18nProps {
|
||||
idNumber: BN;
|
||||
chain_bestNumber?: BN;
|
||||
democracy_referendumVotesFor?: DerivedReferendumVote[];
|
||||
democracy_publicDelay?: BN;
|
||||
democracy_enactmentPeriod: BN;
|
||||
value: ReferendumInfoExtended;
|
||||
}
|
||||
|
||||
@ -111,13 +111,13 @@ class Referendum extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
private renderInfo (): React.ReactNode {
|
||||
const { chain_bestNumber, democracy_publicDelay, t, value: { end, threshold } } = this.props;
|
||||
const { chain_bestNumber, democracy_enactmentPeriod, t, value: { end, threshold } } = this.props;
|
||||
|
||||
if (!chain_bestNumber) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const enactBlock = (democracy_publicDelay || new BN(0)).add(end);
|
||||
const enactBlock = (democracy_enactmentPeriod || new BN(0)).add(end);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -193,6 +193,6 @@ export default withMulti(
|
||||
withCalls<Props>(
|
||||
'derive.chain.bestNumber',
|
||||
['derive.democracy.referendumVotesFor', { paramName: 'idNumber' }],
|
||||
'query.democracy.publicDelay'
|
||||
['consts.democracy.enactmentPeriod', { fallbacks: ['query.democracy.publicDelay'] }]
|
||||
)
|
||||
);
|
||||
|
||||
@ -17,14 +17,20 @@ interface Props extends I18nProps {
|
||||
chain_bestNumber?: BN;
|
||||
democracy_launchPeriod?: BN;
|
||||
democracy_nextTally?: BN;
|
||||
democracy_publicDelay?: BN;
|
||||
democracy_publicPropCount?: BN;
|
||||
democracy_referendumCount?: BN;
|
||||
}
|
||||
|
||||
class Summary extends React.PureComponent<Props> {
|
||||
public render (): React.ReactNode {
|
||||
const { chain_bestNumber = new BN(0), democracy_launchPeriod = new BN(1), democracy_nextTally = new BN(0), democracy_publicPropCount, democracy_referendumCount = new BN(0), t } = this.props;
|
||||
const {
|
||||
chain_bestNumber = new BN(0),
|
||||
democracy_launchPeriod = new BN(1),
|
||||
democracy_nextTally = new BN(0),
|
||||
democracy_publicPropCount,
|
||||
democracy_referendumCount = new BN(0),
|
||||
t
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<SummaryBox>
|
||||
@ -55,7 +61,7 @@ class Summary extends React.PureComponent<Props> {
|
||||
|
||||
export default translate(
|
||||
withCalls<Props>(
|
||||
'query.democracy.launchPeriod',
|
||||
['consts.democracy.launchPeriod', { fallbacks: ['query.democracy.launchPeriod'] }],
|
||||
'query.democracy.nextTally',
|
||||
'query.democracy.publicPropCount',
|
||||
'query.democracy.referendumCount',
|
||||
|
||||
@ -11,13 +11,14 @@ export const storageGetInfo: Snippet = {
|
||||
code: `// Get chain state information
|
||||
// Make our basic chain state/storage queries, all in one go
|
||||
|
||||
const [minimumPeriod, validators, transferFee] = await Promise.all([
|
||||
api.query.timestamp.minimumPeriod(),
|
||||
api.query.session.validators(),
|
||||
api.query.balances.transferFee()
|
||||
const [minimumValidatorCount, validators] = await Promise.all([
|
||||
api.query.staking.minimumValidatorCount(),
|
||||
api.query.session.validators()
|
||||
]);
|
||||
|
||||
console.log('minimum period between blocks: ' + minimumPeriod);
|
||||
const transferFee = api.consts.balances.transferFee;
|
||||
|
||||
console.log('The minimum validator count: ' + minimumValidatorCount);
|
||||
console.log('transfer fee: ', transferFee);
|
||||
|
||||
if (validators && validators.length > 0) {
|
||||
|
||||
@ -50,7 +50,13 @@ class Approve extends TxModal<Props, State> {
|
||||
}
|
||||
|
||||
protected renderTrigger = (): React.ReactNode => {
|
||||
const { t } = this.props;
|
||||
const { api, t } = this.props;
|
||||
|
||||
// disable voting for 1.x (we only use elections here)
|
||||
if (!api.query.elections) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='ui--Row-buttons'>
|
||||
<Button.Group>
|
||||
@ -100,13 +106,10 @@ export default withMulti(
|
||||
translate,
|
||||
withApi,
|
||||
withCalls(
|
||||
[
|
||||
'query.elections.members',
|
||||
{
|
||||
propName: 'threshold',
|
||||
transform: (value: [AccountId, BlockNumber][]): number =>
|
||||
1 + (value.length / 2)
|
||||
}
|
||||
]
|
||||
['query.elections.members', {
|
||||
propName: 'threshold',
|
||||
transform: (value: [AccountId, BlockNumber][]): number =>
|
||||
1 + (value.length / 2)
|
||||
}]
|
||||
)
|
||||
);
|
||||
|
||||
@ -201,10 +201,10 @@ export default withMulti(
|
||||
Settings,
|
||||
translate,
|
||||
withCalls<Props>(
|
||||
['query.treasury.proposalBond', { propName: 'proposalBond' }],
|
||||
['query.treasury.proposalBondMinimum', { propName: 'proposalBondMinimum' }],
|
||||
['query.treasury.spendPeriod', { propName: 'spendPeriod' }],
|
||||
['query.treasury.burn', { propName: 'burn' }],
|
||||
['consts.treasury.proposalBond', { fallbacks: ['query.treasury.proposalBond'], propName: 'proposalBond' }],
|
||||
['consts.treasury.proposalBondMinimum', { fallbacks: ['query.treasury.proposalBondMinimum'], propName: 'proposalBondMinimum' }],
|
||||
['consts.treasury.spendPeriod', { fallbacks: ['query.treasury.spendPeriod'], propName: 'spendPeriod' }],
|
||||
['consts.treasury.burn', { fallbacks: ['query.treasury.burn'], propName: 'burn' }],
|
||||
['query.treasury.pot', { propName: 'pot' }]
|
||||
)
|
||||
);
|
||||
|
||||
@ -12,13 +12,15 @@ import { isEqual, triggerChange } from '../util';
|
||||
import echoTransform from '../transform/echo';
|
||||
import withApi from './api';
|
||||
|
||||
// FIXME This is not correct, we need some junction of derive, query & consts
|
||||
interface Method {
|
||||
(...params: any[]): Promise<any>;
|
||||
at: (hash: Uint8Array | string, ...params: any[]) => Promise<any>;
|
||||
meta: any;
|
||||
multi: (params: any[], cb: (value?: any) => void) => Promise<any>;
|
||||
}
|
||||
|
||||
type ApiMethodInfo = [Method, any[], boolean];
|
||||
type ApiMethodInfo = [Method, any[], string];
|
||||
|
||||
type State = CallState;
|
||||
|
||||
@ -26,7 +28,21 @@ const NOOP = (): void => {
|
||||
// ignore
|
||||
};
|
||||
|
||||
export default function withCall<P extends ApiProps> (endpoint: string, { at, atProp, callOnResult, isMulti = false, params = [], paramName, paramPick, paramValid = false, propName, transform = echoTransform }: Options = {}): (Inner: React.ComponentType<ApiProps>) => React.ComponentType<any> {
|
||||
export default function withCall<P extends ApiProps> (
|
||||
endpoint: string,
|
||||
{
|
||||
at,
|
||||
atProp,
|
||||
callOnResult,
|
||||
fallbacks,
|
||||
isMulti = false,
|
||||
params = [],
|
||||
paramName,
|
||||
paramPick,
|
||||
paramValid = false,
|
||||
propName,
|
||||
transform = echoTransform
|
||||
}: Options = {}): (Inner: React.ComponentType<ApiProps>) => React.ComponentType<any> {
|
||||
return (Inner: React.ComponentType<ApiProps>): React.ComponentType<SubtractProps<P, ApiProps>> => {
|
||||
class WithPromise extends React.Component<P, State> {
|
||||
public state: State = {
|
||||
@ -122,30 +138,43 @@ export default function withCall<P extends ApiProps> (endpoint: string, { at, at
|
||||
? paramValue
|
||||
: [paramValue]
|
||||
);
|
||||
|
||||
return [true, values];
|
||||
}
|
||||
|
||||
private getApiMethod (newParams: any[]): ApiMethodInfo {
|
||||
private constructApiSection = (endpoint: string): [Record<string, Method>, string, string, string] => {
|
||||
const { api } = this.props;
|
||||
const [area, section, method, ...others] = endpoint.split('.');
|
||||
|
||||
assert(area.length && section.length && method.length && others.length === 0, `Invalid API format, expected <area>.<section>.<method>, found ${endpoint}`);
|
||||
assert(['consts', 'rpc', 'query', 'derive'].includes(area), `Unknown api.${area}, expected consts, rpc, query or derive`);
|
||||
assert(!at || area === 'query', `Only able to do an 'at' query on the api.query interface`);
|
||||
|
||||
const apiSection = (api as any)[area][section];
|
||||
|
||||
return [
|
||||
apiSection,
|
||||
area,
|
||||
section,
|
||||
method
|
||||
];
|
||||
}
|
||||
|
||||
private getApiMethod (newParams: any[]): ApiMethodInfo {
|
||||
if (endpoint === 'subscribe') {
|
||||
const [fn, ...params] = newParams;
|
||||
|
||||
return [
|
||||
fn,
|
||||
params,
|
||||
true
|
||||
'subscribe'
|
||||
];
|
||||
}
|
||||
|
||||
const [area, section, method, ...others] = endpoint.split('.');
|
||||
|
||||
assert(area.length && section.length && method.length && others.length === 0, `Invalid API format, expected <area>.<section>.<method>, found ${endpoint}`);
|
||||
assert(['rpc', 'query', 'derive'].includes(area), `Unknown api.${area}, expected rpc, query or derive`);
|
||||
assert(!at || area === 'query', `Only able to do an 'at' query on the api.query interface`);
|
||||
|
||||
const apiSection = (api as any)[area][section];
|
||||
const endpoints: string[] = [endpoint].concat(fallbacks || []);
|
||||
const expanded = endpoints.map(this.constructApiSection);
|
||||
const [apiSection, area, section, method] = expanded.find(([apiSection]): boolean =>
|
||||
!!apiSection
|
||||
) || [{}, expanded[0][1], expanded[0][2], expanded[0][3]];
|
||||
|
||||
assert(apiSection && apiSection[method], `Unable to find api.${area}.${section}.${method}`);
|
||||
|
||||
@ -160,7 +189,7 @@ export default function withCall<P extends ApiProps> (endpoint: string, { at, at
|
||||
return [
|
||||
apiSection[method],
|
||||
newParams,
|
||||
area === 'derive' || (area === 'query' && (!at && !atProp)) || method.startsWith('subscribe')
|
||||
method.startsWith('subscribe') ? 'subscribe' : area
|
||||
];
|
||||
}
|
||||
|
||||
@ -186,17 +215,19 @@ export default function withCall<P extends ApiProps> (endpoint: string, { at, at
|
||||
return;
|
||||
}
|
||||
|
||||
const [apiMethod, params, isSubscription] = info;
|
||||
const [apiMethod, params, area] = info;
|
||||
const updateCb = (value?: any): void =>
|
||||
this.triggerUpdate(this.props, value);
|
||||
|
||||
await this.unsubscribe();
|
||||
|
||||
try {
|
||||
if (isSubscription) {
|
||||
if (['derive', 'subscribe'].includes(area) || (area === 'query' && (!at && !atProp))) {
|
||||
this.destroy = isMulti
|
||||
? await apiMethod.multi(params, updateCb)
|
||||
: await apiMethod(...params, updateCb);
|
||||
} else if (area === 'consts') {
|
||||
updateCb(apiMethod);
|
||||
} else {
|
||||
updateCb(
|
||||
at
|
||||
|
||||
@ -17,6 +17,7 @@ export interface Options {
|
||||
at?: Uint8Array | string;
|
||||
atProp?: string;
|
||||
callOnResult?: OnChangeCb;
|
||||
fallbacks?: string[];
|
||||
isMulti?: boolean;
|
||||
params?: any[];
|
||||
paramName?: string;
|
||||
|
||||
@ -35,7 +35,11 @@ export class Proposal extends React.PureComponent<Props, State> {
|
||||
isBelowMinimum: false
|
||||
};
|
||||
|
||||
public static getDerivedStateFromProps ({ deposit, democracy_minimumDeposit = new BN(0), onChange }: Props): State {
|
||||
public static getDerivedStateFromProps ({
|
||||
deposit,
|
||||
democracy_minimumDeposit = new BN(0),
|
||||
onChange
|
||||
}: Props): State {
|
||||
const extraAmount = deposit instanceof Compact
|
||||
? deposit.toBn()
|
||||
: deposit;
|
||||
@ -87,5 +91,7 @@ export class Proposal extends React.PureComponent<Props, State> {
|
||||
export default withMulti(
|
||||
Proposal,
|
||||
translate,
|
||||
withCalls<Props>('query.democracy.minimumDeposit')
|
||||
withCalls<Props>(
|
||||
['consts.democracy.minimumDeposit', { fallbacks: ['query.democracy.minimumDeposit'] }]
|
||||
)
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user