Cleanup details rendering (#151)

* Cleanup details rendering

* Pass request genesisHash to rendering
This commit is contained in:
Jaco Greeff 2019-09-15 20:47:53 +02:00 committed by GitHub
parent 149623d5bd
commit 1e248093c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 39 deletions

View File

@ -31,12 +31,15 @@ const chains: Map<string, Chain> = new Map(
);
const UNKNOWN_CHAIN: Chain = {
name: 'Any',
isUnknown: true,
name: 'Unknown chain',
specVersion: 0,
ss58Format: 42,
tokenDecimals: 0,
tokenSymbol: 'UNIT',
types: {}
types: {
Keys: 'SessionKeysSubstrate'
}
};
export default function findChain (genesisHash?: string | null): Chain {

View File

@ -5,9 +5,10 @@
import { Metadata } from '@polkadot/types';
export interface Chain {
name: string;
isUnknown?: boolean;
genesisHash?: string;
meta?: Metadata;
name: string;
specVersion: number;
ss58Format: number;
tokenDecimals: number;

View File

@ -3,19 +3,24 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Chain } from '@polkadot/extension-chains/types';
import { BlockNumber, ExtrinsicEra, ExtrinsicPayload } from '@polkadot/types/interfaces';
import { ExtrinsicEra, ExtrinsicPayload } from '@polkadot/types/interfaces';
import { SignerPayloadJSON } from '@polkadot/types/types';
import React from 'react';
import BN from 'bn.js';
import React, { useEffect, useRef, useState } from 'react';
import styled from 'styled-components';
import fromMetadata from '@polkadot/api-metadata/extrinsics/fromMetadata';
import findChain from '@polkadot/extension-chains';
import { createType, GenericCall, getTypeRegistry } from '@polkadot/types';
import { formatNumber } from '@polkadot/util';
import { GenericCall, getTypeRegistry } from '@polkadot/types';
import { formatNumber, bnToBn } from '@polkadot/util';
interface Decoded {
json: MethodJson | null;
method: GenericCall | null;
}
interface MethodJson {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
args: Record<string, any>;
args: Record<string, string>;
}
interface Props {
@ -26,29 +31,34 @@ interface Props {
url: string;
}
function renderMethod (data: string, isDecoded: boolean, chain?: Chain): React.ReactNode {
const base = (
<tr>
<td className='label'>method data</td>
<td className='data'>{data}</td>
</tr>
);
if (!isDecoded || !chain || !chain.meta) {
return base;
}
let json: MethodJson;
let method: GenericCall;
function decodeMethod (data: string, isDecoded: boolean, chain: Chain, specVersion: BN): Decoded {
let json: MethodJson | null = null;
let method: GenericCall | null = null;
try {
getTypeRegistry().register(chain.types);
GenericCall.injectMethods(fromMetadata(chain.meta));
if (isDecoded && chain.meta && specVersion.eqn(chain.specVersion)) {
getTypeRegistry().register(chain.types);
GenericCall.injectMethods(fromMetadata(chain.meta));
method = new GenericCall(data);
json = method.toJSON() as unknown as MethodJson;
method = new GenericCall(data);
json = method.toJSON() as unknown as MethodJson;
}
} catch (error) {
return base;
json = null;
method = null;
}
return { json, method };
}
function renderMethod (data: string, { json, method }: Decoded): React.ReactNode {
if (!json || !method) {
return (
<tr>
<td className='label'>method data</td>
<td className='data'>{data}</td>
</tr>
);
}
return (
@ -75,21 +85,25 @@ function renderMethod (data: string, isDecoded: boolean, chain?: Chain): React.R
);
}
function renderMortality (era: ExtrinsicEra, blockNumber: BlockNumber): string {
function mortalityAsString (era: ExtrinsicEra, hexBlockNumber: string): string {
if (era.isImmortalEra) {
return 'immortal';
}
const blockNumber = bnToBn(hexBlockNumber);
const mortal = era.asMortalEra;
return `mortal, valid from #${formatNumber(mortal.birth(blockNumber))} to #${formatNumber(mortal.death(blockNumber))}`;
}
function Details ({ className, isDecoded, payload, request, url }: Props): React.ReactElement<Props> {
const blockNumber = createType('BlockNumber', request.blockNumber);
const { genesisHash, method } = request;
const { era, nonce, tip } = payload;
const chain = findChain(genesisHash);
function Details ({ className, isDecoded, payload: { era, nonce, tip }, request: { blockNumber, genesisHash, method, specVersion: hexSpec }, url }: Props): React.ReactElement<Props> {
const chain = useRef(findChain(genesisHash)).current;
const specVersion = useRef(bnToBn(hexSpec)).current;
const [decoded, setDecoded] = useState<Decoded>({ json: null, method: null });
useEffect((): void => {
setDecoded(decodeMethod(method, isDecoded, chain, specVersion));
}, [isDecoded]);
return (
<table className={className}>
@ -99,8 +113,12 @@ function Details ({ className, isDecoded, payload, request, url }: Props): React
<td className='data'>{url}</td>
</tr>
<tr>
<td className='label'>{chain ? 'chain' : 'genesis'}</td>
<td className='data'>{chain ? chain.name : genesisHash}</td>
<td className='label'>{chain.isUnknown ? 'genesis' : 'chain'}</td>
<td className='data'>{chain.isUnknown ? genesisHash : chain.name}</td>
</tr>
<tr>
<td className='label'>version</td>
<td className='data'>{specVersion.toNumber()}</td>
</tr>
<tr>
<td className='label'>nonce</td>
@ -112,10 +130,10 @@ function Details ({ className, isDecoded, payload, request, url }: Props): React
<td className='data'>{formatNumber(tip)}</td>
</tr>
)}
{renderMethod(method, isDecoded, chain)}
{renderMethod(method, decoded)}
<tr>
<td className='label'>lifetime</td>
<td className='data'>{renderMortality(era, blockNumber)}</td>
<td className='data'>{mortalityAsString(era, blockNumber)}</td>
</tr>
</tbody>
</table>

View File

@ -48,7 +48,10 @@ export default function Request ({ account: { isExternal }, isFirst, request, si
.catch((error: Error) => console.error(error));
return (
<Address address={request.address}>
<Address
address={request.address}
genesisHash={request.genesisHash}
>
{isExternal && isFirst
? <Qr
payload={payload}