ghost-keychain/packages/extension-ui/src/components/Address.tsx
Jaco Greeff 4945417982
Mobile signer support (via Qr) (#134)
* 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)
2019-09-06 13:03:55 +02:00

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;
}
`;