mirror of
https://github.com/status-im/MyCrypto.git
synced 2025-02-04 23:33:24 +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 { IWallet, Balance, TrezorWallet, LedgerWallet } from 'libs/wallet';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import translate from 'translations';
|
import translate from 'translations';
|
||||||
@ -103,7 +103,9 @@ class AccountInfo extends React.Component<Props, State> {
|
|||||||
<Identicon address={address} size="100%" />
|
<Identicon address={address} size="100%" />
|
||||||
</div>
|
</div>
|
||||||
<div className="AccountInfo-address-wrapper">
|
<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}>
|
<CopyToClipboard onCopy={this.onCopy} text={address}>
|
||||||
<div
|
<div
|
||||||
className={`AccountInfo-copy-icon${this.state.copied ? '-copied' : ''}`}
|
className={`AccountInfo-copy-icon${this.state.copied ? '-copied' : ''}`}
|
||||||
@ -183,24 +185,16 @@ class AccountInfo extends React.Component<Props, State> {
|
|||||||
<ul className="AccountInfo-list">
|
<ul className="AccountInfo-list">
|
||||||
{!!blockExplorer && (
|
{!!blockExplorer && (
|
||||||
<li className="AccountInfo-list-item">
|
<li className="AccountInfo-list-item">
|
||||||
<a
|
<NewTabLink href={blockExplorer.addressUrl(address)}>
|
||||||
href={blockExplorer.addressUrl(address)}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{`${network.name} (${blockExplorer.origin})`}
|
{`${network.name} (${blockExplorer.origin})`}
|
||||||
</a>
|
</NewTabLink>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
{!!tokenExplorer && (
|
{!!tokenExplorer && (
|
||||||
<li className="AccountInfo-list-item">
|
<li className="AccountInfo-list-item">
|
||||||
<a
|
<NewTabLink href={tokenExplorer.address(address)}>
|
||||||
href={tokenExplorer.address(address)}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{`Tokens (${tokenExplorer.name})`}
|
{`Tokens (${tokenExplorer.name})`}
|
||||||
</a>
|
</NewTabLink>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -5,6 +5,7 @@ import { getCurrentTo, ICurrentTo } from 'selectors/transaction';
|
|||||||
import { getAllTokens } from 'selectors/config';
|
import { getAllTokens } from 'selectors/config';
|
||||||
import { getWalletInst } from 'selectors/wallet';
|
import { getWalletInst } from 'selectors/wallet';
|
||||||
import { getAddressMessage } from 'config';
|
import { getAddressMessage } from 'config';
|
||||||
|
import { Address } from 'components/ui';
|
||||||
import { Token } from 'types/network';
|
import { Token } from 'types/network';
|
||||||
|
|
||||||
interface ReduxProps {
|
interface ReduxProps {
|
||||||
@ -72,7 +73,10 @@ class CurrentCustomMessageClass extends PureComponent<Props, State> {
|
|||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<p>
|
<p>
|
||||||
<small>
|
<small>
|
||||||
A message regarding <strong>{address}</strong>:
|
A message regarding{' '}
|
||||||
|
<strong>
|
||||||
|
<Address address={address} />
|
||||||
|
</strong>:
|
||||||
</small>
|
</small>
|
||||||
</p>
|
</p>
|
||||||
<p>{msg.msg}</p>
|
<p>{msg.msg}</p>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import translate from 'translations';
|
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 { TransactionData, TransactionReceipt } from 'libs/nodes';
|
||||||
import { NetworkConfig } from 'types/network';
|
import { NetworkConfig } from 'types/network';
|
||||||
import './TransactionDataTable.scss';
|
import './TransactionDataTable.scss';
|
||||||
@ -98,7 +98,7 @@ const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
|
|||||||
data: (
|
data: (
|
||||||
<MaybeLink href={explorer.from}>
|
<MaybeLink href={explorer.from}>
|
||||||
<Identicon address={data.from} size="26px" />
|
<Identicon address={data.from} size="26px" />
|
||||||
{data.from}
|
<Address address={data.from} />
|
||||||
</MaybeLink>
|
</MaybeLink>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -107,7 +107,7 @@ const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
|
|||||||
data: (
|
data: (
|
||||||
<MaybeLink href={explorer.to}>
|
<MaybeLink href={explorer.to}>
|
||||||
<Identicon address={data.to} size="26px" />
|
<Identicon address={data.to} size="26px" />
|
||||||
{data.to}
|
<Address address={data.to} />
|
||||||
</MaybeLink>
|
</MaybeLink>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -141,7 +141,9 @@ const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
|
|||||||
label: translate('New contract address'),
|
label: translate('New contract address'),
|
||||||
data: receipt &&
|
data: receipt &&
|
||||||
receipt.contractAddress && (
|
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 Tooltip } from './Tooltip';
|
||||||
export { default as TitleBar } from './TitleBar';
|
export { default as TitleBar } from './TitleBar';
|
||||||
export { default as HelpLink } from './HelpLink';
|
export { default as HelpLink } from './HelpLink';
|
||||||
|
export { default as Address } from './Address';
|
||||||
export * from './ConditionalInput';
|
export * from './ConditionalInput';
|
||||||
export * from './Expandable';
|
export * from './Expandable';
|
||||||
export * from './InlineSpinner';
|
export * from './InlineSpinner';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { IOwnedDomainRequest } from 'libs/ens';
|
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}`;
|
const lookupLink = name => `https://etherscan.io/enslookup?q=${name}`;
|
||||||
|
|
||||||
type ChildrenProps = any;
|
type ChildrenProps = any;
|
||||||
@ -40,7 +40,9 @@ export const NameOwned: React.SFC<IOwnedDomainRequest> = ({
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Owner:</td>
|
<td>Owner:</td>
|
||||||
<MonoTd>{ownerAddress}</MonoTd>
|
<MonoTd>
|
||||||
|
<Address address={ownerAddress} />
|
||||||
|
</MonoTd>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Highest Bidder (Deed Owner): </td>
|
<td>Highest Bidder (Deed Owner): </td>
|
||||||
@ -50,7 +52,9 @@ export const NameOwned: React.SFC<IOwnedDomainRequest> = ({
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Resolved Address: </td>
|
<td>Resolved Address: </td>
|
||||||
<MonoTd>{resolvedAddress}</MonoTd>
|
<MonoTd>
|
||||||
|
<Address address={resolvedAddress} />
|
||||||
|
</MonoTd>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -8,6 +8,7 @@ $pw-max-width: 40rem;
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-password {
|
&-password {
|
||||||
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: $pw-max-width;
|
max-width: $pw-max-width;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { toChecksumAddress } from 'ethereumjs-util';
|
||||||
import translate, { translateRaw } from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import { IWallet } from 'libs/wallet';
|
import { IWallet } from 'libs/wallet';
|
||||||
import { print } from 'components/PrintableWallet';
|
import { print } from 'components/PrintableWallet';
|
||||||
@ -26,12 +27,12 @@ export default class WalletInfo extends React.PureComponent<Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
this.setWalletAsyncState(this.props.wallet);
|
this.setStateFromWallet(this.props.wallet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillReceiveProps(nextProps: Props) {
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
if (this.props.wallet !== nextProps.wallet) {
|
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) {
|
private setStateFromWallet(wallet: IWallet) {
|
||||||
const address = wallet.getAddressString();
|
const address = toChecksumAddress(wallet.getAddressString());
|
||||||
const privateKey = wallet.getPrivateKeyString ? await wallet.getPrivateKeyString() : '';
|
const privateKey = wallet.getPrivateKeyString ? wallet.getPrivateKeyString() : '';
|
||||||
this.setState({ address, privateKey });
|
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';
|
type StaticNetworkIds = 'ETH' | 'Ropsten' | 'Kovan' | 'Rinkeby' | 'ETC' | 'UBQ' | 'EXP';
|
||||||
|
|
||||||
interface BlockExplorerConfig {
|
export interface BlockExplorerConfig {
|
||||||
name: string;
|
name: string;
|
||||||
origin: string;
|
origin: string;
|
||||||
txUrl(txHash: string): string;
|
txUrl(txHash: string): string;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user