* Add typings to messages * Fix eslint (after merge) * Mobile signer support (via Qr) * Bump common * Pass through genesisHash * Ok, well, it does something... not recognized * Bump ui * Exclude build from lint * ** * Display accounts with prefix from genesisHash * Adapth for object via scan interface * Bump deps * Split address recoding * Cleanup decoding readability * Display chain affinity overlay * -1 prefix dropdown description * Add generator command * Fix TypeScript error * Lint * Consistent naming * Better promise error handling * Small consistency updates * Constraint handle typings as much as tsc will allow * State naming * Typo in cheain descriptions * Add signature handler (unused) * e2e roundtrip * remove (useless) dev 0.5.1 chain * Insert ActionBar * Revert to empty Props interfaces * SeedLengths type * Add type to transport subscription message * nit * Typecheck passing callback to sendMessage when none expected * Bump api * Small lint fixes * Bump api * Not sure it works... but linting passes * Split public/private * Alphabetical * Don't show button on no media * Remove unneeded resolve - NOT hacking around linting * Pass edited name through to accounts component * genesisHash alignments * Remove KeyringJson * SignRequest with account * Align with master naming * Some manual merges * Manual (small) conflict resolution * Fixup extension account mapping * Remove ununsed messages (less code = better) * Update comment around generation * Add copy-to-apps script (debugging)
107 lines
3.2 KiB
TypeScript
107 lines
3.2 KiB
TypeScript
// Copyright 2019 @polkadot/extension-ui authors & contributors
|
|
// This software may be modified and distributed under the terms
|
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
|
|
|
import { AccountJson } from '@polkadot/extension/background/types';
|
|
import { Chain } from '@polkadot/extension-chains/types';
|
|
import { Prefix } from '@polkadot/util-crypto/address/types';
|
|
|
|
import React, { useContext, useEffect, useState } from 'react';
|
|
import styled from 'styled-components';
|
|
import findChain from '@polkadot/extension-chains';
|
|
import Identicon from '@polkadot/react-identicon';
|
|
import settings from '@polkadot/ui-settings';
|
|
import { decodeAddress, encodeAddress } from '@polkadot/util-crypto';
|
|
|
|
import IconBox from './IconBox';
|
|
import { AccountContext } from './contexts';
|
|
|
|
interface Props {
|
|
address?: string | null;
|
|
children?: React.ReactNode;
|
|
className?: string;
|
|
name?: React.ReactNode | null;
|
|
genesisHash?: string | null;
|
|
theme?: 'polkadot' | 'substrate';
|
|
}
|
|
|
|
// find an account in our list
|
|
function findAccount (accounts: AccountJson[], publicKey: Uint8Array): AccountJson | null {
|
|
const pkStr = publicKey.toString();
|
|
|
|
return accounts.find(({ address }): boolean =>
|
|
decodeAddress(address).toString() === pkStr
|
|
) || null;
|
|
}
|
|
|
|
// recodes an supplied address using the prefix/genesisHash, include the actual saved account & chain
|
|
function recodeAddress (address: string, accounts: AccountJson[], genesisHash?: string | null): [string, AccountJson | null, Chain] {
|
|
// decode and create a shortcut for the encoded address
|
|
const publicKey = decodeAddress(address);
|
|
|
|
// find our account using the actual publicKey, and then find the associated chain
|
|
const account = findAccount(accounts, publicKey);
|
|
const chain = findChain((account && account.genesisHash) || genesisHash);
|
|
|
|
return [
|
|
// always allow the actual settings to override the display
|
|
encodeAddress(publicKey, (settings.prefix === -1 ? chain.ss58Format : settings.prefix) as Prefix),
|
|
account,
|
|
chain
|
|
];
|
|
}
|
|
|
|
function Address ({ address, children, className, genesisHash, name, theme = 'polkadot' }: Props): React.ReactElement<Props> {
|
|
const accounts = useContext(AccountContext);
|
|
const [account, setAccount] = useState<AccountJson | null>(null);
|
|
const [chain, setChain] = useState<Chain | null>(null);
|
|
const [formatted, setFormatted] = useState<string | null>(null);
|
|
|
|
useEffect((): void => {
|
|
if (!address) {
|
|
return;
|
|
}
|
|
|
|
const [formatted, account, chain] = recodeAddress(address, accounts, genesisHash);
|
|
|
|
setFormatted(formatted);
|
|
setChain(chain);
|
|
setAccount(account);
|
|
}, [address]);
|
|
|
|
return (
|
|
<IconBox
|
|
banner={chain && chain.genesisHash && chain.name}
|
|
className={className}
|
|
icon={
|
|
<Identicon
|
|
className='icon'
|
|
size={64}
|
|
theme={theme}
|
|
value={address}
|
|
/>
|
|
}
|
|
intro={
|
|
<>
|
|
<div className='name'>{name || (account && account.name) || '<unknown>'}</div>
|
|
<div className='address'>{formatted || '<unknown>'}</div>
|
|
</>
|
|
}
|
|
>
|
|
{children}
|
|
</IconBox>
|
|
);
|
|
}
|
|
|
|
export default styled(Address)`
|
|
.address {
|
|
opacity: 0.5;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.name {
|
|
padding-bottom: 0.5rem;
|
|
}
|
|
`;
|