mirror of
https://github.com/status-im/MyCrypto.git
synced 2025-01-26 19:09:11 +00:00
Address component for checksumming + linking to explorer (#1168)
* Add address component that checksums and optionally links to block explorer. * tscheck * Add exclusive props, type guard.
This commit is contained in:
parent
5fcec1ecd7
commit
1eb57a38bc
@ -1,4 +1,4 @@
|
||||
import { Identicon, UnitDisplay } from 'components/ui';
|
||||
import { Identicon, UnitDisplay, Address, NewTabLink } from 'components/ui';
|
||||
import { IWallet, Balance, TrezorWallet, LedgerWallet } from 'libs/wallet';
|
||||
import React from 'react';
|
||||
import translate from 'translations';
|
||||
@ -103,7 +103,9 @@ class AccountInfo extends React.Component<Props, State> {
|
||||
<Identicon address={address} size="100%" />
|
||||
</div>
|
||||
<div className="AccountInfo-address-wrapper">
|
||||
<div className="AccountInfo-address-addr">{address}</div>
|
||||
<div className="AccountInfo-address-addr">
|
||||
<Address address={address} />
|
||||
</div>
|
||||
<CopyToClipboard onCopy={this.onCopy} text={address}>
|
||||
<div
|
||||
className={`AccountInfo-copy-icon${this.state.copied ? '-copied' : ''}`}
|
||||
@ -183,24 +185,16 @@ class AccountInfo extends React.Component<Props, State> {
|
||||
<ul className="AccountInfo-list">
|
||||
{!!blockExplorer && (
|
||||
<li className="AccountInfo-list-item">
|
||||
<a
|
||||
href={blockExplorer.addressUrl(address)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<NewTabLink href={blockExplorer.addressUrl(address)}>
|
||||
{`${network.name} (${blockExplorer.origin})`}
|
||||
</a>
|
||||
</NewTabLink>
|
||||
</li>
|
||||
)}
|
||||
{!!tokenExplorer && (
|
||||
<li className="AccountInfo-list-item">
|
||||
<a
|
||||
href={tokenExplorer.address(address)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<NewTabLink href={tokenExplorer.address(address)}>
|
||||
{`Tokens (${tokenExplorer.name})`}
|
||||
</a>
|
||||
</NewTabLink>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
|
@ -5,6 +5,7 @@ import { getCurrentTo, ICurrentTo } from 'selectors/transaction';
|
||||
import { getAllTokens } from 'selectors/config';
|
||||
import { getWalletInst } from 'selectors/wallet';
|
||||
import { getAddressMessage } from 'config';
|
||||
import { Address } from 'components/ui';
|
||||
import { Token } from 'types/network';
|
||||
|
||||
interface ReduxProps {
|
||||
@ -72,7 +73,10 @@ class CurrentCustomMessageClass extends PureComponent<Props, State> {
|
||||
<React.Fragment>
|
||||
<p>
|
||||
<small>
|
||||
A message regarding <strong>{address}</strong>:
|
||||
A message regarding{' '}
|
||||
<strong>
|
||||
<Address address={address} />
|
||||
</strong>:
|
||||
</small>
|
||||
</p>
|
||||
<p>{msg.msg}</p>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import translate from 'translations';
|
||||
import { Identicon, UnitDisplay, NewTabLink } from 'components/ui';
|
||||
import { Identicon, UnitDisplay, NewTabLink, Address } from 'components/ui';
|
||||
import { TransactionData, TransactionReceipt } from 'libs/nodes';
|
||||
import { NetworkConfig } from 'types/network';
|
||||
import './TransactionDataTable.scss';
|
||||
@ -98,7 +98,7 @@ const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
|
||||
data: (
|
||||
<MaybeLink href={explorer.from}>
|
||||
<Identicon address={data.from} size="26px" />
|
||||
{data.from}
|
||||
<Address address={data.from} />
|
||||
</MaybeLink>
|
||||
)
|
||||
},
|
||||
@ -107,7 +107,7 @@ const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
|
||||
data: (
|
||||
<MaybeLink href={explorer.to}>
|
||||
<Identicon address={data.to} size="26px" />
|
||||
{data.to}
|
||||
<Address address={data.to} />
|
||||
</MaybeLink>
|
||||
)
|
||||
},
|
||||
@ -141,7 +141,9 @@ const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
|
||||
label: translate('New contract address'),
|
||||
data: receipt &&
|
||||
receipt.contractAddress && (
|
||||
<MaybeLink href={explorer.contract}>{receipt.contractAddress}</MaybeLink>
|
||||
<MaybeLink href={explorer.contract}>
|
||||
<Address address={receipt.contractAddress} />
|
||||
</MaybeLink>
|
||||
)
|
||||
},
|
||||
{
|
||||
|
40
common/components/ui/Address.tsx
Normal file
40
common/components/ui/Address.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import { toChecksumAddress } from 'ethereumjs-util';
|
||||
import NewTabLink from './NewTabLink';
|
||||
import { IWallet } from 'libs/wallet';
|
||||
import { BlockExplorerConfig } from 'types/network';
|
||||
|
||||
interface BaseProps {
|
||||
explorer?: BlockExplorerConfig | null;
|
||||
}
|
||||
|
||||
interface AddressProps extends BaseProps {
|
||||
address: string;
|
||||
}
|
||||
|
||||
interface WalletProps extends BaseProps {
|
||||
wallet: IWallet;
|
||||
}
|
||||
|
||||
type Props = AddressProps | WalletProps;
|
||||
|
||||
const isAddressProps = (props: Props): props is AddressProps =>
|
||||
typeof (props as AddressProps).address === 'string';
|
||||
|
||||
const Address: React.SFC<Props> = props => {
|
||||
let addr = '';
|
||||
if (isAddressProps(props)) {
|
||||
addr = props.address;
|
||||
} else {
|
||||
addr = props.wallet.getAddressString();
|
||||
}
|
||||
addr = toChecksumAddress(addr);
|
||||
|
||||
if (props.explorer) {
|
||||
return <NewTabLink href={props.explorer.addressUrl(addr)}>{addr}</NewTabLink>;
|
||||
} else {
|
||||
return <React.Fragment>{addr}</React.Fragment>;
|
||||
}
|
||||
};
|
||||
|
||||
export default Address;
|
@ -12,6 +12,7 @@ export { default as SwapDropdown } from './SwapDropdown';
|
||||
export { default as Tooltip } from './Tooltip';
|
||||
export { default as TitleBar } from './TitleBar';
|
||||
export { default as HelpLink } from './HelpLink';
|
||||
export { default as Address } from './Address';
|
||||
export * from './ConditionalInput';
|
||||
export * from './Expandable';
|
||||
export * from './InlineSpinner';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { IOwnedDomainRequest } from 'libs/ens';
|
||||
import { NewTabLink } from 'components/ui';
|
||||
import { NewTabLink, Address } from 'components/ui';
|
||||
const lookupLink = name => `https://etherscan.io/enslookup?q=${name}`;
|
||||
|
||||
type ChildrenProps = any;
|
||||
@ -40,7 +40,9 @@ export const NameOwned: React.SFC<IOwnedDomainRequest> = ({
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Owner:</td>
|
||||
<MonoTd>{ownerAddress}</MonoTd>
|
||||
<MonoTd>
|
||||
<Address address={ownerAddress} />
|
||||
</MonoTd>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Highest Bidder (Deed Owner): </td>
|
||||
@ -50,7 +52,9 @@ export const NameOwned: React.SFC<IOwnedDomainRequest> = ({
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Resolved Address: </td>
|
||||
<MonoTd>{resolvedAddress}</MonoTd>
|
||||
<MonoTd>
|
||||
<Address address={resolvedAddress} />
|
||||
</MonoTd>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -8,6 +8,7 @@ $pw-max-width: 40rem;
|
||||
}
|
||||
|
||||
&-password {
|
||||
display: block;
|
||||
position: relative;
|
||||
max-width: $pw-max-width;
|
||||
width: 100%;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { toChecksumAddress } from 'ethereumjs-util';
|
||||
import translate, { translateRaw } from 'translations';
|
||||
import { IWallet } from 'libs/wallet';
|
||||
import { print } from 'components/PrintableWallet';
|
||||
@ -26,12 +27,12 @@ export default class WalletInfo extends React.PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
public componentDidMount() {
|
||||
this.setWalletAsyncState(this.props.wallet);
|
||||
this.setStateFromWallet(this.props.wallet);
|
||||
}
|
||||
|
||||
public componentWillReceiveProps(nextProps: Props) {
|
||||
if (this.props.wallet !== nextProps.wallet) {
|
||||
this.setWalletAsyncState(nextProps.wallet);
|
||||
this.setStateFromWallet(nextProps.wallet);
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,9 +115,9 @@ export default class WalletInfo extends React.PureComponent<Props, State> {
|
||||
);
|
||||
}
|
||||
|
||||
private async setWalletAsyncState(wallet: IWallet) {
|
||||
const address = wallet.getAddressString();
|
||||
const privateKey = wallet.getPrivateKeyString ? await wallet.getPrivateKeyString() : '';
|
||||
private setStateFromWallet(wallet: IWallet) {
|
||||
const address = toChecksumAddress(wallet.getAddressString());
|
||||
const privateKey = wallet.getPrivateKeyString ? wallet.getPrivateKeyString() : '';
|
||||
this.setState({ address, privateKey });
|
||||
}
|
||||
|
||||
|
2
shared/types/network.d.ts
vendored
2
shared/types/network.d.ts
vendored
@ -2,7 +2,7 @@ import { StaticNetworksState, CustomNetworksState } from 'reducers/config/networ
|
||||
|
||||
type StaticNetworkIds = 'ETH' | 'Ropsten' | 'Kovan' | 'Rinkeby' | 'ETC' | 'UBQ' | 'EXP';
|
||||
|
||||
interface BlockExplorerConfig {
|
||||
export interface BlockExplorerConfig {
|
||||
name: string;
|
||||
origin: string;
|
||||
txUrl(txHash: string): string;
|
||||
|
Loading…
x
Reference in New Issue
Block a user