Translation Updates (#1323)
* Update account view routing * Temporarily add unicode character to translated strings for testing * Temporarily select add unicode to all untranslated strings * Format changes * Add all english translations for /account & /generate * Add the rest of the english translations * Add a few more missing translations * Update en translations * Get selectedLanguage from localstorage instead of redux sttate * Update snapshots * Add missing translation keys & Update translate functs & change variable prefix * translate all markdown strings & remove old translation strings * Update snapshot * Add a few more translation strs * Move raw strings being translated into json * All translation keys are now Uppercase * Fix up the last few translations * Update snapshot * Uppercase de translation strings * Bring back shapeshift logo on swap * Fix contracts tab translations * Fix a few more translations * Fix translations * remove debugging stuff * Update snapshots * Use react.fragment as markdown root renderer * Seperate markdown translations into their own function * Clean up translation functions * Clean up translation functions * Update snapshot * Fix some broken translation strings * Add prettier ignore file
This commit is contained in:
parent
7521337bda
commit
816ce3180f
|
@ -0,0 +1 @@
|
||||||
|
common/translations
|
|
@ -13,7 +13,7 @@ export const AddressField: React.SFC<Props> = ({ isReadOnly }) => (
|
||||||
withProps={({ currentTo, isValid, onChange, readOnly }) => (
|
withProps={({ currentTo, isValid, onChange, readOnly }) => (
|
||||||
<div className="input-group-wrapper">
|
<div className="input-group-wrapper">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translate('SEND_addr')}</div>
|
<div className="input-group-header">{translate('SEND_ADDR_SHORT')}</div>
|
||||||
<Input
|
<Input
|
||||||
className={`input-group-input ${isValid ? '' : 'invalid'}`}
|
className={`input-group-input ${isValid ? '' : 'invalid'}`}
|
||||||
type="text"
|
type="text"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { AmountFieldFactory } from './AmountFieldFactory';
|
import { AmountFieldFactory } from './AmountFieldFactory';
|
||||||
import { UnitDropDown } from 'components';
|
import { UnitDropDown } from 'components';
|
||||||
import translate, { translateRaw } from 'translations';
|
import translate from 'translations';
|
||||||
import { Input } from 'components/ui';
|
import { Input } from 'components/ui';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -19,13 +19,13 @@ export const AmountField: React.SFC<Props> = ({
|
||||||
withProps={({ currentValue: { raw }, isValid, onChange, readOnly }) => (
|
withProps={({ currentValue: { raw }, isValid, onChange, readOnly }) => (
|
||||||
<div className="input-group-wrapper">
|
<div className="input-group-wrapper">
|
||||||
<label className="input-group input-group-inline">
|
<label className="input-group input-group-inline">
|
||||||
<div className="input-group-header">{translate('SEND_amount')}</div>
|
<div className="input-group-header">{translate('SEND_AMOUNT_SHORT')}</div>
|
||||||
<Input
|
<Input
|
||||||
className={`input-group-input ${
|
className={`input-group-input ${
|
||||||
isAmountValid(raw, customValidator, isValid) ? '' : 'invalid'
|
isAmountValid(raw, customValidator, isValid) ? '' : 'invalid'
|
||||||
}`}
|
}`}
|
||||||
type="number"
|
type="number"
|
||||||
placeholder={translateRaw('SEND_amount_short')}
|
placeholder={'1'}
|
||||||
value={raw}
|
value={raw}
|
||||||
readOnly={!!readOnly}
|
readOnly={!!readOnly}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
|
|
@ -98,7 +98,7 @@ class AccountInfo extends React.Component<Props, State> {
|
||||||
const wallet = this.props.wallet as LedgerWallet | TrezorWallet;
|
const wallet = this.props.wallet as LedgerWallet | TrezorWallet;
|
||||||
return (
|
return (
|
||||||
<div className="AccountInfo">
|
<div className="AccountInfo">
|
||||||
<h5 className="AccountInfo-section-header">{translate('sidebar_AccountAddr')}</h5>
|
<h5 className="AccountInfo-section-header">{translate('SIDEBAR_ACCOUNTADDR')}</h5>
|
||||||
<div className="AccountInfo-section AccountInfo-address-section">
|
<div className="AccountInfo-section AccountInfo-address-section">
|
||||||
<div className="AccountInfo-address-icon">
|
<div className="AccountInfo-address-icon">
|
||||||
<Identicon address={address} size="100%" />
|
<Identicon address={address} size="100%" />
|
||||||
|
@ -134,7 +134,9 @@ class AccountInfo extends React.Component<Props, State> {
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{confirmAddr ? null : 'Display address on ' + wallet.getWalletType()}
|
{confirmAddr
|
||||||
|
? null
|
||||||
|
: translate('SIDEBAR_DISPLAY_ADDR', { $wallet: wallet.getWalletType() })}
|
||||||
</a>
|
</a>
|
||||||
{confirmAddr ? (
|
{confirmAddr ? (
|
||||||
<span className="AccountInfo-address-confirm">
|
<span className="AccountInfo-address-confirm">
|
||||||
|
@ -145,7 +147,7 @@ class AccountInfo extends React.Component<Props, State> {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="AccountInfo-section">
|
<div className="AccountInfo-section">
|
||||||
<h5 className="AccountInfo-section-header">{translate('sidebar_AccountBal')}</h5>
|
<h5 className="AccountInfo-section-header">{translate('SIDEBAR_ACCOUNTBAL')}</h5>
|
||||||
<ul className="AccountInfo-list">
|
<ul className="AccountInfo-list">
|
||||||
<li className="AccountInfo-list-item AccountInfo-balance">
|
<li className="AccountInfo-list-item AccountInfo-balance">
|
||||||
<span
|
<span
|
||||||
|
@ -182,7 +184,7 @@ class AccountInfo extends React.Component<Props, State> {
|
||||||
|
|
||||||
{(!!blockExplorer || !!tokenExplorer) && (
|
{(!!blockExplorer || !!tokenExplorer) && (
|
||||||
<div className="AccountInfo-section">
|
<div className="AccountInfo-section">
|
||||||
<h5 className="AccountInfo-section-header">{translate('sidebar_TransHistory')}</h5>
|
<h5 className="AccountInfo-section-header">{translate('SIDEBAR_TRANSHISTORY')}</h5>
|
||||||
<ul className="AccountInfo-list">
|
<ul className="AccountInfo-list">
|
||||||
{!!blockExplorer && (
|
{!!blockExplorer && (
|
||||||
<li className="AccountInfo-list-item">
|
<li className="AccountInfo-list-item">
|
||||||
|
|
|
@ -169,7 +169,7 @@ class EquivalentValues extends React.Component<Props, State> {
|
||||||
return (
|
return (
|
||||||
<div className="EquivalentValues">
|
<div className="EquivalentValues">
|
||||||
<div className="EquivalentValues-header">
|
<div className="EquivalentValues-header">
|
||||||
<h5 className="EquivalentValues-title">{translate('sidebar_Equiv')}</h5>
|
<h5 className="EquivalentValues-title">{translate('SIDEBAR_EQUIV')}</h5>
|
||||||
<Select
|
<Select
|
||||||
name="equivalentValues"
|
name="equivalentValues"
|
||||||
// TODO: Update type
|
// TODO: Update type
|
||||||
|
@ -183,13 +183,11 @@ class EquivalentValues extends React.Component<Props, State> {
|
||||||
|
|
||||||
{isOffline ? (
|
{isOffline ? (
|
||||||
<div className="EquivalentValues-offline well well-sm">
|
<div className="EquivalentValues-offline well well-sm">
|
||||||
Equivalent values are unavailable offline
|
{translate('EQUIV_VALS_OFFLINE')}
|
||||||
</div>
|
</div>
|
||||||
) : network.isTestnet ? (
|
) : network.isTestnet ? (
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<h5 style={{ color: 'red' }}>
|
<h5 style={{ color: 'red' }}>{translate('EQUIV_VALS_TESTNET')}</h5>
|
||||||
On test network, equivalent values will not be displayed.
|
|
||||||
</h5>
|
|
||||||
</div>
|
</div>
|
||||||
) : ratesError ? (
|
) : ratesError ? (
|
||||||
<h5>{ratesError}</h5>
|
<h5>{ratesError}</h5>
|
||||||
|
@ -228,7 +226,7 @@ class EquivalentValues extends React.Component<Props, State> {
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
) : (
|
) : (
|
||||||
<p>Sorry, equivalent values are not supported for this unit.</p>
|
<p>{translate('EQUIV_VALS_UNSUPPORTED_UNIT')}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { HELP_ARTICLE } from 'config';
|
import { HELP_ARTICLE } from 'config';
|
||||||
import { isPositiveIntegerOrZero, isValidETHAddress } from 'libs/validators';
|
import { isPositiveIntegerOrZero, isValidETHAddress } from 'libs/validators';
|
||||||
import translate from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import { HelpLink, Input } from 'components/ui';
|
import { HelpLink, Input } from 'components/ui';
|
||||||
import './AddCustomTokenForm.scss';
|
import './AddCustomTokenForm.scss';
|
||||||
import { Token } from 'types/network';
|
import { Token } from 'types/network';
|
||||||
|
@ -47,17 +47,17 @@ export default class AddCustomTokenForm extends React.PureComponent<Props, State
|
||||||
{
|
{
|
||||||
name: 'symbol',
|
name: 'symbol',
|
||||||
value: symbol,
|
value: symbol,
|
||||||
label: translate('TOKEN_Symbol')
|
label: translateRaw('TOKEN_SYMBOL')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'address',
|
name: 'address',
|
||||||
value: address,
|
value: address,
|
||||||
label: translate('TOKEN_Addr')
|
label: translateRaw('TOKEN_ADDR')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'decimal',
|
name: 'decimal',
|
||||||
value: decimal,
|
value: decimal,
|
||||||
label: translate('TOKEN_Dec')
|
label: translateRaw('TOKEN_DEC')
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -84,20 +84,20 @@ export default class AddCustomTokenForm extends React.PureComponent<Props, State
|
||||||
})}
|
})}
|
||||||
|
|
||||||
<HelpLink article={HELP_ARTICLE.ADDING_NEW_TOKENS} className="AddCustom-buttons-help">
|
<HelpLink article={HELP_ARTICLE.ADDING_NEW_TOKENS} className="AddCustom-buttons-help">
|
||||||
{translate('Need help? Learn how to add custom tokens.')}
|
{translate('ADD_CUSTOM_TKN_HELP')}
|
||||||
</HelpLink>
|
</HelpLink>
|
||||||
<div className="AddCustom-buttons">
|
<div className="AddCustom-buttons">
|
||||||
<button
|
<button
|
||||||
className="AddCustom-buttons-btn btn btn-sm btn-default"
|
className="AddCustom-buttons-btn btn btn-sm btn-default"
|
||||||
onClick={this.props.toggleForm}
|
onClick={this.props.toggleForm}
|
||||||
>
|
>
|
||||||
{translate('x_Cancel')}
|
{translate('ACTION_2')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="AddCustom-buttons-btn btn btn-primary btn-sm"
|
className="AddCustom-buttons-btn btn btn-primary btn-sm"
|
||||||
disabled={!this.isValid()}
|
disabled={!this.isValid()}
|
||||||
>
|
>
|
||||||
{translate('x_Save')}
|
{translate('X_SAVE')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -50,11 +50,9 @@ export default class TokenBalances extends React.PureComponent<Props, State> {
|
||||||
bottom = (
|
bottom = (
|
||||||
<div className="TokenBalances-buttons">
|
<div className="TokenBalances-buttons">
|
||||||
<button className="btn btn-primary btn-block" onClick={this.handleSetWalletTokens}>
|
<button className="btn btn-primary btn-block" onClick={this.handleSetWalletTokens}>
|
||||||
<span>{translate('x_Save')}</span>
|
<span>{translate('X_SAVE')}</span>
|
||||||
</button>
|
</button>
|
||||||
<p className="TokenBalances-buttons-help">
|
<p className="TokenBalances-buttons-help">{translate('PROMPT_ADD_CUSTOM_TKN')}</p>
|
||||||
{translate('Missing tokens? You can add custom tokens next.')}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (showCustomTokenForm) {
|
} else if (showCustomTokenForm) {
|
||||||
|
@ -71,10 +69,10 @@ export default class TokenBalances extends React.PureComponent<Props, State> {
|
||||||
bottom = (
|
bottom = (
|
||||||
<div className="TokenBalances-buttons">
|
<div className="TokenBalances-buttons">
|
||||||
<button className="btn btn-default btn-xs" onClick={this.toggleShowCustomTokenForm}>
|
<button className="btn btn-default btn-xs" onClick={this.toggleShowCustomTokenForm}>
|
||||||
<span>{translate('SEND_custom')}</span>
|
<span>{translate('SEND_CUSTOM')}</span>
|
||||||
</button>{' '}
|
</button>
|
||||||
<button className="btn btn-default btn-xs" onClick={this.props.scanWalletForTokens}>
|
<button className="btn btn-default btn-xs" onClick={this.props.scanWalletForTokens}>
|
||||||
<span>Scan for New Tokens</span>
|
<span>{translate('SCAN_TOKENS')}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -105,7 +103,7 @@ export default class TokenBalances extends React.PureComponent<Props, State> {
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
) : (
|
) : (
|
||||||
<div className="well well-sm text-center">No tokens found</div>
|
<div className="well well-sm text-center">{translate('SCAN_TOKENS_FAIL_NO_TOKENS')}</div>
|
||||||
)}
|
)}
|
||||||
{bottom}
|
{bottom}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -74,7 +74,7 @@ class TokenBalances extends React.Component<Props> {
|
||||||
className="TokenBalances-scan btn btn-primary btn-block"
|
className="TokenBalances-scan btn btn-primary btn-block"
|
||||||
onClick={this.scanWalletForTokens}
|
onClick={this.scanWalletForTokens}
|
||||||
>
|
>
|
||||||
{translate('Scan for my Tokens')}
|
{translate('SCAN_TOKENS')}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -95,7 +95,7 @@ class TokenBalances extends React.Component<Props> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="TokenBalances">
|
<section className="TokenBalances">
|
||||||
<h5 className="TokenBalances-title">{translate('sidebar_TokenBal')}</h5>
|
<h5 className="TokenBalances-title">{translate('SIDEBAR_TOKENBAL')}</h5>
|
||||||
{content}
|
{content}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { AppState } from 'reducers';
|
||||||
import './Body.scss';
|
import './Body.scss';
|
||||||
import { getNetworkConfig } from 'selectors/config';
|
import { getNetworkConfig } from 'selectors/config';
|
||||||
import { NetworkConfig } from 'types/network';
|
import { NetworkConfig } from 'types/network';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
showDetails: boolean;
|
showDetails: boolean;
|
||||||
|
@ -43,7 +44,7 @@ class BodyClass extends React.Component<StateProps, State> {
|
||||||
}`}
|
}`}
|
||||||
onClick={this.toggleDetails}
|
onClick={this.toggleDetails}
|
||||||
>
|
>
|
||||||
Details
|
{translate('ACTION_8')}
|
||||||
</button>
|
</button>
|
||||||
{showDetails && <Details />}
|
{showDetails && <Details />}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { SerializedTransaction } from 'components/renderCbs';
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
import { getFrom, getUnit, isEtherTransaction } from 'selectors/transaction';
|
import { getFrom, getUnit, isEtherTransaction } from 'selectors/transaction';
|
||||||
import { toChecksumAddress } from 'ethereumjs-util';
|
import { toChecksumAddress } from 'ethereumjs-util';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
interface StateProps {
|
interface StateProps {
|
||||||
from: AppState['transaction']['meta']['from'];
|
from: AppState['transaction']['meta']['from'];
|
||||||
|
@ -35,7 +36,7 @@ class AddressesClass extends Component<StateProps> {
|
||||||
<Identicon className="tx-modal-address-from-icon" size={size} address={from} />
|
<Identicon className="tx-modal-address-from-icon" size={size} address={from} />
|
||||||
)}
|
)}
|
||||||
<div className="tx-modal-address-from-content">
|
<div className="tx-modal-address-from-content">
|
||||||
<h5 className="tx-modal-address-from-title">From </h5>
|
<h5 className="tx-modal-address-from-title">{translate('CONFIRM_TX_FROM')} </h5>
|
||||||
<h5 className="tx-modal-address-from-address small">{from}</h5>
|
<h5 className="tx-modal-address-from-address small">{from}</h5>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,7 +46,9 @@ class AddressesClass extends Component<StateProps> {
|
||||||
<img src={arrow} alt="arrow" />
|
<img src={arrow} alt="arrow" />
|
||||||
</div>
|
</div>
|
||||||
<div className="tx-modal-address-tkn-contract-content">
|
<div className="tx-modal-address-tkn-contract-content">
|
||||||
<p className="tx-modal-address-tkn-contract-title">via the {unit} contract</p>
|
<p className="tx-modal-address-tkn-contract-title">
|
||||||
|
{translate('CONFIRM_TX_VIA_CONTRACT', { unit })}
|
||||||
|
</p>
|
||||||
<a
|
<a
|
||||||
className="small tx-modal-address-tkn-contract-link"
|
className="small tx-modal-address-tkn-contract-link"
|
||||||
href={ETHAddressExplorer(to)}
|
href={ETHAddressExplorer(to)}
|
||||||
|
@ -62,7 +65,7 @@ class AddressesClass extends Component<StateProps> {
|
||||||
address={toFormatted}
|
address={toFormatted}
|
||||||
/>
|
/>
|
||||||
<div className="tx-modal-address-to-content">
|
<div className="tx-modal-address-to-content">
|
||||||
<h5 className="tx-modal-address-to-title">To </h5>
|
<h5 className="tx-modal-address-to-title">{translate('CONFIRM_TX_TO')} </h5>
|
||||||
<h5 className="small tx-modal-address-to-address">{toFormatted}</h5>
|
<h5 className="small tx-modal-address-to-address">{toFormatted}</h5>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { SerializedTxParams, getParamsFromSerializedTx } from 'selectors/transac
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { getNetworkConfig } from 'selectors/config';
|
import { getNetworkConfig } from 'selectors/config';
|
||||||
import { NetworkConfig } from 'types/network';
|
import { NetworkConfig } from 'types/network';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
interface StateProps extends SerializedTxParams, AllUSDValues {
|
interface StateProps extends SerializedTxParams, AllUSDValues {
|
||||||
network: NetworkConfig;
|
network: NetworkConfig;
|
||||||
|
@ -32,7 +33,7 @@ class AmountsClass extends Component<StateProps> {
|
||||||
<table className="tx-modal-amount">
|
<table className="tx-modal-amount">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr className="tx-modal-amount-send">
|
<tr className="tx-modal-amount-send">
|
||||||
<td>You'll Send</td>
|
<td>{translate('CONFIRM_TX_SENDING')}</td>
|
||||||
<td>
|
<td>
|
||||||
<UnitDisplay
|
<UnitDisplay
|
||||||
value={currentValue}
|
value={currentValue}
|
||||||
|
@ -54,7 +55,7 @@ class AmountsClass extends Component<StateProps> {
|
||||||
)}
|
)}
|
||||||
</tr>
|
</tr>
|
||||||
<tr className="tx-modal-amount-fee">
|
<tr className="tx-modal-amount-fee">
|
||||||
<td>Transaction Fee</td>
|
<td>{translate('CONFIRM_TX_FEE')}</td>
|
||||||
<td>
|
<td>
|
||||||
<UnitDisplay
|
<UnitDisplay
|
||||||
value={fee}
|
value={fee}
|
||||||
|
@ -77,7 +78,7 @@ class AmountsClass extends Component<StateProps> {
|
||||||
</tr>
|
</tr>
|
||||||
{!isToken && (
|
{!isToken && (
|
||||||
<tr className="tx-modal-amount-total">
|
<tr className="tx-modal-amount-total">
|
||||||
<td>Total</td>
|
<td>{translate('CONFIRM_TX_TOTAL')}</td>
|
||||||
<td>
|
<td>
|
||||||
<UnitDisplay
|
<UnitDisplay
|
||||||
value={total}
|
value={total}
|
||||||
|
|
|
@ -11,9 +11,9 @@ import {
|
||||||
TBroadcastWeb3TransactionRequested
|
TBroadcastWeb3TransactionRequested
|
||||||
} from 'actions/transaction';
|
} from 'actions/transaction';
|
||||||
import { currentTransactionBroadcasting } from 'selectors/transaction';
|
import { currentTransactionBroadcasting } from 'selectors/transaction';
|
||||||
import { translateRaw } from 'translations';
|
|
||||||
import './ConfirmationModalTemplate.scss';
|
import './ConfirmationModalTemplate.scss';
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
|
import { translateRaw, translate } from 'translations';
|
||||||
|
|
||||||
interface DispatchProps {
|
interface DispatchProps {
|
||||||
broadcastLocalTransactionRequested: TBroadcastLocalTransactionRequested;
|
broadcastLocalTransactionRequested: TBroadcastLocalTransactionRequested;
|
||||||
|
@ -73,7 +73,7 @@ class ConfirmationModalTemplateClass extends React.Component<Props, State> {
|
||||||
const { timeToRead } = this.state;
|
const { timeToRead } = this.state;
|
||||||
const buttonPrefix = timeToRead > 0 ? `(${timeToRead}) ` : '';
|
const buttonPrefix = timeToRead > 0 ? `(${timeToRead}) ` : '';
|
||||||
const defaultConfirmButton = {
|
const defaultConfirmButton = {
|
||||||
text: buttonPrefix + translateRaw('SENDModal_Yes'),
|
text: buttonPrefix + translateRaw('ACTION_11'),
|
||||||
type: 'primary' as IButton['type'],
|
type: 'primary' as IButton['type'],
|
||||||
disabled: timeToRead > 0,
|
disabled: timeToRead > 0,
|
||||||
onClick: this.confirm
|
onClick: this.confirm
|
||||||
|
@ -85,7 +85,7 @@ class ConfirmationModalTemplateClass extends React.Component<Props, State> {
|
||||||
timeLeft: timeToRead,
|
timeLeft: timeToRead,
|
||||||
timePrefix: buttonPrefix,
|
timePrefix: buttonPrefix,
|
||||||
timeLocked: defaultConfirmButton.disabled,
|
timeLocked: defaultConfirmButton.disabled,
|
||||||
defaultText: translateRaw('SENDModal_Yes'),
|
defaultText: translateRaw('ACTION_11'),
|
||||||
type: defaultConfirmButton.type
|
type: defaultConfirmButton.type
|
||||||
})
|
})
|
||||||
: defaultConfirmButton;
|
: defaultConfirmButton;
|
||||||
|
@ -93,7 +93,7 @@ class ConfirmationModalTemplateClass extends React.Component<Props, State> {
|
||||||
const buttons: IButton[] = [
|
const buttons: IButton[] = [
|
||||||
confirmButton,
|
confirmButton,
|
||||||
{
|
{
|
||||||
text: translateRaw('SENDModal_No'),
|
text: translate('ACTION_2'),
|
||||||
type: 'default',
|
type: 'default',
|
||||||
onClick: onClose
|
onClick: onClose
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ class ConfirmationModalTemplateClass extends React.Component<Props, State> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title="Confirm Transaction"
|
title={translateRaw('CONFIRM_TX_MODAL_TITLE')}
|
||||||
buttons={buttons}
|
buttons={buttons}
|
||||||
handleClose={onClose}
|
handleClose={onClose}
|
||||||
disableButtons={transactionBroadcasting}
|
disableButtons={transactionBroadcasting}
|
||||||
|
|
|
@ -9,7 +9,7 @@ export const DataField: React.SFC<{}> = () => (
|
||||||
withProps={({ data: { raw }, dataExists, onChange, readOnly }) => (
|
withProps={({ data: { raw }, dataExists, onChange, readOnly }) => (
|
||||||
<div className="input-group-wrapper">
|
<div className="input-group-wrapper">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translate('OFFLINE_Step2_Label_6')}</div>
|
<div className="input-group-header">{translate('OFFLINE_STEP2_LABEL_6')}</div>
|
||||||
<Input
|
<Input
|
||||||
className={dataExists ? 'is-valid' : 'is-invalid'}
|
className={dataExists ? 'is-valid' : 'is-invalid'}
|
||||||
type="text"
|
type="text"
|
||||||
|
|
|
@ -14,7 +14,7 @@ const TransactionSucceeded = ({ txHash, blockExplorer }: TransactionSucceededPro
|
||||||
if (blockExplorer) {
|
if (blockExplorer) {
|
||||||
verifyBtn = (
|
verifyBtn = (
|
||||||
<NewTabLink className="btn btn-xs" href={blockExplorer.txUrl(txHash)}>
|
<NewTabLink className="btn btn-xs" href={blockExplorer.txUrl(txHash)}>
|
||||||
Verify Transaction on {blockExplorer.name}
|
{translate('VERIFY_TX', { $block_explorer: blockExplorer.name })}
|
||||||
</NewTabLink>
|
</NewTabLink>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import Modal, { IButton } from 'components/ui/Modal';
|
||||||
import { HelpLink } from 'components/ui';
|
import { HelpLink } from 'components/ui';
|
||||||
import { HELP_ARTICLE } from 'config';
|
import { HELP_ARTICLE } from 'config';
|
||||||
import './DisclaimerModal.scss';
|
import './DisclaimerModal.scss';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
|
@ -10,7 +11,9 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const DisclaimerModal: React.SFC<Props> = ({ isOpen, handleClose }) => {
|
const DisclaimerModal: React.SFC<Props> = ({ isOpen, handleClose }) => {
|
||||||
const buttons: IButton[] = [{ text: 'Okay', type: 'default', onClick: handleClose }];
|
const buttons: IButton[] = [
|
||||||
|
{ text: translate('ACTION_10'), type: 'default', onClick: handleClose }
|
||||||
|
];
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} title="Disclaimer" buttons={buttons} handleClose={handleClose}>
|
<Modal isOpen={isOpen} title="Disclaimer" buttons={buttons} handleClose={handleClose}>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './PreFooter.scss';
|
import './PreFooter.scss';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
openModal(): void;
|
openModal(): void;
|
||||||
|
@ -10,9 +11,8 @@ const PreFooter: React.SFC<Props> = ({ openModal }) => {
|
||||||
<section className="pre-footer">
|
<section className="pre-footer">
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<p>
|
<p>
|
||||||
MyCrypto.com does not hold your keys for you. We cannot access accounts, recover keys,
|
{translate('PREFOOTER_WARNING')}{' '}
|
||||||
reset passwords, nor reverse transactions. Protect your keys & always check that you are
|
<a onClick={openModal}>{translate('PREFOOTER_SECURITY_WARNING')}</a>
|
||||||
on correct URL. <a onClick={openModal}>You are responsible for your security.</a>
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -14,6 +14,7 @@ import DisclaimerModal from './DisclaimerModal';
|
||||||
import { NewTabLink } from 'components/ui';
|
import { NewTabLink } from 'components/ui';
|
||||||
import OnboardModal from 'containers/OnboardModal';
|
import OnboardModal from 'containers/OnboardModal';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
import { translateRaw } from 'translations';
|
||||||
|
|
||||||
const SocialMediaLink = ({ link, text }: Link) => {
|
const SocialMediaLink = ({ link, text }: Link) => {
|
||||||
return (
|
return (
|
||||||
|
@ -58,39 +59,39 @@ const PRODUCT_INFO: Link[] = [
|
||||||
{
|
{
|
||||||
link:
|
link:
|
||||||
'https://chrome.google.com/webstore/detail/etheraddresslookup/pdknmigbbbhmllnmgdfalmedcmcefdfn',
|
'https://chrome.google.com/webstore/detail/etheraddresslookup/pdknmigbbbhmllnmgdfalmedcmcefdfn',
|
||||||
text: 'Ether Address Lookup'
|
text: translateRaw('ETHER_ADDRESS_LOOKUP')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
link:
|
link:
|
||||||
'https://chrome.google.com/webstore/detail/ethersecuritylookup/bhhfhgpgmifehjdghlbbijjaimhmcgnf',
|
'https://chrome.google.com/webstore/detail/ethersecuritylookup/bhhfhgpgmifehjdghlbbijjaimhmcgnf',
|
||||||
text: 'Ether Security Lookup'
|
text: translateRaw('ETHER_SECURITY_LOOKUP')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
link: 'https://etherscamdb.info/',
|
link: 'https://etherscamdb.info/',
|
||||||
text: 'EtherScamDB'
|
text: translateRaw('ETHERSCAMDB')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
link: 'https://www.mycrypto.com/helpers.html',
|
link: 'https://www.mycrypto.com/helpers.html',
|
||||||
text: 'Helpers & ENS Debugging'
|
text: translateRaw('FOOTER_HELP_AND_DEBUGGING')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
link: 'mailto:press@mycrypto.com',
|
link: 'mailto:press@mycrypto.com',
|
||||||
text: 'Press Inquiries'
|
text: translateRaw('FOOTER_PRESS')
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const AFFILIATES: Link[] = [
|
const AFFILIATES: Link[] = [
|
||||||
{
|
{
|
||||||
link: ledgerReferralURL,
|
link: ledgerReferralURL,
|
||||||
text: 'Buy a Ledger Wallet'
|
text: translateRaw('LEDGER_REFERAL_1')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
link: trezorReferralURL,
|
link: trezorReferralURL,
|
||||||
text: 'Buy a TREZOR'
|
text: translateRaw('TREZOR_REFERAL')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
link: ethercardReferralURL,
|
link: ethercardReferralURL,
|
||||||
text: 'Get an ether.card'
|
text: translateRaw('ETHERCARD_REFERAL')
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -165,51 +166,52 @@ export default class Footer extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
<div className="Footer-about-links">
|
<div className="Footer-about-links">
|
||||||
<a href="https://mycrypto.com">MyCrypto.com</a>
|
<a href="https://mycrypto.com">MyCrypto.com</a>
|
||||||
<NewTabLink href={knowledgeBaseURL}>Help & Support</NewTabLink>
|
<NewTabLink href={knowledgeBaseURL}>{translateRaw('FOOTER_SUPPORT')}</NewTabLink>
|
||||||
<NewTabLink href="https://about.mycrypto.com">Our Team</NewTabLink>
|
<NewTabLink href="https://about.mycrypto.com">
|
||||||
|
{translateRaw('FOOTER_TEAM')}
|
||||||
|
</NewTabLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="Footer-about-text">
|
<p className="Footer-about-text">{translateRaw('FOOTER_ABOUT')}</p>
|
||||||
MyCrypto is an open-source, client-side tool for generating Ether Wallets, handling
|
|
||||||
ERC-20 tokens, and interacting with the blockchain more easily. Developed by and for
|
|
||||||
the community since 2015, we’re focused on building awesome products that put the
|
|
||||||
power in people’s hands.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="Footer-about-legal">
|
<div className="Footer-about-legal">
|
||||||
<div className="Footer-about-legal-text">
|
<div className="Footer-about-legal-text">
|
||||||
© {new Date().getFullYear()} MyCrypto, Inc.
|
© {new Date().getFullYear()} MyCrypto, Inc.
|
||||||
</div>
|
</div>
|
||||||
<div className="Footer-about-legal-text">
|
<div className="Footer-about-legal-text">
|
||||||
<a onClick={this.toggleModal}>Disclaimer</a>
|
<a onClick={this.toggleModal}>{translateRaw('DISCLAIMER')}</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="Footer-about-legal-text">v{VERSION}</div>
|
<div className="Footer-about-legal-text">v{VERSION}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="Footer-support Footer-section">
|
<div className="Footer-support Footer-section">
|
||||||
<h5 className="Footer-support-title">Support Us & Our Friends</h5>
|
<h5 className="Footer-support-title">{translateRaw('FOOTER_AFFILIATE_TITLE')}</h5>
|
||||||
<div className="Footer-support-affiliates">
|
<div className="Footer-support-affiliates">
|
||||||
{AFFILIATES.map(link => (
|
{AFFILIATES.map((link, i) => (
|
||||||
<NewTabLink key={link.text} href={link.link}>
|
<NewTabLink key={i} href={link.link}>
|
||||||
{link.text}
|
{link.text}
|
||||||
</NewTabLink>
|
</NewTabLink>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="Footer-support-donate">
|
<div className="Footer-support-donate">
|
||||||
<div className="Footer-support-donate-currency">Donate ETH</div>
|
<div className="Footer-support-donate-currency">
|
||||||
|
{translateRaw('DONATE_CURRENCY', { $currency: 'ETH' })}
|
||||||
|
</div>
|
||||||
<div className="Footer-support-donate-address">{donationAddressMap.ETH}</div>
|
<div className="Footer-support-donate-address">{donationAddressMap.ETH}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="Footer-support-donate">
|
<div className="Footer-support-donate">
|
||||||
<div className="Footer-support-donate-currency">Donate BTC</div>
|
<div className="Footer-support-donate-currency">
|
||||||
|
{translateRaw('DONATE_CURRENCY', { $currency: 'BTC' })}
|
||||||
|
</div>
|
||||||
<div className="Footer-support-donate-address">{donationAddressMap.BTC}</div>
|
<div className="Footer-support-donate-address">{donationAddressMap.BTC}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="Footer-support-friends">
|
<div className="Footer-support-friends">
|
||||||
{FRIENDS.map(link => (
|
{FRIENDS.map((link, i) => (
|
||||||
<NewTabLink key={link.text} href={link.link}>
|
<NewTabLink key={i} href={link.link}>
|
||||||
{link.text}
|
{link.text}
|
||||||
</NewTabLink>
|
</NewTabLink>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -17,14 +17,14 @@ export const GasLimitField: React.SFC<Props> = ({ customLabel, disabled }) => (
|
||||||
<div className="input-group-wrapper AdvancedGas-gas-price">
|
<div className="input-group-wrapper AdvancedGas-gas-price">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">
|
<div className="input-group-header">
|
||||||
{customLabel ? customLabel : translate('TRANS_gas')}
|
{customLabel ? customLabel : translate('TRANS_GAS')}
|
||||||
<div className="flex-spacer" />
|
<div className="flex-spacer" />
|
||||||
<InlineSpinner active={gasEstimationPending} text="Calculating" />
|
<InlineSpinner active={gasEstimationPending} text="Calculating" />
|
||||||
</div>
|
</div>
|
||||||
<Input
|
<Input
|
||||||
className={gasLimitValidator(raw) ? 'is-valid' : 'is-invalid'}
|
className={gasLimitValidator(raw) ? 'is-valid' : 'is-invalid'}
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="e.g. 21000"
|
placeholder="21000"
|
||||||
readOnly={!!readOnly}
|
readOnly={!!readOnly}
|
||||||
value={raw}
|
value={raw}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
|
|
@ -55,14 +55,14 @@ export default class GenerateKeystoreModal extends React.Component<Props, State>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={translateRaw('Generate Keystore File')}
|
title={translateRaw('GENERATE_KEYSTORE_ACTION')}
|
||||||
isOpen={this.props.isOpen}
|
isOpen={this.props.isOpen}
|
||||||
handleClose={this.handleClose}
|
handleClose={this.handleClose}
|
||||||
>
|
>
|
||||||
<form className="GenKeystore" onSubmit={this.handleSubmit}>
|
<form className="GenKeystore" onSubmit={this.handleSubmit}>
|
||||||
<div className="input-group-wrapper GenKeystore-field">
|
<div className="input-group-wrapper GenKeystore-field">
|
||||||
<label className="input-group input-group-inline">
|
<label className="input-group input-group-inline">
|
||||||
<div className="input-group-header">Private Key</div>
|
<div className="input-group-header">{translate('X_PRIVKEY2')}</div>
|
||||||
<TogglablePassword
|
<TogglablePassword
|
||||||
name="privateKey"
|
name="privateKey"
|
||||||
value={privateKey}
|
value={privateKey}
|
||||||
|
@ -75,12 +75,14 @@ export default class GenerateKeystoreModal extends React.Component<Props, State>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-group-wrapper GenKeystore-field">
|
<div className="input-group-wrapper GenKeystore-field">
|
||||||
<label className="input-group input-group-inline">
|
<label className="input-group input-group-inline">
|
||||||
<div className="input-group-header">Password</div>
|
<div className="input-group-header">{translate('INPUT_PASSWORD_LABEL')}</div>
|
||||||
<TogglablePassword
|
<TogglablePassword
|
||||||
name="password"
|
name="password"
|
||||||
value={password}
|
value={password}
|
||||||
onChange={this.handleInput}
|
onChange={this.handleInput}
|
||||||
placeholder={translateRaw('Minimum 9 characters')}
|
placeholder={translateRaw('INPUT_PASSWORD_PLACEHOLDER', {
|
||||||
|
$pass_length: MINIMUM_PASSWORD_LENGTH.toString()
|
||||||
|
})}
|
||||||
isValid={isPasswordValid}
|
isValid={isPasswordValid}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
@ -91,24 +93,20 @@ export default class GenerateKeystoreModal extends React.Component<Props, State>
|
||||||
className="GenKeystore-button btn btn-primary btn-block"
|
className="GenKeystore-button btn btn-primary btn-block"
|
||||||
disabled={!isPrivateKeyValid || !isPasswordValid}
|
disabled={!isPrivateKeyValid || !isPasswordValid}
|
||||||
>
|
>
|
||||||
{translate('Generate Keystore File')}
|
{translate('GENERATE_KEYSTORE_ACTION')}
|
||||||
</button>
|
</button>
|
||||||
) : hasError ? (
|
) : hasError ? (
|
||||||
<p className="alert alert-danger">
|
<p className="alert alert-danger">{translate('GENERATE_KEYSTORE_FAILED')}</p>
|
||||||
Keystore generation failed or was invalid. In order to prevent loss of funds, we
|
|
||||||
cannot provide you with a keystore file that may be corrupted. Refresh the page or use
|
|
||||||
a different browser, and try again.
|
|
||||||
</p>
|
|
||||||
) : (
|
) : (
|
||||||
<a
|
<a
|
||||||
onClick={this.handleClose}
|
onClick={this.handleClose}
|
||||||
href={keystoreFile.blob}
|
href={keystoreFile.blob}
|
||||||
className="GenKeystore-button btn btn-success btn-block"
|
className="GenKeystore-button btn btn-success btn-block"
|
||||||
aria-label={translateRaw('x_Keystore')}
|
aria-label={translateRaw('X_KEYSTORE')}
|
||||||
aria-describedby={translateRaw('x_KeystoreDesc')}
|
aria-describedby={translateRaw('X_KEYSTOREDESC')}
|
||||||
download={keystoreFile.filename}
|
download={keystoreFile.filename}
|
||||||
>
|
>
|
||||||
{translate('Download Keystore File')}
|
{translate('ACTION_12')}
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -6,7 +6,7 @@ export const GenerateTransaction: React.SFC<{}> = () => (
|
||||||
<GenerateTransactionFactory
|
<GenerateTransactionFactory
|
||||||
withProps={({ disabled, isWeb3Wallet, onClick }) => (
|
withProps={({ disabled, isWeb3Wallet, onClick }) => (
|
||||||
<button disabled={disabled} className="btn btn-info btn-block" onClick={onClick}>
|
<button disabled={disabled} className="btn btn-info btn-block" onClick={onClick}>
|
||||||
{isWeb3Wallet ? translate('SEND_generate') : translate('DEP_signtx')}
|
{isWeb3Wallet ? translate('SEND_GENERATE') : translate('DEP_SIGNTX')}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -84,7 +84,7 @@ class CustomNodeModal extends React.Component<Props, State> {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'default',
|
type: 'default',
|
||||||
text: translate('x_Cancel'),
|
text: translate('ACTION_2'),
|
||||||
onClick: handleClose
|
onClick: handleClose
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -105,19 +105,18 @@ class CustomNodeModal extends React.Component<Props, State> {
|
||||||
handleClose={handleClose}
|
handleClose={handleClose}
|
||||||
maxWidth={580}
|
maxWidth={580}
|
||||||
>
|
>
|
||||||
{isHttps && <div className="alert alert-warning small">{translate('NODE_Warning')}</div>}
|
{isHttps && <div className="alert alert-warning small">{translate('NODE_WARNING')}</div>}
|
||||||
|
|
||||||
{conflictedNode && (
|
{conflictedNode && (
|
||||||
<div className="alert alert-warning small">
|
<div className="alert alert-warning small">
|
||||||
You already have a node called '{conflictedNode.name}' that matches this one, saving
|
{translate('CUSTOM_NODE_CONFLICT', { conflictedNode: conflictedNode.name })}
|
||||||
this will overwrite it
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<form className="CustomNodeModal">
|
<form className="CustomNodeModal">
|
||||||
<div className="flex-wrapper">
|
<div className="flex-wrapper">
|
||||||
<label className="col-sm-9 input-group flex-grow-1">
|
<label className="col-sm-9 input-group flex-grow-1">
|
||||||
<div className="input-group-header">Node Name</div>
|
<div className="input-group-header">{translate('CUSTOM_NODE_NAME')}</div>
|
||||||
<Input
|
<Input
|
||||||
className={`input-group-input ${this.state.name && invalids.name ? 'invalid' : ''}`}
|
className={`input-group-input ${this.state.name && invalids.name ? 'invalid' : ''}`}
|
||||||
type="text"
|
type="text"
|
||||||
|
@ -143,7 +142,7 @@ class CustomNodeModal extends React.Component<Props, State> {
|
||||||
{network === CUSTOM.value && (
|
{network === CUSTOM.value && (
|
||||||
<div className="flex-wrapper">
|
<div className="flex-wrapper">
|
||||||
<label className="col-sm-6 input-group input-group-inline">
|
<label className="col-sm-6 input-group input-group-inline">
|
||||||
<div className="input-group-header">Network Name</div>
|
<div className="input-group-header">{translate('CUSTOM_NETWORK_NAME')}</div>
|
||||||
<Input
|
<Input
|
||||||
className={`input-group-input ${
|
className={`input-group-input ${
|
||||||
this.state.customNetworkId && invalids.customNetworkId ? 'invalid' : ''
|
this.state.customNetworkId && invalids.customNetworkId ? 'invalid' : ''
|
||||||
|
@ -155,7 +154,7 @@ class CustomNodeModal extends React.Component<Props, State> {
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label className="col-sm-3 input-group input-group-inline">
|
<label className="col-sm-3 input-group input-group-inline">
|
||||||
<div className="input-group-header">Currency</div>
|
<div className="input-group-header">{translate('CUSTOM_NETWORK_CURRENCY')}</div>
|
||||||
<Input
|
<Input
|
||||||
className={`input-group-input ${
|
className={`input-group-input ${
|
||||||
this.state.customNetworkUnit && invalids.customNetworkUnit ? 'invalid' : ''
|
this.state.customNetworkUnit && invalids.customNetworkUnit ? 'invalid' : ''
|
||||||
|
@ -167,7 +166,7 @@ class CustomNodeModal extends React.Component<Props, State> {
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label className="col-sm-3 input-group input-group-inline">
|
<label className="col-sm-3 input-group input-group-inline">
|
||||||
<div className="input-group-header">Chain ID</div>
|
<div className="input-group-header">{translate('CUSTOM_NETWORK_CHAIN_ID')}</div>
|
||||||
<Input
|
<Input
|
||||||
className={`input-group-input ${
|
className={`input-group-input ${
|
||||||
this.state.customNetworkChainId && invalids.customNetworkChainId
|
this.state.customNetworkChainId && invalids.customNetworkChainId
|
||||||
|
@ -184,7 +183,7 @@ class CustomNodeModal extends React.Component<Props, State> {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<label className="input-group input-group-inline">
|
<label className="input-group input-group-inline">
|
||||||
<div className="input-group-header">URL</div>
|
<div className="input-group-header">{translate('CUSTOM_NETWORK_URL')}</div>
|
||||||
<Input
|
<Input
|
||||||
className={`input-group-input ${this.state.url && invalids.url ? 'invalid' : ''}`}
|
className={`input-group-input ${this.state.url && invalids.url ? 'invalid' : ''}`}
|
||||||
type="text"
|
type="text"
|
||||||
|
@ -202,13 +201,13 @@ class CustomNodeModal extends React.Component<Props, State> {
|
||||||
checked={this.state.hasAuth}
|
checked={this.state.hasAuth}
|
||||||
onChange={() => this.setState({ hasAuth: !this.state.hasAuth })}
|
onChange={() => this.setState({ hasAuth: !this.state.hasAuth })}
|
||||||
/>
|
/>
|
||||||
<span>HTTP Basic Authentication</span>
|
<span>{translate('CUSTOM_NETWORK_HTTP_AUTH')}</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
{this.state.hasAuth && (
|
{this.state.hasAuth && (
|
||||||
<div className="flex-wrapper ">
|
<div className="flex-wrapper ">
|
||||||
<label className="col-sm-6 input-group input-group-inline">
|
<label className="col-sm-6 input-group input-group-inline">
|
||||||
<div className="input-group-header">Username</div>
|
<div className="input-group-header">{translate('INPUT_USERNAME_LABEL')}</div>
|
||||||
<Input
|
<Input
|
||||||
className={`input-group-input ${
|
className={`input-group-input ${
|
||||||
this.state.username && invalids.username ? 'invalid' : ''
|
this.state.username && invalids.username ? 'invalid' : ''
|
||||||
|
@ -219,7 +218,7 @@ class CustomNodeModal extends React.Component<Props, State> {
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label className="col-sm-6 input-group input-group-inline">
|
<label className="col-sm-6 input-group input-group-inline">
|
||||||
<div className="input-group-header">Password</div>
|
<div className="input-group-header">{translate('INPUT_PASSWORD_LABEL')}</div>
|
||||||
<Input
|
<Input
|
||||||
className={`input-group-input ${
|
className={`input-group-input ${
|
||||||
this.state.password && invalids.password ? 'invalid' : ''
|
this.state.password && invalids.password ? 'invalid' : ''
|
||||||
|
|
|
@ -11,19 +11,19 @@ export interface TabLink {
|
||||||
|
|
||||||
const tabs: TabLink[] = [
|
const tabs: TabLink[] = [
|
||||||
{
|
{
|
||||||
name: 'Account View & Send',
|
name: 'NAV_VIEW',
|
||||||
to: '/account'
|
to: '/account'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'NAV_GenerateWallet',
|
name: 'NAV_GENERATEWALLET',
|
||||||
to: '/generate'
|
to: '/generate'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'NAV_Swap',
|
name: 'NAV_SWAP',
|
||||||
to: '/swap'
|
to: '/swap'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'NAV_Contracts',
|
name: 'NAV_CONTRACTS',
|
||||||
to: '/contracts'
|
to: '/contracts'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -31,19 +31,19 @@ const tabs: TabLink[] = [
|
||||||
to: '/ens'
|
to: '/ens'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Sign & Verify Message',
|
name: 'NAV_SIGN',
|
||||||
to: '/sign-and-verify-message'
|
to: '/sign-and-verify-message'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'NAV_TxStatus',
|
name: 'NAV_TXSTATUS',
|
||||||
to: '/tx-status'
|
to: '/tx-status'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Broadcast Transaction',
|
name: 'NAV_BROADCAST',
|
||||||
to: '/pushTx'
|
to: '/pushTx'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'NAV_Help',
|
name: 'NAV_HELP',
|
||||||
to: `${knowledgeBaseURL}`,
|
to: `${knowledgeBaseURL}`,
|
||||||
external: true
|
external: true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "common/sass/variables";
|
@import 'common/sass/variables';
|
||||||
|
|
||||||
.NavigationLink {
|
.NavigationLink {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
min-height: 2.75rem;
|
min-height: 2.75rem;
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
content: "";
|
content: '';
|
||||||
background: $brand-primary;
|
background: $brand-primary;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -45,10 +45,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#NAV_Swap a:before {
|
#NAV_SWAP a:before {
|
||||||
content:"";
|
content: '';
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-top: -.1rem;
|
margin-top: -0.1rem;
|
||||||
width: 1.3rem;
|
width: 1.3rem;
|
||||||
height: 1.3rem;
|
height: 1.3rem;
|
||||||
background-image: url('~assets/images/logo-shapeshift-no-text.svg');
|
background-image: url('~assets/images/logo-shapeshift-no-text.svg');
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||||
import Modal, { IButton } from 'components/ui/Modal';
|
import Modal, { IButton } from 'components/ui/Modal';
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
import { resetWallet, TResetWallet } from 'actions/wallet';
|
import { resetWallet, TResetWallet } from 'actions/wallet';
|
||||||
|
import translate, { translateRaw } from 'translations';
|
||||||
|
|
||||||
interface Props extends RouteComponentProps<{}> {
|
interface Props extends RouteComponentProps<{}> {
|
||||||
// State
|
// State
|
||||||
|
@ -42,17 +43,17 @@ class LogOutPromptClass extends React.Component<Props, State> {
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const buttons: IButton[] = [
|
const buttons: IButton[] = [
|
||||||
{ text: 'Log Out', type: 'primary', onClick: this.onConfirm },
|
{ text: translate('ACTION_7'), type: 'primary', onClick: this.onConfirm },
|
||||||
{ text: 'Cancel', type: 'default', onClick: this.onCancel }
|
{ text: translate('ACTION_2'), type: 'default', onClick: this.onCancel }
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title="You are about to log out"
|
title={translateRaw('WALLET_LOGOUT_MODAL_TITLE')}
|
||||||
isOpen={this.state.openModal}
|
isOpen={this.state.openModal}
|
||||||
handleClose={this.onCancel}
|
handleClose={this.onCancel}
|
||||||
buttons={buttons}
|
buttons={buttons}
|
||||||
>
|
>
|
||||||
<p>Leaving this page will log you out. Are you sure you want to continue?</p>
|
<p>{translate('WALLET_LOGOUT_MODAL_DESC')}</p>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ class NonceField extends React.Component<Props> {
|
||||||
<div className="input-group-wrapper Nonce-label">
|
<div className="input-group-wrapper Nonce-label">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">
|
<div className="input-group-header">
|
||||||
{translate('OFFLINE_Step2_Label_5')}
|
{translate('OFFLINE_STEP2_LABEL_5')}
|
||||||
<Help
|
<Help
|
||||||
size="x1"
|
size="x1"
|
||||||
link="https://support.mycrypto.com/transactions/what-is-nonce.html"
|
link="https://support.mycrypto.com/transactions/what-is-nonce.html"
|
||||||
|
@ -44,7 +44,7 @@ class NonceField extends React.Component<Props> {
|
||||||
<Input
|
<Input
|
||||||
className={`Nonce-field-input ${!!value ? 'is-valid' : 'is-invalid'}`}
|
className={`Nonce-field-input ${!!value ? 'is-valid' : 'is-invalid'}`}
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="e.g. 7"
|
placeholder="7"
|
||||||
value={raw}
|
value={raw}
|
||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { PaperWallet } from 'components';
|
import { PaperWallet } from 'components';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { translateRaw } from 'translations';
|
|
||||||
import printElement from 'utils/printElement';
|
import printElement from 'utils/printElement';
|
||||||
import { stripHexPrefix } from 'libs/values';
|
import { stripHexPrefix } from 'libs/values';
|
||||||
|
import translate, { translateRaw } from 'translations';
|
||||||
|
|
||||||
export const print = (address: string, privateKey: string) => () =>
|
export const print = (address: string, privateKey: string) => () =>
|
||||||
address &&
|
address &&
|
||||||
|
@ -38,13 +38,13 @@ const PrintableWallet: React.SFC<Props> = ({ address, privateKey }) => {
|
||||||
<PaperWallet address={address} privateKey={pkey} />
|
<PaperWallet address={address} privateKey={pkey} />
|
||||||
<a
|
<a
|
||||||
role="button"
|
role="button"
|
||||||
aria-label={translateRaw('x_Print')}
|
aria-label={translateRaw('X_PRINT')}
|
||||||
aria-describedby="x_PrintDesc"
|
aria-describedby="x_PrintDesc"
|
||||||
className="btn btn-lg btn-primary btn-block"
|
className="btn btn-lg btn-primary btn-block"
|
||||||
onClick={print(address, pkey)}
|
onClick={print(address, pkey)}
|
||||||
style={{ margin: '10px auto 0', maxWidth: '260px' }}
|
style={{ margin: '10px auto 0', maxWidth: '260px' }}
|
||||||
>
|
>
|
||||||
{translateRaw('x_Print')}
|
{translate('X_PRINT')}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,11 +12,11 @@ export const SendButton: React.SFC<{
|
||||||
onlyTransactionParameters={!!onlyTransactionParameters}
|
onlyTransactionParameters={!!onlyTransactionParameters}
|
||||||
toggleDisabled={toggleDisabled}
|
toggleDisabled={toggleDisabled}
|
||||||
Modal={customModal ? customModal : ConfirmationModal}
|
Modal={customModal ? customModal : ConfirmationModal}
|
||||||
withProps={({ disabled, onClick }) => (
|
withProps={({ disabled, onClick }: { disabled: boolean; onClick(): void }) => (
|
||||||
<div className="row form-group">
|
<div className="row form-group">
|
||||||
<div className="col-xs-12">
|
<div className="col-xs-12">
|
||||||
<button disabled={disabled} className="btn btn-primary btn-block" onClick={onClick}>
|
<button disabled={disabled} className="btn btn-primary btn-block" onClick={onClick}>
|
||||||
{translate('SEND_trans')}
|
{translate('SEND_TRANS')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -49,7 +49,7 @@ class SendButtonFactoryClass extends Component<Props> {
|
||||||
// shows the json representation of the transaction
|
// shows the json representation of the transaction
|
||||||
const leftTxCompare = serializedTransaction && (
|
const leftTxCompare = serializedTransaction && (
|
||||||
<div className={`col-sm-${columnSize}`}>
|
<div className={`col-sm-${columnSize}`}>
|
||||||
<label>{walletType.isWeb3Wallet ? 'Transaction Parameters' : translate('SEND_raw')}</label>
|
<label>{walletType.isWeb3Wallet ? 'Transaction Parameters' : translate('SEND_RAW')}</label>
|
||||||
<TextArea value={getStringifiedTx(serializedTransaction)} rows={4} readOnly={true} />
|
<TextArea value={getStringifiedTx(serializedTransaction)} rows={4} readOnly={true} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -63,7 +63,7 @@ class SendButtonFactoryClass extends Component<Props> {
|
||||||
<label>
|
<label>
|
||||||
{walletType.isWeb3Wallet
|
{walletType.isWeb3Wallet
|
||||||
? 'Serialized Transaction Parameters'
|
? 'Serialized Transaction Parameters'
|
||||||
: translate('SEND_signed')}
|
: translate('SEND_SIGNED')}
|
||||||
</label>
|
</label>
|
||||||
<TextArea
|
<TextArea
|
||||||
value={addHexPrefix(serializedTransaction.toString('hex'))}
|
value={addHexPrefix(serializedTransaction.toString('hex'))}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class SendEverythingClass extends Component<Props> {
|
||||||
!readOnly ? (
|
!readOnly ? (
|
||||||
<span className="help-block">
|
<span className="help-block">
|
||||||
<a onClick={this.onSendEverything}>
|
<a onClick={this.onSendEverything}>
|
||||||
<span className="">{translate('SEND_TransferTotal')}</span>
|
<span>{translate('SEND_TRANSFERTOTAL')}</span>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
) : null
|
) : null
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { connect } from 'react-redux';
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
import { signaturePending } from 'selectors/transaction';
|
import { signaturePending } from 'selectors/transaction';
|
||||||
import { Spinner } from 'components/ui';
|
import { Spinner } from 'components/ui';
|
||||||
|
import translate from 'translations';
|
||||||
interface StateProps {
|
interface StateProps {
|
||||||
isSignaturePending: boolean;
|
isSignaturePending: boolean;
|
||||||
isHardwareWallet: boolean;
|
isHardwareWallet: boolean;
|
||||||
|
@ -15,7 +16,7 @@ class SigningStatusClass extends Component<StateProps> {
|
||||||
const HWWalletPrompt: React.SFC<{}> = _ =>
|
const HWWalletPrompt: React.SFC<{}> = _ =>
|
||||||
isHardwareWallet ? (
|
isHardwareWallet ? (
|
||||||
<p>
|
<p>
|
||||||
<b>Confirm transaction on hardware wallet</b>
|
<b>{translate('CONFIRM_HARDWARE_WALLET_TRANSACTION')}</b>
|
||||||
</p>
|
</p>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import BN from 'bn.js';
|
import BN from 'bn.js';
|
||||||
import { translateRaw } from 'translations';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
inputGasPrice,
|
inputGasPrice,
|
||||||
|
@ -22,6 +21,7 @@ import AdvancedGas, { AdvancedOptions } from './components/AdvancedGas';
|
||||||
import './TXMetaDataPanel.scss';
|
import './TXMetaDataPanel.scss';
|
||||||
import { getGasPrice } from 'selectors/transaction';
|
import { getGasPrice } from 'selectors/transaction';
|
||||||
import { NetworkConfig } from 'types/network';
|
import { NetworkConfig } from 'types/network';
|
||||||
|
import { translateRaw } from 'translations';
|
||||||
|
|
||||||
type SliderStates = 'simple' | 'advanced';
|
type SliderStates = 'simple' | 'advanced';
|
||||||
|
|
||||||
|
@ -114,8 +114,8 @@ class TXMetaDataPanel extends React.Component<Props, State> {
|
||||||
<div className="help-block">
|
<div className="help-block">
|
||||||
<a className="Gas-toggle" onClick={this.toggleAdvanced}>
|
<a className="Gas-toggle" onClick={this.toggleAdvanced}>
|
||||||
{showAdvanced
|
{showAdvanced
|
||||||
? `- ${translateRaw('Back to simple')}`
|
? `- ${translateRaw('TRANS_SIMPLE')}`
|
||||||
: `+ ${translateRaw('Advanced Settings')}`}
|
: `+ ${translateRaw('TRANS_ADVANCED')}`}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import translate, { translateRaw } from 'translations';
|
import { translateRaw } from 'translations';
|
||||||
import FeeSummary from './FeeSummary';
|
import FeeSummary from './FeeSummary';
|
||||||
import './AdvancedGas.scss';
|
import './AdvancedGas.scss';
|
||||||
import { TToggleAutoGasLimit, toggleAutoGasLimit } from 'actions/config';
|
import { TToggleAutoGasLimit, toggleAutoGasLimit } from 'actions/config';
|
||||||
|
@ -74,7 +74,7 @@ class AdvancedGas extends React.Component<Props, State> {
|
||||||
<div className="input-group-wrapper AdvancedGas-gas-price">
|
<div className="input-group-wrapper AdvancedGas-gas-price">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">
|
<div className="input-group-header">
|
||||||
{translate('OFFLINE_Step2_Label_3')} (gwei)
|
{translateRaw('OFFLINE_STEP2_LABEL_3')} (gwei)
|
||||||
</div>
|
</div>
|
||||||
<Input
|
<Input
|
||||||
className={!!gasPrice.raw && !validGasPrice ? 'is-invalid' : ''}
|
className={!!gasPrice.raw && !validGasPrice ? 'is-invalid' : ''}
|
||||||
|
@ -89,7 +89,7 @@ class AdvancedGas extends React.Component<Props, State> {
|
||||||
|
|
||||||
{gasLimitField && (
|
{gasLimitField && (
|
||||||
<div className="AdvancedGas-gas-limit">
|
<div className="AdvancedGas-gas-limit">
|
||||||
<GasLimitField customLabel={translateRaw('OFFLINE_Step2_Label_4')} />
|
<GasLimitField customLabel={translateRaw('OFFLINE_STEP2_LABEL_4')} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{nonceField && (
|
{nonceField && (
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Slider, { createSliderWithTooltip } from 'rc-slider';
|
import Slider, { createSliderWithTooltip } from 'rc-slider';
|
||||||
import translate, { translateRaw } from 'translations';
|
import translate from 'translations';
|
||||||
import FeeSummary from './FeeSummary';
|
import FeeSummary from './FeeSummary';
|
||||||
import './SimpleGas.scss';
|
import './SimpleGas.scss';
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
|
@ -80,7 +80,7 @@ class SimpleGas extends React.Component<Props> {
|
||||||
<div className="SimpleGas row form-group">
|
<div className="SimpleGas row form-group">
|
||||||
<div className="SimpleGas-title">
|
<div className="SimpleGas-title">
|
||||||
<div className="flex-wrapper">
|
<div className="flex-wrapper">
|
||||||
<label>{translateRaw('Transaction Fee')} </label>
|
<label>{translate('CONFIRM_TX_FEE')} </label>
|
||||||
<div className="flex-spacer" />
|
<div className="flex-spacer" />
|
||||||
<InlineSpinner active={noncePending || gasLimitPending} text="Calculating" />
|
<InlineSpinner active={noncePending || gasLimitPending} text="Calculating" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -108,8 +108,8 @@ class SimpleGas extends React.Component<Props> {
|
||||||
disabled={isGasEstimating}
|
disabled={isGasEstimating}
|
||||||
/>
|
/>
|
||||||
<div className="SimpleGas-slider-labels">
|
<div className="SimpleGas-slider-labels">
|
||||||
<span>{translate('Cheap')}</span>
|
<span>{translate('TX_FEE_SCALE_LEFT')}</span>
|
||||||
<span>{translate('Fast')}</span>
|
<span>{translate('TX_FEE_SCALE_RIGHT')}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<FeeSummary
|
<FeeSummary
|
||||||
|
|
|
@ -17,7 +17,6 @@ interface Props {
|
||||||
toggleAriaLabel?: string;
|
toggleAriaLabel?: string;
|
||||||
isValid?: boolean;
|
isValid?: boolean;
|
||||||
isVisible?: boolean;
|
isVisible?: boolean;
|
||||||
validity?: 'valid' | 'invalid' | 'semivalid';
|
|
||||||
readOnly?: boolean;
|
readOnly?: boolean;
|
||||||
|
|
||||||
// Textarea-only props
|
// Textarea-only props
|
||||||
|
@ -56,7 +55,6 @@ export default class TogglablePassword extends React.PureComponent<Props, State>
|
||||||
disabled,
|
disabled,
|
||||||
ariaLabel,
|
ariaLabel,
|
||||||
toggleAriaLabel,
|
toggleAriaLabel,
|
||||||
validity,
|
|
||||||
isTextareaWhenVisible,
|
isTextareaWhenVisible,
|
||||||
isValid,
|
isValid,
|
||||||
onChange,
|
onChange,
|
||||||
|
@ -68,10 +66,10 @@ export default class TogglablePassword extends React.PureComponent<Props, State>
|
||||||
const { isVisible } = this.state;
|
const { isVisible } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`TogglablePassword input-group input-group-inline ${className}`}>
|
<div className={`TogglablePassword input-group input-group-inline`}>
|
||||||
{isTextareaWhenVisible && isVisible ? (
|
{isTextareaWhenVisible && isVisible ? (
|
||||||
<TextArea
|
<TextArea
|
||||||
className={validity || !isValid ? 'invalid' : ''}
|
className={`${className} ${!isValid ? 'invalid' : ''}`}
|
||||||
value={value}
|
value={value}
|
||||||
name={name}
|
name={name}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
@ -90,7 +88,7 @@ export default class TogglablePassword extends React.PureComponent<Props, State>
|
||||||
name={name}
|
name={name}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
type={isVisible ? 'text' : 'password'}
|
type={isVisible ? 'text' : 'password'}
|
||||||
className={`${validity || !isValid ? 'invalid' : ''} border-rad-right-0`}
|
className={`${className} ${!isValid ? 'invalid' : ''} border-rad-right-0`}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onFocus={onFocus}
|
onFocus={onFocus}
|
||||||
|
|
|
@ -71,7 +71,7 @@ const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
|
||||||
|
|
||||||
const rows: TableRow[] = [
|
const rows: TableRow[] = [
|
||||||
{
|
{
|
||||||
label: 'Status',
|
label: translate('TX_STATUS'),
|
||||||
data: (
|
data: (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<strong className={`TxData-row-data-status is-${statusType}`}>{statusMsg}</strong>
|
<strong className={`TxData-row-data-status is-${statusType}`}>{statusMsg}</strong>
|
||||||
|
@ -86,15 +86,15 @@ const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: translate('x_TxHash'),
|
label: translate('X_TXHASH'),
|
||||||
data: <MaybeLink href={explorer.tx}>{data.hash}</MaybeLink>
|
data: <MaybeLink href={explorer.tx}>{data.hash}</MaybeLink>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Block Number',
|
label: translate('TX_BLOCK_NUMB'),
|
||||||
data: receipt && <MaybeLink href={explorer.block}>{receipt.blockNumber}</MaybeLink>
|
data: receipt && <MaybeLink href={explorer.block}>{receipt.blockNumber}</MaybeLink>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: translate('OFFLINE_Step1_Label_1'),
|
label: translate('OFFLINE_STEP1_LABEL_1'),
|
||||||
data: (
|
data: (
|
||||||
<MaybeLink href={explorer.from}>
|
<MaybeLink href={explorer.from}>
|
||||||
<Identicon address={data.from} size="26px" />
|
<Identicon address={data.from} size="26px" />
|
||||||
|
@ -103,7 +103,7 @@ const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: translate('OFFLINE_Step2_Label_1'),
|
label: translate('OFFLINE_STEP2_LABEL_1'),
|
||||||
data: (
|
data: (
|
||||||
<MaybeLink href={explorer.to}>
|
<MaybeLink href={explorer.to}>
|
||||||
<Identicon address={data.to} size="26px" />
|
<Identicon address={data.to} size="26px" />
|
||||||
|
@ -112,23 +112,23 @@ const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: translate('SEND_amount_short'),
|
label: translate('SEND_AMOUNT_SHORT'),
|
||||||
data: <UnitDisplay value={data.value} unit="ether" symbol={network.unit} />
|
data: <UnitDisplay value={data.value} unit="ether" symbol={network.unit} />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: translate('OFFLINE_Step2_Label_3'),
|
label: translate('OFFLINE_STEP2_LABEL_3'),
|
||||||
data: <UnitDisplay value={data.gasPrice} unit="gwei" symbol="Gwei" />
|
data: <UnitDisplay value={data.gasPrice} unit="gwei" symbol="Gwei" />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: translate('OFFLINE_Step2_Label_4'),
|
label: translate('OFFLINE_STEP2_LABEL_4'),
|
||||||
data: <UnitDisplay value={data.gas} unit="wei" />
|
data: <UnitDisplay value={data.gas} unit="wei" />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Gas Used',
|
label: translate('TX_GAS_USED'),
|
||||||
data: receipt && <UnitDisplay value={receipt.gasUsed} unit="wei" />
|
data: receipt && <UnitDisplay value={receipt.gasUsed} unit="wei" />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Transaction Fee',
|
label: translate('CONFIRM_TX_FEE'),
|
||||||
data: receipt && (
|
data: receipt && (
|
||||||
<UnitDisplay
|
<UnitDisplay
|
||||||
value={receipt.gasUsed.mul(data.gasPrice)}
|
value={receipt.gasUsed.mul(data.gasPrice)}
|
||||||
|
@ -138,7 +138,7 @@ const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: translate('New contract address'),
|
label: translate('NEW_CONTRACT_ADDR'),
|
||||||
data: receipt &&
|
data: receipt &&
|
||||||
receipt.contractAddress && (
|
receipt.contractAddress && (
|
||||||
<MaybeLink href={explorer.contract}>
|
<MaybeLink href={explorer.contract}>
|
||||||
|
@ -147,11 +147,11 @@ const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: translate('OFFLINE_Step2_Label_5'),
|
label: translate('OFFLINE_STEP2_LABEL_5'),
|
||||||
data: data.nonce
|
data: data.nonce
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: translate('TRANS_data'),
|
label: translate('TRANS_DATA'),
|
||||||
data: hasInputData ? <TextArea value={data.input} disabled={true} /> : null
|
data: hasInputData ? <TextArea value={data.input} disabled={true} /> : null
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
@ -44,7 +44,6 @@ class TransactionStatus extends React.Component<Props> {
|
||||||
if (tx && tx.data) {
|
if (tx && tx.data) {
|
||||||
content = (
|
content = (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<h2 className="TxStatus-title">Transaction Found</h2>
|
|
||||||
<div className="TxStatus-data">
|
<div className="TxStatus-data">
|
||||||
<TransactionDataTable network={network} data={tx.data} receipt={tx.receipt} />
|
<TransactionDataTable network={network} data={tx.data} receipt={tx.receipt} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -53,13 +52,13 @@ class TransactionStatus extends React.Component<Props> {
|
||||||
} else if (tx && tx.error) {
|
} else if (tx && tx.error) {
|
||||||
content = (
|
content = (
|
||||||
<div className="TxStatus-error">
|
<div className="TxStatus-error">
|
||||||
<h2 className="TxStatus-error-title">{translate('tx_notFound')}</h2>
|
<h2 className="TxStatus-error-title">{translate('TX_NOTFOUND')}</h2>
|
||||||
<p className="TxStatus-error-desc">{translate('tx_notFound_1')}</p>
|
<p className="TxStatus-error-desc">{translate('TX_NOTFOUND_1')}</p>
|
||||||
<ul className="TxStatus-error-list">
|
<ul className="TxStatus-error-list">
|
||||||
<li>Make sure you copied the Transaction Hash correctly</li>
|
<li>{translate('TX_NOTFOUND_5')}</li>
|
||||||
<li>{translate('tx_notFound_2')}</li>
|
<li>{translate('TX_NOTFOUND_2')}</li>
|
||||||
<li>{translate('tx_notFound_3')}</li>
|
<li>{translate('TX_NOTFOUND_3')}</li>
|
||||||
<li>{translate('tx_notFound_4')}</li>
|
<li>{translate('TX_NOTFOUND_4')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,22 +1,20 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Markdown from 'react-markdown';
|
import Markdown from 'react-markdown';
|
||||||
import { translateRaw } from 'translations';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
translationKey: string;
|
source: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Translate = ({ translationKey }: Props) => {
|
const TranslateMarkdown = ({ source }: Props) => {
|
||||||
const source = translateRaw(translationKey);
|
|
||||||
return (
|
return (
|
||||||
<Markdown
|
<Markdown
|
||||||
escapeHtml={true}
|
escapeHtml={true}
|
||||||
unwrapDisallowed={true}
|
unwrapDisallowed={true}
|
||||||
allowedTypes={['link', 'emphasis', 'strong', 'code', 'root', 'inlineCode']}
|
allowedTypes={['link', 'emphasis', 'strong', 'code', 'root', 'inlineCode']}
|
||||||
renderers={{ root: 'span' }}
|
renderers={{ root: React.Fragment }}
|
||||||
source={source}
|
source={source}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Translate;
|
export default TranslateMarkdown;
|
||||||
|
|
|
@ -18,7 +18,7 @@ import {
|
||||||
TResetWallet
|
TResetWallet
|
||||||
} from 'actions/wallet';
|
} from 'actions/wallet';
|
||||||
import { reset, TReset, ResetAction } from 'actions/transaction';
|
import { reset, TReset, ResetAction } from 'actions/transaction';
|
||||||
import translate from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import {
|
import {
|
||||||
KeystoreDecrypt,
|
KeystoreDecrypt,
|
||||||
LedgerNanoSDecrypt,
|
LedgerNanoSDecrypt,
|
||||||
|
@ -50,6 +50,7 @@ import MetamaskIcon from 'assets/images/wallets/metamask.svg';
|
||||||
import MistIcon from 'assets/images/wallets/mist.svg';
|
import MistIcon from 'assets/images/wallets/mist.svg';
|
||||||
import TrezorIcon from 'assets/images/wallets/trezor.svg';
|
import TrezorIcon from 'assets/images/wallets/trezor.svg';
|
||||||
import './WalletDecrypt.scss';
|
import './WalletDecrypt.scss';
|
||||||
|
import { withRouter, RouteComponentProps } from 'react-router';
|
||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
|
@ -75,7 +76,7 @@ interface StateProps {
|
||||||
isPasswordPending: AppState['wallet']['isPasswordPending'];
|
isPasswordPending: AppState['wallet']['isPasswordPending'];
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = OwnProps & StateProps & DispatchProps;
|
type Props = OwnProps & StateProps & DispatchProps & RouteComponentProps<{}>;
|
||||||
|
|
||||||
type UnlockParams = {} | PrivateKeyValue;
|
type UnlockParams = {} | PrivateKeyValue;
|
||||||
interface State {
|
interface State {
|
||||||
|
@ -92,6 +93,7 @@ interface BaseWalletInfo {
|
||||||
helpLink: string;
|
helpLink: string;
|
||||||
isReadOnly?: boolean;
|
isReadOnly?: boolean;
|
||||||
attemptUnlock?: boolean;
|
attemptUnlock?: boolean;
|
||||||
|
redirect?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SecureWalletInfo extends BaseWalletInfo {
|
export interface SecureWalletInfo extends BaseWalletInfo {
|
||||||
|
@ -108,15 +110,15 @@ interface MiscWalletInfo extends InsecureWalletInfo {}
|
||||||
|
|
||||||
const WEB3_TYPES = {
|
const WEB3_TYPES = {
|
||||||
CipherProvider: {
|
CipherProvider: {
|
||||||
lid: 'x_Cipher',
|
lid: 'X_CIPHER',
|
||||||
icon: CipherIcon
|
icon: CipherIcon
|
||||||
},
|
},
|
||||||
MetamaskInpageProvider: {
|
MetamaskInpageProvider: {
|
||||||
lid: 'x_MetaMask',
|
lid: 'X_METAMASK',
|
||||||
icon: MetamaskIcon
|
icon: MetamaskIcon
|
||||||
},
|
},
|
||||||
EthereumProvider: {
|
EthereumProvider: {
|
||||||
lid: 'x_Mist',
|
lid: 'X_MIST',
|
||||||
icon: MistIcon
|
icon: MistIcon
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -133,311 +135,319 @@ const SECURE_WALLETS = Object.values(SecureWalletName);
|
||||||
const INSECURE_WALLETS = Object.values(InsecureWalletName);
|
const INSECURE_WALLETS = Object.values(InsecureWalletName);
|
||||||
const MISC_WALLETS = Object.values(MiscWalletName);
|
const MISC_WALLETS = Object.values(MiscWalletName);
|
||||||
|
|
||||||
export class WalletDecrypt extends Component<Props, State> {
|
const WalletDecrypt = withRouter<Props>(
|
||||||
// https://github.com/Microsoft/TypeScript/issues/13042
|
class WalletDecryptClass extends Component<RouteComponentProps<{}> & Props, State> {
|
||||||
// index signature should become [key: Wallets] (from config) once typescript bug is fixed
|
// https://github.com/Microsoft/TypeScript/issues/13042
|
||||||
public WALLETS: Wallets = {
|
// index signature should become [key: Wallets] (from config) once typescript bug is fixed
|
||||||
[SecureWalletName.WEB3]: {
|
public WALLETS: Wallets = {
|
||||||
lid: WEB3_TYPE && WEB3_TYPES[WEB3_TYPE] ? WEB3_TYPES[WEB3_TYPE].lid : 'x_Web3',
|
[SecureWalletName.WEB3]: {
|
||||||
icon: WEB3_TYPE && WEB3_TYPES[WEB3_TYPE] && WEB3_TYPES[WEB3_TYPE].icon,
|
lid: WEB3_TYPE && WEB3_TYPES[WEB3_TYPE] ? WEB3_TYPES[WEB3_TYPE].lid : 'X_WEB3',
|
||||||
description: 'ADD_Web3Desc',
|
icon: WEB3_TYPE && WEB3_TYPES[WEB3_TYPE] && WEB3_TYPES[WEB3_TYPE].icon,
|
||||||
component: Web3Decrypt,
|
description: 'ADD_WEB3DESC',
|
||||||
initialParams: {},
|
component: Web3Decrypt,
|
||||||
unlock: this.props.unlockWeb3,
|
initialParams: {},
|
||||||
attemptUnlock: true,
|
unlock: this.props.unlockWeb3,
|
||||||
helpLink: `${knowledgeBaseURL}/migration/moving-from-private-key-to-metamask`
|
attemptUnlock: true,
|
||||||
},
|
helpLink: `${knowledgeBaseURL}/migration/moving-from-private-key-to-metamask`
|
||||||
[SecureWalletName.LEDGER_NANO_S]: {
|
|
||||||
lid: 'x_Ledger',
|
|
||||||
icon: LedgerIcon,
|
|
||||||
description: 'ADD_HardwareDesc',
|
|
||||||
component: LedgerNanoSDecrypt,
|
|
||||||
initialParams: {},
|
|
||||||
unlock: this.props.setWallet,
|
|
||||||
helpLink: 'https://support.ledgerwallet.com/hc/en-us/articles/115005200009'
|
|
||||||
},
|
|
||||||
[SecureWalletName.TREZOR]: {
|
|
||||||
lid: 'x_Trezor',
|
|
||||||
icon: TrezorIcon,
|
|
||||||
description: 'ADD_HardwareDesc',
|
|
||||||
component: TrezorDecrypt,
|
|
||||||
initialParams: {},
|
|
||||||
unlock: this.props.setWallet,
|
|
||||||
helpLink: 'https://doc.satoshilabs.com/trezor-apps/mew.html'
|
|
||||||
},
|
|
||||||
[InsecureWalletName.KEYSTORE_FILE]: {
|
|
||||||
lid: 'x_Keystore2',
|
|
||||||
example: 'UTC--2017-12-15T17-35-22.547Z--6be6e49e82425a5aa56396db03512f2cc10e95e8',
|
|
||||||
component: KeystoreDecrypt,
|
|
||||||
initialParams: {
|
|
||||||
file: '',
|
|
||||||
password: ''
|
|
||||||
},
|
},
|
||||||
unlock: this.props.unlockKeystore,
|
[SecureWalletName.LEDGER_NANO_S]: {
|
||||||
helpLink: `${knowledgeBaseURL}/private-keys-passwords/difference-beween-private-key-and-keystore-file.html`
|
lid: 'X_LEDGER',
|
||||||
},
|
icon: LedgerIcon,
|
||||||
[InsecureWalletName.MNEMONIC_PHRASE]: {
|
description: 'ADD_HARDWAREDESC',
|
||||||
lid: 'x_Mnemonic',
|
component: LedgerNanoSDecrypt,
|
||||||
example: 'brain surround have swap horror cheese file distinct',
|
initialParams: {},
|
||||||
component: MnemonicDecrypt,
|
unlock: this.props.setWallet,
|
||||||
initialParams: {},
|
helpLink: 'https://support.ledgerwallet.com/hc/en-us/articles/115005200009'
|
||||||
unlock: this.props.unlockMnemonic,
|
|
||||||
helpLink: `${knowledgeBaseURL}/private-keys-passwords/difference-beween-private-key-and-keystore-file.html`
|
|
||||||
},
|
|
||||||
[InsecureWalletName.PRIVATE_KEY]: {
|
|
||||||
lid: 'x_PrivKey2',
|
|
||||||
example: 'f1d0e0789c6d40f399ca90cc674b7858de4c719e0d5752a60d5d2f6baa45d4c9',
|
|
||||||
component: PrivateKeyDecrypt,
|
|
||||||
initialParams: {
|
|
||||||
key: '',
|
|
||||||
password: ''
|
|
||||||
},
|
},
|
||||||
unlock: this.props.unlockPrivateKey,
|
[SecureWalletName.TREZOR]: {
|
||||||
helpLink: `${knowledgeBaseURL}/private-keys-passwords/difference-beween-private-key-and-keystore-file.html`
|
lid: 'X_TREZOR',
|
||||||
},
|
icon: TrezorIcon,
|
||||||
[MiscWalletName.VIEW_ONLY]: {
|
description: 'ADD_HARDWAREDESC',
|
||||||
lid: 'View Address',
|
component: TrezorDecrypt,
|
||||||
example: donationAddressMap.ETH,
|
initialParams: {},
|
||||||
component: ViewOnlyDecrypt,
|
unlock: this.props.setWallet,
|
||||||
initialParams: {},
|
helpLink: 'https://doc.satoshilabs.com/trezor-apps/mew.html'
|
||||||
unlock: this.props.setWallet,
|
},
|
||||||
helpLink: '',
|
[InsecureWalletName.KEYSTORE_FILE]: {
|
||||||
isReadOnly: true
|
lid: 'X_KEYSTORE2',
|
||||||
}
|
example: 'UTC--2017-12-15T17-35-22.547Z--6be6e49e82425a5aa56396db03512f2cc10e95e8',
|
||||||
};
|
component: KeystoreDecrypt,
|
||||||
|
initialParams: {
|
||||||
|
file: '',
|
||||||
|
password: ''
|
||||||
|
},
|
||||||
|
unlock: this.props.unlockKeystore,
|
||||||
|
helpLink: `${knowledgeBaseURL}/private-keys-passwords/difference-beween-private-key-and-keystore-file.html`
|
||||||
|
},
|
||||||
|
[InsecureWalletName.MNEMONIC_PHRASE]: {
|
||||||
|
lid: 'X_MNEMONIC',
|
||||||
|
example: 'brain surround have swap horror cheese file distinct',
|
||||||
|
component: MnemonicDecrypt,
|
||||||
|
initialParams: {},
|
||||||
|
unlock: this.props.unlockMnemonic,
|
||||||
|
helpLink: `${knowledgeBaseURL}/private-keys-passwords/difference-beween-private-key-and-keystore-file.html`
|
||||||
|
},
|
||||||
|
[InsecureWalletName.PRIVATE_KEY]: {
|
||||||
|
lid: 'X_PRIVKEY2',
|
||||||
|
example: 'f1d0e0789c6d40f399ca90cc674b7858de4c719e0d5752a60d5d2f6baa45d4c9',
|
||||||
|
component: PrivateKeyDecrypt,
|
||||||
|
initialParams: {
|
||||||
|
key: '',
|
||||||
|
password: ''
|
||||||
|
},
|
||||||
|
unlock: this.props.unlockPrivateKey,
|
||||||
|
helpLink: `${knowledgeBaseURL}/private-keys-passwords/difference-beween-private-key-and-keystore-file.html`
|
||||||
|
},
|
||||||
|
[MiscWalletName.VIEW_ONLY]: {
|
||||||
|
lid: 'VIEW_ADDR',
|
||||||
|
example: donationAddressMap.ETH,
|
||||||
|
component: ViewOnlyDecrypt,
|
||||||
|
initialParams: {},
|
||||||
|
unlock: this.props.setWallet,
|
||||||
|
helpLink: '',
|
||||||
|
isReadOnly: true,
|
||||||
|
redirect: '/account/info'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public state: State = {
|
public state: State = {
|
||||||
selectedWalletKey: null,
|
selectedWalletKey: null,
|
||||||
value: null,
|
value: null,
|
||||||
hasAcknowledgedInsecure: false
|
hasAcknowledgedInsecure: false
|
||||||
};
|
};
|
||||||
|
|
||||||
public componentWillReceiveProps(nextProps: Props) {
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
// Reset state when unlock is hidden / revealed
|
// Reset state when unlock is hidden / revealed
|
||||||
if (nextProps.hidden !== this.props.hidden) {
|
if (nextProps.hidden !== this.props.hidden) {
|
||||||
this.setState({
|
this.setState({
|
||||||
value: null,
|
value: null,
|
||||||
selectedWalletKey: null
|
selectedWalletKey: null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public getSelectedWallet() {
|
|
||||||
const { selectedWalletKey } = this.state;
|
|
||||||
if (!selectedWalletKey) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.WALLETS[selectedWalletKey];
|
public getSelectedWallet() {
|
||||||
}
|
const { selectedWalletKey } = this.state;
|
||||||
|
if (!selectedWalletKey) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public getDecryptionComponent() {
|
return this.WALLETS[selectedWalletKey];
|
||||||
const { selectedWalletKey, hasAcknowledgedInsecure } = this.state;
|
|
||||||
const selectedWallet = this.getSelectedWallet();
|
|
||||||
if (!selectedWalletKey || !selectedWallet) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (INSECURE_WALLETS.includes(selectedWalletKey) && !hasAcknowledgedInsecure) {
|
public getDecryptionComponent() {
|
||||||
|
const { selectedWalletKey, hasAcknowledgedInsecure } = this.state;
|
||||||
|
const selectedWallet = this.getSelectedWallet();
|
||||||
|
if (!selectedWalletKey || !selectedWallet) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (INSECURE_WALLETS.includes(selectedWalletKey) && !hasAcknowledgedInsecure) {
|
||||||
|
return (
|
||||||
|
<div className="WalletDecrypt-decrypt">
|
||||||
|
<InsecureWalletWarning
|
||||||
|
walletType={translate(selectedWallet.lid)}
|
||||||
|
onContinue={this.handleAcknowledgeInsecure}
|
||||||
|
onCancel={this.clearWalletChoice}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="WalletDecrypt-decrypt">
|
<div className="WalletDecrypt-decrypt">
|
||||||
<InsecureWalletWarning
|
<button className="WalletDecrypt-decrypt-back" onClick={this.clearWalletChoice}>
|
||||||
walletType={translate(selectedWallet.lid)}
|
<i className="fa fa-arrow-left" /> {translate('CHANGE_WALLET')}
|
||||||
onContinue={this.handleAcknowledgeInsecure}
|
</button>
|
||||||
onCancel={this.clearWalletChoice}
|
<h2 className="WalletDecrypt-decrypt-title">
|
||||||
/>
|
{!selectedWallet.isReadOnly && 'Unlock your'} {translate(selectedWallet.lid)}
|
||||||
|
</h2>
|
||||||
|
<section className="WalletDecrypt-decrypt-form">
|
||||||
|
<selectedWallet.component
|
||||||
|
value={this.state.value}
|
||||||
|
onChange={this.onChange}
|
||||||
|
onUnlock={(value: any) => {
|
||||||
|
if (selectedWallet.redirect) {
|
||||||
|
this.props.history.push(selectedWallet.redirect);
|
||||||
|
}
|
||||||
|
this.onUnlock(value);
|
||||||
|
}}
|
||||||
|
showNotification={this.props.showNotification}
|
||||||
|
isWalletPending={
|
||||||
|
this.state.selectedWalletKey === InsecureWalletName.KEYSTORE_FILE
|
||||||
|
? this.props.isWalletPending
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
isPasswordPending={
|
||||||
|
this.state.selectedWalletKey === InsecureWalletName.KEYSTORE_FILE
|
||||||
|
? this.props.isPasswordPending
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
public handleAcknowledgeInsecure = () => {
|
||||||
<div className="WalletDecrypt-decrypt">
|
this.setState({ hasAcknowledgedInsecure: true });
|
||||||
<button className="WalletDecrypt-decrypt-back" onClick={this.clearWalletChoice}>
|
};
|
||||||
<i className="fa fa-arrow-left" /> {translate('Change Wallet')}
|
|
||||||
</button>
|
|
||||||
<h2 className="WalletDecrypt-decrypt-title">
|
|
||||||
{!selectedWallet.isReadOnly && 'Unlock your'} {translate(selectedWallet.lid)}
|
|
||||||
</h2>
|
|
||||||
<section className="WalletDecrypt-decrypt-form">
|
|
||||||
<selectedWallet.component
|
|
||||||
value={this.state.value}
|
|
||||||
onChange={this.onChange}
|
|
||||||
onUnlock={this.onUnlock}
|
|
||||||
showNotification={this.props.showNotification}
|
|
||||||
isWalletPending={
|
|
||||||
this.state.selectedWalletKey === InsecureWalletName.KEYSTORE_FILE
|
|
||||||
? this.props.isWalletPending
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
isPasswordPending={
|
|
||||||
this.state.selectedWalletKey === InsecureWalletName.KEYSTORE_FILE
|
|
||||||
? this.props.isPasswordPending
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public handleAcknowledgeInsecure = () => {
|
public buildWalletOptions() {
|
||||||
this.setState({ hasAcknowledgedInsecure: true });
|
const { computedDisabledWallets } = this.props;
|
||||||
};
|
const { reasons } = computedDisabledWallets;
|
||||||
|
|
||||||
public buildWalletOptions() {
|
return (
|
||||||
const { computedDisabledWallets } = this.props;
|
<div className="WalletDecrypt-wallets">
|
||||||
const { reasons } = computedDisabledWallets;
|
<h2 className="WalletDecrypt-wallets-title">{translate('DECRYPT_ACCESS')}</h2>
|
||||||
|
|
||||||
return (
|
<div className="WalletDecrypt-wallets-row">
|
||||||
<div className="WalletDecrypt-wallets">
|
{SECURE_WALLETS.map((walletType: SecureWalletName) => {
|
||||||
<h2 className="WalletDecrypt-wallets-title">{translate('decrypt_Access')}</h2>
|
const wallet = this.WALLETS[walletType];
|
||||||
|
return (
|
||||||
<div className="WalletDecrypt-wallets-row">
|
<WalletButton
|
||||||
{SECURE_WALLETS.map((walletType: SecureWalletName) => {
|
key={walletType}
|
||||||
const wallet = this.WALLETS[walletType];
|
name={translateRaw(wallet.lid)}
|
||||||
return (
|
description={translateRaw(wallet.description)}
|
||||||
<WalletButton
|
icon={wallet.icon}
|
||||||
key={walletType}
|
helpLink={wallet.helpLink}
|
||||||
name={translate(wallet.lid)}
|
walletType={walletType}
|
||||||
description={translate(wallet.description)}
|
isSecure={true}
|
||||||
icon={wallet.icon}
|
isDisabled={this.isWalletDisabled(walletType)}
|
||||||
helpLink={wallet.helpLink}
|
disableReason={reasons[walletType]}
|
||||||
walletType={walletType}
|
onClick={this.handleWalletChoice}
|
||||||
isSecure={true}
|
/>
|
||||||
isDisabled={this.isWalletDisabled(walletType)}
|
);
|
||||||
disableReason={reasons[walletType]}
|
})}
|
||||||
onClick={this.handleWalletChoice}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<div className="WalletDecrypt-wallets-row">
|
|
||||||
{INSECURE_WALLETS.map((walletType: InsecureWalletName) => {
|
|
||||||
const wallet = this.WALLETS[walletType];
|
|
||||||
return (
|
|
||||||
<WalletButton
|
|
||||||
key={walletType}
|
|
||||||
name={translate(wallet.lid)}
|
|
||||||
example={wallet.example}
|
|
||||||
helpLink={wallet.helpLink}
|
|
||||||
walletType={walletType}
|
|
||||||
isSecure={false}
|
|
||||||
isDisabled={this.isWalletDisabled(walletType)}
|
|
||||||
disableReason={reasons[walletType]}
|
|
||||||
onClick={this.handleWalletChoice}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
|
|
||||||
{MISC_WALLETS.map((walletType: MiscWalletName) => {
|
|
||||||
const wallet = this.WALLETS[walletType];
|
|
||||||
return (
|
|
||||||
<WalletButton
|
|
||||||
key={walletType}
|
|
||||||
name={translate(wallet.lid)}
|
|
||||||
example={wallet.example}
|
|
||||||
helpLink={wallet.helpLink}
|
|
||||||
walletType={walletType}
|
|
||||||
isReadOnly={true}
|
|
||||||
isDisabled={this.isWalletDisabled(walletType)}
|
|
||||||
disableReason={reasons[walletType]}
|
|
||||||
onClick={this.handleWalletChoice}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{this.props.showGenerateLink && (
|
|
||||||
<div className="WalletDecrypt-wallets-generate">
|
|
||||||
Don’t have an account yet? <Link to="/generate">Click here to get one</Link>.
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
<div className="WalletDecrypt-wallets-row">
|
||||||
</div>
|
{INSECURE_WALLETS.map((walletType: InsecureWalletName) => {
|
||||||
);
|
const wallet = this.WALLETS[walletType];
|
||||||
}
|
return (
|
||||||
|
<WalletButton
|
||||||
|
key={walletType}
|
||||||
|
name={translateRaw(wallet.lid)}
|
||||||
|
example={wallet.example}
|
||||||
|
helpLink={wallet.helpLink}
|
||||||
|
walletType={walletType}
|
||||||
|
isSecure={false}
|
||||||
|
isDisabled={this.isWalletDisabled(walletType)}
|
||||||
|
disableReason={reasons[walletType]}
|
||||||
|
onClick={this.handleWalletChoice}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
public handleWalletChoice = async (walletType: WalletName) => {
|
{MISC_WALLETS.map((walletType: MiscWalletName) => {
|
||||||
const wallet = this.WALLETS[walletType];
|
const wallet = this.WALLETS[walletType];
|
||||||
|
return (
|
||||||
|
<WalletButton
|
||||||
|
key={walletType}
|
||||||
|
name={translateRaw(wallet.lid)}
|
||||||
|
example={wallet.example}
|
||||||
|
helpLink={wallet.helpLink}
|
||||||
|
walletType={walletType}
|
||||||
|
isReadOnly={true}
|
||||||
|
isDisabled={this.isWalletDisabled(walletType)}
|
||||||
|
disableReason={reasons[walletType]}
|
||||||
|
onClick={this.handleWalletChoice}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
if (!wallet) {
|
{this.props.showGenerateLink && (
|
||||||
return;
|
<div className="WalletDecrypt-wallets-generate">
|
||||||
|
<Link to="/generate">{translate('DONT_HAVE_WALLET_PROMPT')}</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let timeout = 0;
|
public handleWalletChoice = async (walletType: WalletName) => {
|
||||||
const web3Available = await isWeb3NodeAvailable();
|
const wallet = this.WALLETS[walletType];
|
||||||
if (wallet.attemptUnlock && web3Available) {
|
|
||||||
// timeout is only the maximum wait time before secondary view is shown
|
|
||||||
// send view will be shown immediately on web3 resolve
|
|
||||||
timeout = 1000;
|
|
||||||
wallet.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
window.setTimeout(() => {
|
if (!wallet) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let timeout = 0;
|
||||||
|
const web3Available = await isWeb3NodeAvailable();
|
||||||
|
if (wallet.attemptUnlock && web3Available) {
|
||||||
|
// timeout is only the maximum wait time before secondary view is shown
|
||||||
|
// send view will be shown immediately on web3 resolve
|
||||||
|
timeout = 1000;
|
||||||
|
wallet.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.setTimeout(() => {
|
||||||
|
this.setState({
|
||||||
|
selectedWalletKey: walletType,
|
||||||
|
value: wallet.initialParams,
|
||||||
|
hasAcknowledgedInsecure: false
|
||||||
|
});
|
||||||
|
}, timeout);
|
||||||
|
};
|
||||||
|
|
||||||
|
public clearWalletChoice = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedWalletKey: walletType,
|
selectedWalletKey: null,
|
||||||
value: wallet.initialParams,
|
value: null,
|
||||||
hasAcknowledgedInsecure: false
|
hasAcknowledgedInsecure: false
|
||||||
});
|
});
|
||||||
}, timeout);
|
};
|
||||||
};
|
|
||||||
|
|
||||||
public clearWalletChoice = () => {
|
public render() {
|
||||||
this.setState({
|
const { hidden } = this.props;
|
||||||
selectedWalletKey: null,
|
const selectedWallet = this.getSelectedWallet();
|
||||||
value: null,
|
const decryptionComponent = this.getDecryptionComponent();
|
||||||
hasAcknowledgedInsecure: false
|
return (
|
||||||
});
|
<div>
|
||||||
};
|
{!hidden && (
|
||||||
|
<article className="Tab-content-pane">
|
||||||
public render() {
|
<div className="WalletDecrypt">
|
||||||
const { hidden } = this.props;
|
<TransitionGroup>
|
||||||
const selectedWallet = this.getSelectedWallet();
|
{decryptionComponent && selectedWallet ? (
|
||||||
const decryptionComponent = this.getDecryptionComponent();
|
<CSSTransition classNames="DecryptContent" timeout={500} key="decrypt">
|
||||||
return (
|
{decryptionComponent}
|
||||||
<div>
|
</CSSTransition>
|
||||||
{!hidden && (
|
) : (
|
||||||
<article className="Tab-content-pane">
|
<CSSTransition classNames="DecryptContent" timeout={500} key="wallets">
|
||||||
<div className="WalletDecrypt">
|
{this.buildWalletOptions()}
|
||||||
<TransitionGroup>
|
</CSSTransition>
|
||||||
{decryptionComponent && selectedWallet ? (
|
)}
|
||||||
<CSSTransition classNames="DecryptContent" timeout={500} key="decrypt">
|
</TransitionGroup>
|
||||||
{decryptionComponent}
|
</div>
|
||||||
</CSSTransition>
|
</article>
|
||||||
) : (
|
)}
|
||||||
<CSSTransition classNames="DecryptContent" timeout={500} key="wallets">
|
</div>
|
||||||
{this.buildWalletOptions()}
|
);
|
||||||
</CSSTransition>
|
|
||||||
)}
|
|
||||||
</TransitionGroup>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public onChange = (value: UnlockParams) => {
|
|
||||||
this.setState({ value });
|
|
||||||
};
|
|
||||||
|
|
||||||
public onUnlock = (payload: any) => {
|
|
||||||
const { value, selectedWalletKey } = this.state;
|
|
||||||
if (!selectedWalletKey) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// some components (TrezorDecrypt) don't take an onChange prop, and thus
|
public onChange = (value: UnlockParams) => {
|
||||||
// this.state.value will remain unpopulated. in this case, we can expect
|
this.setState({ value });
|
||||||
// the payload to contain the unlocked wallet info.
|
};
|
||||||
const unlockValue = value && !isEmpty(value) ? value : payload;
|
|
||||||
this.WALLETS[selectedWalletKey].unlock(unlockValue);
|
|
||||||
this.props.resetTransactionState(this.props.resetIncludeExcludeProperties);
|
|
||||||
};
|
|
||||||
|
|
||||||
private isWalletDisabled = (walletKey: WalletName) => {
|
public onUnlock = (payload: any) => {
|
||||||
return this.props.computedDisabledWallets.wallets.indexOf(walletKey) !== -1;
|
const { value, selectedWalletKey } = this.state;
|
||||||
};
|
if (!selectedWalletKey) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// some components (TrezorDecrypt) don't take an onChange prop, and thus
|
||||||
|
// this.state.value will remain unpopulated. in this case, we can expect
|
||||||
|
// the payload to contain the unlocked wallet info.
|
||||||
|
const unlockValue = value && !isEmpty(value) ? value : payload;
|
||||||
|
this.WALLETS[selectedWalletKey].unlock(unlockValue);
|
||||||
|
this.props.resetTransactionState(this.props.resetIncludeExcludeProperties);
|
||||||
|
};
|
||||||
|
|
||||||
|
private isWalletDisabled = (walletKey: WalletName) => {
|
||||||
|
return this.props.computedDisabledWallets.wallets.indexOf(walletKey) !== -1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
function mapStateToProps(state: AppState, ownProps: Props) {
|
function mapStateToProps(state: AppState, ownProps: Props) {
|
||||||
const { disabledWallets } = ownProps;
|
const { disabledWallets } = ownProps;
|
||||||
|
@ -460,7 +470,7 @@ function mapStateToProps(state: AppState, ownProps: Props) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect<StateProps, DispatchProps>(mapStateToProps, {
|
export default connect(mapStateToProps, {
|
||||||
unlockKeystore,
|
unlockKeystore,
|
||||||
unlockMnemonic,
|
unlockMnemonic,
|
||||||
unlockPrivateKey,
|
unlockPrivateKey,
|
||||||
|
@ -469,4 +479,4 @@ export default connect<StateProps, DispatchProps>(mapStateToProps, {
|
||||||
resetWallet,
|
resetWallet,
|
||||||
resetTransactionState: reset,
|
resetTransactionState: reset,
|
||||||
showNotification
|
showNotification
|
||||||
})(WalletDecrypt);
|
})(WalletDecrypt) as React.ComponentClass<OwnProps>;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import Select, { Option } from 'react-select';
|
import Select, { Option } from 'react-select';
|
||||||
import translate from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import {
|
import {
|
||||||
DeterministicWalletData,
|
DeterministicWalletData,
|
||||||
getDeterministicWallets,
|
getDeterministicWallets,
|
||||||
|
@ -101,13 +101,13 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
const buttons: IButton[] = [
|
const buttons: IButton[] = [
|
||||||
{
|
{
|
||||||
text: 'Unlock this Address',
|
text: translate('ACTION_3'),
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
onClick: this.handleConfirmAddress,
|
onClick: this.handleConfirmAddress,
|
||||||
disabled: !selectedAddress
|
disabled: !selectedAddress
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Cancel',
|
text: translate('ACTION_2'),
|
||||||
type: 'default',
|
type: 'default',
|
||||||
onClick: onCancel
|
onClick: onCancel
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={`Unlock your ${walletType || ''} Wallet`}
|
title={translateRaw(`DECRYPT_PROMPT_UNLOCK_${walletType}`)}
|
||||||
isOpen={this.props.isOpen}
|
isOpen={this.props.isOpen}
|
||||||
buttons={buttons}
|
buttons={buttons}
|
||||||
handleClose={onCancel}
|
handleClose={onCancel}
|
||||||
|
@ -125,7 +125,7 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
|
||||||
className="DWModal-path form-group-sm flex-wrapper"
|
className="DWModal-path form-group-sm flex-wrapper"
|
||||||
onSubmit={this.handleSubmitCustomPath}
|
onSubmit={this.handleSubmitCustomPath}
|
||||||
>
|
>
|
||||||
<span className="DWModal-path-label">Addresses </span>
|
<span className="DWModal-path-label">{translate('DECRYPT_DROPDOWN_LABEL')} </span>
|
||||||
<div className="DWModal-path-select">
|
<div className="DWModal-path-select">
|
||||||
<Select
|
<Select
|
||||||
name="fieldDPath"
|
name="fieldDPath"
|
||||||
|
@ -180,7 +180,7 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td>More</td>
|
<td>{translate('ACTION_5')}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>{wallets.map(wallet => this.renderWalletRow(wallet))}</tbody>
|
<tbody>{wallets.map(wallet => this.renderWalletRow(wallet))}</tbody>
|
||||||
|
@ -192,13 +192,13 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
|
||||||
disabled={page === 0}
|
disabled={page === 0}
|
||||||
onClick={this.prevPage}
|
onClick={this.prevPage}
|
||||||
>
|
>
|
||||||
← Back
|
← {translate('ACTION_4')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="DWModal-addresses-nav-btn btn btn-sm btn-default"
|
className="DWModal-addresses-nav-btn btn btn-sm btn-default"
|
||||||
onClick={this.nextPage}
|
onClick={this.nextPage}
|
||||||
>
|
>
|
||||||
More →
|
{translate('ACTION_5')} →
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { HelpLink } from 'components/ui';
|
|
||||||
import { HELP_ARTICLE } from 'config';
|
import { HELP_ARTICLE } from 'config';
|
||||||
import './InsecureWalletWarning.scss';
|
import './InsecureWalletWarning.scss';
|
||||||
|
import translate from 'translations';
|
||||||
|
import { knowledgeBaseURL } from 'config/data';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
walletType: string | React.ReactElement<string>;
|
walletType: string | React.ReactElement<string>;
|
||||||
|
@ -43,15 +44,15 @@ export class InsecureWalletWarning extends React.Component<Props, State> {
|
||||||
const checkboxes: Checkbox[] = [
|
const checkboxes: Checkbox[] = [
|
||||||
{
|
{
|
||||||
name: 'hasAcknowledgedWallets',
|
name: 'hasAcknowledgedWallets',
|
||||||
label: 'I acknowledge that I can and should use MetaMask or a Hardware Wallet'
|
label: translate('INSECURE_WALLET_WARNING_1')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'hasAcknowledgedDownload',
|
name: 'hasAcknowledgedDownload',
|
||||||
label: 'I acknowledge that I can and should download and run MyCrypto locally'
|
label: translate('INSECURE_WALLET_WARNING_2')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'hasConfirmedSite',
|
name: 'hasConfirmedSite',
|
||||||
label: 'I have checked the URL and SSL certificate to make sure this is the real MyCrypto'
|
label: translate('INSECURE_WALLET_WARNING_3')
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
const canContinue = checkboxes.reduce(
|
const canContinue = checkboxes.reduce(
|
||||||
|
@ -61,38 +62,31 @@ export class InsecureWalletWarning extends React.Component<Props, State> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="WalletWarning">
|
<div className="WalletWarning">
|
||||||
<h2 className="WalletWarning-title">
|
<h2 className="WalletWarning-title">{translate('INSECURE_WALLET_TYPE_TITLE')}</h2>
|
||||||
This is <u>not</u> a recommended way to access your wallet
|
|
||||||
</h2>
|
|
||||||
<p className="WalletWarning-desc">
|
<p className="WalletWarning-desc">
|
||||||
Entering your {walletType} on a website is <strong>dangerous</strong>. If our website is
|
{translate('INSECURE_WALLET_TYPE_DESC', { $wallet_type: walletType as string })}
|
||||||
compromised, or you accidentally visit a phishing website, you could{' '}
|
|
||||||
<strong>lose all of your funds</strong>. Before you continue, please consider:
|
|
||||||
</p>
|
</p>
|
||||||
<ul className="WalletWarning-bullets">
|
<ul className="WalletWarning-bullets">
|
||||||
<li>
|
<li>
|
||||||
Using <HelpLink article={HELP_ARTICLE.MIGRATE_TO_METAMASK}>MetaMask</HelpLink> or a{' '}
|
{translate('INSECURE_WALLET_RECOMMEND_1', {
|
||||||
<HelpLink article={HELP_ARTICLE.HARDWARE_WALLET_RECOMMENDATIONS}>
|
$metamask_article: knowledgeBaseURL + '/' + HELP_ARTICLE.MIGRATE_TO_METAMASK,
|
||||||
Hardware Wallet
|
$hardware_wallet_article:
|
||||||
</HelpLink>{' '}
|
knowledgeBaseURL + '/' + HELP_ARTICLE.HARDWARE_WALLET_RECOMMENDATIONS
|
||||||
to access your wallet
|
})}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<HelpLink article={HELP_ARTICLE.RUNNING_LOCALLY}>
|
{translate('INSECURE_WALLET_RECOMMEND_2', {
|
||||||
Downloading MyCrypto and running it offline & locally
|
$run_local_article: knowledgeBaseURL + '/' + HELP_ARTICLE.RUNNING_LOCALLY
|
||||||
</HelpLink>
|
})}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Reading{' '}
|
{translate('INSECURE_WALLET_RECOMMEND_3', {
|
||||||
<HelpLink article={HELP_ARTICLE.SECURING_YOUR_ETH}>
|
$secure_your_eth_article: knowledgeBaseURL + '/' + HELP_ARTICLE.SECURING_YOUR_ETH
|
||||||
How to Protect Yourself and Your Funds
|
})}
|
||||||
</HelpLink>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p className="WalletWarning-check">
|
<p className="WalletWarning-check">
|
||||||
If you must use your {walletType} online, please double-check the URL & SSL certificate.
|
{translate('WALLET_WARNING_CHECK', { $wallet_type: walletType as string })}
|
||||||
It should say <code>{'https://www.mycrypto.com'}</code>
|
|
||||||
& <code>MyCrypto, Inc (US)</code> in your URL bar.
|
|
||||||
</p>
|
</p>
|
||||||
<div className="WalletWarning-checkboxes">{checkboxes.map(this.makeCheckbox)}</div>
|
<div className="WalletWarning-checkboxes">{checkboxes.map(this.makeCheckbox)}</div>
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ export class KeystoreDecrypt extends PureComponent {
|
||||||
/>
|
/>
|
||||||
<label htmlFor="fselector" style={{ width: '100%' }}>
|
<label htmlFor="fselector" style={{ width: '100%' }}>
|
||||||
<a className="btn btn-default btn-block" id="aria1" tabIndex={0} role="button">
|
<a className="btn btn-default btn-block" id="aria1" tabIndex={0} role="button">
|
||||||
{translate('ADD_Radio_2_short')}
|
{translate('ADD_RADIO_2_SHORT')}
|
||||||
</a>
|
</a>
|
||||||
</label>
|
</label>
|
||||||
{isWalletPending ? <Spinner /> : ''}
|
{isWalletPending ? <Spinner /> : ''}
|
||||||
|
@ -63,13 +63,13 @@ export class KeystoreDecrypt extends PureComponent {
|
||||||
value={password}
|
value={password}
|
||||||
onChange={this.onPasswordChange}
|
onChange={this.onPasswordChange}
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
placeholder={translateRaw('x_Password')}
|
placeholder={translateRaw('INPUT_PASSWORD_LABEL')}
|
||||||
type="password"
|
type="password"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button className="btn btn-primary btn-block" disabled={unlockDisabled}>
|
<button className="btn btn-primary btn-block" disabled={unlockDisabled}>
|
||||||
{translate('ADD_Label_6_short')}
|
{translate('ADD_LABEL_6_SHORT')}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import './LedgerNano.scss';
|
import './LedgerNano.scss';
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import translate, { translateRaw } from 'translations';
|
import translate from 'translations';
|
||||||
import DeterministicWalletsModal from './DeterministicWalletsModal';
|
import DeterministicWalletsModal from './DeterministicWalletsModal';
|
||||||
import { LedgerWallet } from 'libs/wallet';
|
import { LedgerWallet } from 'libs/wallet';
|
||||||
import ledger from 'ledgerco';
|
import ledger from 'ledgerco';
|
||||||
|
@ -83,23 +83,22 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="LedgerDecrypt-message">
|
<div className="LedgerDecrypt-message">
|
||||||
<Spinner light={true} />
|
<Spinner light={true} />
|
||||||
Unlocking...
|
{translate('WALLET_UNLOCKING')}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
translate('ADD_Ledger_scan')
|
translate('ADD_LEDGER_SCAN')
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<NewTabLink className="LedgerDecrypt-buy btn btn-sm btn-default" href={ledgerReferralURL}>
|
<NewTabLink className="LedgerDecrypt-buy btn btn-sm btn-default" href={ledgerReferralURL}>
|
||||||
{translate('Don’t have a Ledger? Order one now!')}
|
{translate('LEDGER_REFERAL_2')}
|
||||||
</NewTabLink>
|
</NewTabLink>
|
||||||
|
|
||||||
<div className={`LedgerDecrypt-error alert alert-danger ${showErr}`}>{error || '-'}</div>
|
<div className={`LedgerDecrypt-error alert alert-danger ${showErr}`}>{error || '-'}</div>
|
||||||
|
|
||||||
<div className="LedgerDecrypt-help">
|
<div className="LedgerDecrypt-help">
|
||||||
Guide:{' '}
|
|
||||||
<NewTabLink href="https://support.ledgerwallet.com/hc/en-us/articles/115005200009">
|
<NewTabLink href="https://support.ledgerwallet.com/hc/en-us/articles/115005200009">
|
||||||
How to use MyCrypto with your Nano S
|
{translate('HELP_ARTICLE_1')}
|
||||||
</NewTabLink>
|
</NewTabLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -112,7 +111,7 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
|
||||||
onCancel={this.handleCancel}
|
onCancel={this.handleCancel}
|
||||||
onConfirmAddress={this.handleUnlock}
|
onConfirmAddress={this.handleUnlock}
|
||||||
onPathChange={this.handlePathChange}
|
onPathChange={this.handlePathChange}
|
||||||
walletType={translateRaw('x_Ledger')}
|
walletType={'LEDGER'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -55,7 +55,7 @@ class MnemonicDecryptClass extends PureComponent<Props, State> {
|
||||||
<TogglablePassword
|
<TogglablePassword
|
||||||
value={phrase}
|
value={phrase}
|
||||||
rows={4}
|
rows={4}
|
||||||
placeholder={translateRaw('x_Mnemonic')}
|
placeholder={translateRaw('X_MNEMONIC')}
|
||||||
isValid={isValidMnemonic}
|
isValid={isValidMnemonic}
|
||||||
isTextareaWhenVisible={true}
|
isTextareaWhenVisible={true}
|
||||||
onChange={this.onMnemonicChange}
|
onChange={this.onMnemonicChange}
|
||||||
|
@ -63,11 +63,11 @@ class MnemonicDecryptClass extends PureComponent<Props, State> {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<p>Password (optional):</p>
|
<p>{translate('ADD_LABEL_8')}</p>
|
||||||
<Input
|
<Input
|
||||||
value={pass}
|
value={pass}
|
||||||
onChange={this.onPasswordChange}
|
onChange={this.onPasswordChange}
|
||||||
placeholder={translateRaw('x_Password')}
|
placeholder={translateRaw('INPUT_PASSWORD_LABEL')}
|
||||||
type="password"
|
type="password"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,7 +78,7 @@ class MnemonicDecryptClass extends PureComponent<Props, State> {
|
||||||
className="btn btn-primary btn-lg"
|
className="btn btn-primary btn-lg"
|
||||||
disabled={!isValidMnemonic}
|
disabled={!isValidMnemonic}
|
||||||
>
|
>
|
||||||
{translate('Choose Address')}
|
{translate('MNEMONIC_CHOOSE_ADDR')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -91,7 +91,7 @@ class MnemonicDecryptClass extends PureComponent<Props, State> {
|
||||||
onCancel={this.handleCancel}
|
onCancel={this.handleCancel}
|
||||||
onConfirmAddress={this.handleUnlock}
|
onConfirmAddress={this.handleUnlock}
|
||||||
onPathChange={this.handlePathChange}
|
onPathChange={this.handlePathChange}
|
||||||
walletType={translateRaw('x_Mnemonic')}
|
walletType={'MNEMONIC'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -59,7 +59,7 @@ export class PrivateKeyDecrypt extends PureComponent<Props> {
|
||||||
<TogglablePassword
|
<TogglablePassword
|
||||||
value={key}
|
value={key}
|
||||||
rows={4}
|
rows={4}
|
||||||
placeholder={translateRaw('x_PrivKey2')}
|
placeholder={translateRaw('X_PRIVKEY2')}
|
||||||
isValid={isValidPkey}
|
isValid={isValidPkey}
|
||||||
onChange={this.onPkeyChange}
|
onChange={this.onPkeyChange}
|
||||||
onEnter={this.props.onUnlock}
|
onEnter={this.props.onUnlock}
|
||||||
|
@ -70,20 +70,20 @@ export class PrivateKeyDecrypt extends PureComponent<Props> {
|
||||||
isPassRequired && (
|
isPassRequired && (
|
||||||
<div className="input-group-wrapper">
|
<div className="input-group-wrapper">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translate('ADD_Label_3')}</div>
|
<div className="input-group-header">{translate('ADD_LABEL_3')}</div>
|
||||||
<Input
|
<Input
|
||||||
className={`form-control ${password.length > 0 ? 'is-valid' : 'is-invalid'}`}
|
className={`form-control ${password.length > 0 ? 'is-valid' : 'is-invalid'}`}
|
||||||
value={password}
|
value={password}
|
||||||
onChange={this.onPasswordChange}
|
onChange={this.onPasswordChange}
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
placeholder={translateRaw('x_Password')}
|
placeholder={translateRaw('INPUT_PASSWORD_LABEL')}
|
||||||
type="password"
|
type="password"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<button className="btn btn-block btn-primary" disabled={unlockDisabled}>
|
<button className="btn btn-block btn-primary" disabled={unlockDisabled}>
|
||||||
{translate('ADD_Label_6_short')}
|
{translate('ADD_LABEL_6_SHORT')}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { TrezorWallet, TREZOR_MINIMUM_FIRMWARE } from 'libs/wallet';
|
import { TrezorWallet, TREZOR_MINIMUM_FIRMWARE } from 'libs/wallet';
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import translate, { translateRaw } from 'translations';
|
import translate from 'translations';
|
||||||
import TrezorConnect from 'vendor/trezor-connect';
|
import TrezorConnect from 'vendor/trezor-connect';
|
||||||
import DeterministicWalletsModal from './DeterministicWalletsModal';
|
import DeterministicWalletsModal from './DeterministicWalletsModal';
|
||||||
import './Trezor.scss';
|
import './Trezor.scss';
|
||||||
|
@ -63,7 +63,7 @@ class TrezorDecryptClass extends PureComponent<Props, State> {
|
||||||
Unlocking...
|
Unlocking...
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
translate('ADD_Trezor_scan')
|
translate('ADD_TREZOR_SCAN')
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -74,7 +74,6 @@ class TrezorDecryptClass extends PureComponent<Props, State> {
|
||||||
<div className={`TrezorDecrypt-error alert alert-danger ${showErr}`}>{error || '-'}</div>
|
<div className={`TrezorDecrypt-error alert alert-danger ${showErr}`}>{error || '-'}</div>
|
||||||
|
|
||||||
<div className="TrezorDecrypt-help">
|
<div className="TrezorDecrypt-help">
|
||||||
Guide:{' '}
|
|
||||||
<NewTabLink href="https://blog.trezor.io/trezor-integration-with-myetherwallet-3e217a652e08">
|
<NewTabLink href="https://blog.trezor.io/trezor-integration-with-myetherwallet-3e217a652e08">
|
||||||
How to use TREZOR with MyCrypto
|
How to use TREZOR with MyCrypto
|
||||||
</NewTabLink>
|
</NewTabLink>
|
||||||
|
@ -89,7 +88,7 @@ class TrezorDecryptClass extends PureComponent<Props, State> {
|
||||||
onCancel={this.handleCancel}
|
onCancel={this.handleCancel}
|
||||||
onConfirmAddress={this.handleUnlock}
|
onConfirmAddress={this.handleUnlock}
|
||||||
onPathChange={this.handlePathChange}
|
onPathChange={this.handlePathChange}
|
||||||
walletType={translateRaw('x_Trezor')}
|
walletType={'TREZOR'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -35,7 +35,7 @@ export class ViewOnlyDecrypt extends PureComponent<Props, State> {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button className="btn btn-primary btn-block" disabled={!isValid}>
|
<button className="btn btn-primary btn-block" disabled={!isValid}>
|
||||||
{translate('NAV_ViewWallet')}
|
{translate('NAV_VIEWWALLET')}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { translateRaw, TranslateType } from 'translations';
|
|
||||||
import { NewTabLink, Tooltip } from 'components/ui';
|
import { NewTabLink, Tooltip } from 'components/ui';
|
||||||
import './WalletButton.scss';
|
import './WalletButton.scss';
|
||||||
|
|
||||||
import { WalletName } from 'config';
|
import { WalletName } from 'config';
|
||||||
|
import { translateRaw } from 'translations';
|
||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
name: TranslateType;
|
name: string;
|
||||||
description?: TranslateType;
|
description?: string;
|
||||||
example?: TranslateType;
|
example?: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
helpLink: string;
|
helpLink: string;
|
||||||
walletType: WalletName;
|
walletType: WalletName;
|
||||||
|
@ -51,20 +51,20 @@ export class WalletButton extends React.PureComponent<Props> {
|
||||||
if (isReadOnly) {
|
if (isReadOnly) {
|
||||||
icons.push({
|
icons.push({
|
||||||
icon: 'eye',
|
icon: 'eye',
|
||||||
tooltip: translateRaw('You cannot send using address only'),
|
tooltip: translateRaw('TOOLTIP_READ_ONLY_WALLET'),
|
||||||
arialabel: 'Read Only'
|
arialabel: 'Read Only'
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (isSecure) {
|
if (isSecure) {
|
||||||
icons.push({
|
icons.push({
|
||||||
icon: 'shield',
|
icon: 'shield',
|
||||||
tooltip: translateRaw('This wallet type is secure'),
|
tooltip: translateRaw('TOOLTIP_SECURE_WALLET_TYPE'),
|
||||||
arialabel: 'Secure wallet type'
|
arialabel: 'Secure wallet type'
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
icons.push({
|
icons.push({
|
||||||
icon: 'exclamation-triangle',
|
icon: 'exclamation-triangle',
|
||||||
tooltip: translateRaw('This wallet type is insecure'),
|
tooltip: translateRaw('TOOLTIP_INSECURE_WALLET_TYPE'),
|
||||||
arialabel: 'Insecure wallet type'
|
arialabel: 'Insecure wallet type'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ export class WalletButton extends React.PureComponent<Props> {
|
||||||
if (helpLink) {
|
if (helpLink) {
|
||||||
icons.push({
|
icons.push({
|
||||||
icon: 'question-circle',
|
icon: 'question-circle',
|
||||||
tooltip: translateRaw('NAV_Help'),
|
tooltip: translateRaw('TOOLTIP_MORE_INFO'),
|
||||||
href: helpLink,
|
href: helpLink,
|
||||||
arialabel: 'More info'
|
arialabel: 'More info'
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,14 +11,14 @@ export const Web3Decrypt: React.SFC<Props> = ({ onUnlock }) => (
|
||||||
<div className="Web3Decrypt">
|
<div className="Web3Decrypt">
|
||||||
<div>
|
<div>
|
||||||
<button className="Web3Decrypt-decrypt btn btn-primary btn-lg btn-block" onClick={onUnlock}>
|
<button className="Web3Decrypt-decrypt btn btn-primary btn-lg btn-block" onClick={onUnlock}>
|
||||||
{translate('ADD_MetaMask')}
|
{translate('ADD_METAMASK')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<NewTabLink
|
<NewTabLink
|
||||||
className="Web3Decrypt-install btn btn-sm btn-default btn-block"
|
className="Web3Decrypt-install btn btn-sm btn-default btn-block"
|
||||||
content={translate('Download MetaMask')}
|
content={translate('ACTION_13', { $thing: 'MetaMask' })}
|
||||||
href="https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=en"
|
href="https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=en"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,7 +9,7 @@ type ButtonType = 'default' | 'primary' | 'success' | 'info' | 'warning' | 'dang
|
||||||
type ButtonSize = 'lg' | 'sm' | 'xs';
|
type ButtonSize = 'lg' | 'sm' | 'xs';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
text: React.ReactElement<any> | string;
|
text: string;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
loadingText?: string;
|
loadingText?: string;
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
import translate, { TranslateType } from 'translations';
|
import translate from 'translations';
|
||||||
import WalletDecrypt, { DisabledWallets } from 'components/WalletDecrypt';
|
import WalletDecrypt, { DisabledWallets } from 'components/WalletDecrypt';
|
||||||
import { IWallet } from 'libs/wallet/IWallet';
|
import { IWallet } from 'libs/wallet/IWallet';
|
||||||
import closeIcon from 'assets/images/close.svg';
|
import closeIcon from 'assets/images/close.svg';
|
||||||
import './UnlockHeader.scss';
|
import './UnlockHeader.scss';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: TranslateType;
|
title: string;
|
||||||
wallet: IWallet;
|
wallet: IWallet;
|
||||||
disabledWallets?: DisabledWallets;
|
disabledWallets?: DisabledWallets;
|
||||||
showGenerateLink?: boolean;
|
showGenerateLink?: boolean;
|
||||||
|
@ -44,7 +44,7 @@ export class UnlockHeader extends React.PureComponent<Props, State> {
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
<span className="hidden-xs UnlockHeader-open-text">
|
<span className="hidden-xs UnlockHeader-open-text">
|
||||||
{translate('Change Wallet')}
|
{translate('CHANGE_WALLET')}
|
||||||
</span>
|
</span>
|
||||||
<i className="fa fa-refresh" />
|
<i className="fa fa-refresh" />
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -4,15 +4,15 @@ import OnboardSlide from './OnboardSlide';
|
||||||
import onboardIconFour from 'assets/images/onboarding/slide-04.svg';
|
import onboardIconFour from 'assets/images/onboarding/slide-04.svg';
|
||||||
|
|
||||||
const BlockchainSlide = () => {
|
const BlockchainSlide = () => {
|
||||||
const header = translate('ONBOARD_blockchain_title');
|
const header = translate('ONBOARD_BLOCKCHAIN_TITLE');
|
||||||
const content = (
|
const content = (
|
||||||
<ul>
|
<ul>
|
||||||
<li>{translate('ONBOARD_blockchain_content__1')}</li>
|
<li>{translate('ONBOARD_BLOCKCHAIN_CONTENT__1')}</li>
|
||||||
<li>{translate('ONBOARD_blockchain_content__2')}</li>
|
<li>{translate('ONBOARD_BLOCKCHAIN_CONTENT__2')}</li>
|
||||||
<li>{translate('ONBOARD_blockchain_content__3')}</li>
|
<li>{translate('ONBOARD_BLOCKCHAIN_CONTENT__3')}</li>
|
||||||
<li>{translate('ONBOARD_blockchain_content__4')}</li>
|
<li>{translate('ONBOARD_BLOCKCHAIN_CONTENT__4')}</li>
|
||||||
<li>{translate('ONBOARD_blockchain_content__5')}</li>
|
<li>{translate('ONBOARD_BLOCKCHAIN_CONTENT__5')}</li>
|
||||||
<li>{translate('ONBOARD_blockchain_content__6')}</li>
|
<li>{translate('ONBOARD_BLOCKCHAIN_CONTENT__6')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -11,49 +11,49 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const FinalSlide: React.SFC<Props> = ({ closeModal }) => {
|
const FinalSlide: React.SFC<Props> = ({ closeModal }) => {
|
||||||
const header = translate('ONBOARD_final_title');
|
const header = translate('ONBOARD_FINAL_TITLE');
|
||||||
const subheader = translate('ONBOARD_final_subtitle');
|
const subheader = translate('ONBOARD_FINAL_SUBTITLE');
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<HelpLink article={HELP_ARTICLE.HARDWARE_WALLET_RECOMMENDATIONS} className="strong">
|
<HelpLink article={HELP_ARTICLE.HARDWARE_WALLET_RECOMMENDATIONS} className="strong">
|
||||||
{translate('ONBOARD_final_content__2')}
|
{translate('ONBOARD_FINAL_CONTENT__2')}
|
||||||
</HelpLink>
|
</HelpLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<HelpLink article={HELP_ARTICLE.MIGRATE_TO_METAMASK} className="strong">
|
<HelpLink article={HELP_ARTICLE.MIGRATE_TO_METAMASK} className="strong">
|
||||||
{translate('ONBOARD_final_content__3')}
|
{translate('ONBOARD_FINAL_CONTENT__3')}
|
||||||
</HelpLink>
|
</HelpLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<HelpLink article={HELP_ARTICLE.RUNNING_LOCALLY} className="strong">
|
<HelpLink article={HELP_ARTICLE.RUNNING_LOCALLY} className="strong">
|
||||||
{translate('ONBOARD_final_content__4')}
|
{translate('ONBOARD_FINAL_CONTENT__4')}
|
||||||
</HelpLink>
|
</HelpLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<HelpLink article={HELP_ARTICLE.MIGRATE_TO_LEDGER} className="strong">
|
<HelpLink article={HELP_ARTICLE.MIGRATE_TO_LEDGER} className="strong">
|
||||||
{translate('ONBOARD_final_content__5')}
|
{translate('ONBOARD_FINAL_CONTENT__5')}
|
||||||
</HelpLink>
|
</HelpLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<HelpLink article={HELP_ARTICLE.SENDING_TO_TREZOR} className="strong">
|
<HelpLink article={HELP_ARTICLE.SENDING_TO_TREZOR} className="strong">
|
||||||
{translate('ONBOARD_final_content__6')}
|
{translate('ONBOARD_FINAL_CONTENT__6')}
|
||||||
</HelpLink>
|
</HelpLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<HelpLink article={HELP_ARTICLE.MIGRATE_TO_METAMASK} className="strong">
|
<HelpLink article={HELP_ARTICLE.MIGRATE_TO_METAMASK} className="strong">
|
||||||
{translate('ONBOARD_final_content__7')}
|
{translate('ONBOARD_FINAL_CONTENT__7')}
|
||||||
</HelpLink>
|
</HelpLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<HelpLink article={HELP_ARTICLE.HOME} className="strong">
|
<HelpLink article={HELP_ARTICLE.HOME} className="strong">
|
||||||
{translate('ONBOARD_final_content__8')}
|
{translate('ONBOARD_FINAL_CONTENT__8')}
|
||||||
</HelpLink>
|
</HelpLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link onClick={closeModal} to="/account" className="strong">
|
<Link onClick={closeModal} to="/account" className="strong">
|
||||||
<span> {translate('ONBOARD_final_content__9')}</span>
|
<span> {translate('ONBOARD_FINAL_CONTENT__9')}</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -4,17 +4,17 @@ import OnboardSlide from './OnboardSlide';
|
||||||
import onboardIconThree from 'assets/images/onboarding/slide-03.svg';
|
import onboardIconThree from 'assets/images/onboarding/slide-03.svg';
|
||||||
|
|
||||||
const InterfaceSlide = () => {
|
const InterfaceSlide = () => {
|
||||||
const header = translate('ONBOARD_interface_title');
|
const header = translate('ONBOARD_INTERFACE_TITLE');
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<ul>
|
<ul>
|
||||||
<li>{translate('ONBOARD_interface_content__1')}</li>
|
<li>{translate('ONBOARD_INTERFACE_CONTENT__1')}</li>
|
||||||
<li>{translate('ONBOARD_interface_content__2')}</li>
|
<li>{translate('ONBOARD_INTERFACE_CONTENT__2')}</li>
|
||||||
<li>{translate('ONBOARD_interface_content__3')}</li>
|
<li>{translate('ONBOARD_INTERFACE_CONTENT__3')}</li>
|
||||||
<li>{translate('ONBOARD_interface_content__4')}</li>
|
<li>{translate('ONBOARD_INTERFACE_CONTENT__4')}</li>
|
||||||
<li>{translate('ONBOARD_interface_content__5')}</li>
|
<li>{translate('ONBOARD_INTERFACE_CONTENT__5')}</li>
|
||||||
<li>{translate('ONBOARD_interface_content__6')}</li>
|
<li>{translate('ONBOARD_INTERFACE_CONTENT__6')}</li>
|
||||||
<li>{translate('ONBOARD_interface_content__7')}</li>
|
<li>{translate('ONBOARD_INTERFACE_CONTENT__7')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -4,15 +4,15 @@ import OnboardSlide from './OnboardSlide';
|
||||||
import onboardIconTwo from 'assets/images/onboarding/slide-02.svg';
|
import onboardIconTwo from 'assets/images/onboarding/slide-02.svg';
|
||||||
|
|
||||||
const NotABankSlide = () => {
|
const NotABankSlide = () => {
|
||||||
const header = translate('ONBOARD_bank_title');
|
const header = translate('ONBOARD_BANK_TITLE');
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<ul>
|
<ul>
|
||||||
<li>{translate('ONBOARD_bank_content__1')}</li>
|
<li>{translate('ONBOARD_BANK_CONTENT__1')}</li>
|
||||||
<li>{translate('ONBOARD_bank_content__2')}</li>
|
<li>{translate('ONBOARD_BANK_CONTENT__2')}</li>
|
||||||
<li>{translate('ONBOARD_bank_content__3')}</li>
|
<li>{translate('ONBOARD_BANK_CONTENT__3')}</li>
|
||||||
<li>{translate('ONBOARD_bank_content__4')}</li>
|
<li>{translate('ONBOARD_BANK_CONTENT__4')}</li>
|
||||||
<li>{translate('ONBOARD_bank_content__5')}</li>
|
<li>{translate('ONBOARD_BANK_CONTENT__5')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -4,18 +4,18 @@ import OnboardSlide from './OnboardSlide';
|
||||||
import onboardIconSeven from 'assets/images/onboarding/slide-07.svg';
|
import onboardIconSeven from 'assets/images/onboarding/slide-07.svg';
|
||||||
|
|
||||||
const SecureSlideOne = () => {
|
const SecureSlideOne = () => {
|
||||||
const header = translate('ONBOARD_secure_1_title');
|
const header = translate('ONBOARD_SECURE_1_TITLE');
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<div>
|
<div>
|
||||||
<p>{translate('ONBOARD_secure_1_content__1')}</p>
|
<p>{translate('ONBOARD_SECURE_1_CONTENT__1')}</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>{translate('ONBOARD_secure_1_content__2')}</li>
|
<li>{translate('ONBOARD_SECURE_1_CONTENT__2')}</li>
|
||||||
<li>{translate('ONBOARD_secure_1_content__3')} </li>
|
<li>{translate('ONBOARD_SECURE_1_CONTENT__3')}</li>
|
||||||
<li>{translate('ONBOARD_secure_1_content__4')}</li>
|
<li>{translate('ONBOARD_SECURE_1_CONTENT__4')}</li>
|
||||||
<li>{translate('ONBOARD_secure_1_content__5')}</li>
|
<li>{translate('ONBOARD_SECURE_1_CONTENT__5')}</li>
|
||||||
<li>{translate('ONBOARD_secure_1_content__6')}</li>
|
<li>{translate('ONBOARD_SECURE_1_CONTENT__6')}</li>
|
||||||
<li>{translate('ONBOARD_secure_1_content__7')}</li>
|
<li>{translate('ONBOARD_SECURE_1_CONTENT__7')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,19 +8,19 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const SecureSlideThree: React.SFC<Props> = ({ site }) => {
|
const SecureSlideThree: React.SFC<Props> = ({ site }) => {
|
||||||
const header = translate('ONBOARD_secure_3_title');
|
const header = translate('ONBOARD_SECURE_3_TITLE');
|
||||||
const subheader = translate('ONBOARD_secure_3_content__1');
|
const subheader = translate('ONBOARD_SECURE_3_CONTENT__1');
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<div>
|
<div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>{translate('ONBOARD_secure_3_content__2')}</li>
|
<li>{translate('ONBOARD_SECURE_3_CONTENT__2')}</li>
|
||||||
<li>{translate('ONBOARD_secure_3_content__3')}</li>
|
<li>{translate('ONBOARD_SECURE_3_CONTENT__3')}</li>
|
||||||
<li>{translate('ONBOARD_secure_3_content__4')}</li>
|
<li>{translate('ONBOARD_SECURE_3_CONTENT__4')}</li>
|
||||||
<li>{translate('ONBOARD_secure_3_content__5')}</li>
|
<li>{translate('ONBOARD_SECURE_3_CONTENT__5')}</li>
|
||||||
{site === 'cx' && <li>{translate('CX_Warning_1')}</li>}
|
{site === 'cx' && <li>{translate('CX_WARNING_1')}</li>}
|
||||||
</ul>
|
</ul>
|
||||||
<h5 className="text-center">{translate('ONBOARD_secure_3_content__6')} </h5>
|
<h5 className="text-center">{translate('ONBOARD_SECURE_3_CONTENT__6')} </h5>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,15 @@ import OnboardSlide from './OnboardSlide';
|
||||||
import onboardIconEight from 'assets/images/onboarding/slide-08.svg';
|
import onboardIconEight from 'assets/images/onboarding/slide-08.svg';
|
||||||
|
|
||||||
const SecureSlideTwo = () => {
|
const SecureSlideTwo = () => {
|
||||||
const header = translate('ONBOARD_secure_2_title');
|
const header = translate('ONBOARD_SECURE_2_TITLE');
|
||||||
const subheader = translate('ONBOARD_secure_2_content__1');
|
const subheader = translate('ONBOARD_SECURE_2_CONTENT__1');
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<ul>
|
<ul>
|
||||||
<li>{translate('ONBOARD_secure_2_content__2')}</li>
|
<li>{translate('ONBOARD_SECURE_2_CONTENT__2')}</li>
|
||||||
<li>{translate('ONBOARD_secure_2_content__3')}</li>
|
<li>{translate('ONBOARD_SECURE_2_CONTENT__3')}</li>
|
||||||
<li>{translate('ONBOARD_secure_2_content__4')}</li>
|
<li>{translate('ONBOARD_SECURE_2_CONTENT__4')}</li>
|
||||||
<li>{translate('ONBOARD_secure_2_content__5')}</li>
|
<li>{translate('ONBOARD_SECURE_2_CONTENT__5')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ import onboardIconOne from 'assets/images/onboarding/slide-01.svg';
|
||||||
import './WelcomeSlide.scss';
|
import './WelcomeSlide.scss';
|
||||||
|
|
||||||
const WelcomeSlide = () => {
|
const WelcomeSlide = () => {
|
||||||
const header = translate('ONBOARD_welcome_title');
|
const header = translate('ONBOARD_WELCOME_TITLE');
|
||||||
const subheader = <small>{translate('ONBOARD_welcome_content__3')}</small>;
|
const subheader = <small>{translate('ONBOARD_WELCOME_CONTENT__3')}</small>;
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<div>
|
<div>
|
||||||
|
@ -16,21 +16,21 @@ const WelcomeSlide = () => {
|
||||||
<i className="fa fa-exclamation-triangle" />
|
<i className="fa fa-exclamation-triangle" />
|
||||||
</div>
|
</div>
|
||||||
<span>
|
<span>
|
||||||
{translate('ONBOARD_welcome_content__1')}
|
{translate('ONBOARD_WELCOME_CONTENT__1')}
|
||||||
{translate('ONBOARD_welcome_content__2')}
|
{translate('ONBOARD_WELCOME_CONTENT__2')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="WelcomeSlide-alert">
|
<div className="WelcomeSlide-alert">
|
||||||
<div className="WelcomeSlide-alert-icon">
|
<div className="WelcomeSlide-alert-icon">
|
||||||
<i className="fa fa-exclamation-triangle" />
|
<i className="fa fa-exclamation-triangle" />
|
||||||
</div>
|
</div>
|
||||||
<span>{translate('ONBOARD_welcome_content__8')}</span>
|
{translate('ONBOARD_WELCOME_CONTENT__8')}
|
||||||
</div>
|
</div>
|
||||||
<h5>{translate('ONBOARD_welcome_content__4')}</h5>
|
<h5>{translate('ONBOARD_WELCOME_CONTENT__4')}</h5>
|
||||||
<ul>
|
<ul>
|
||||||
<li>{translate('ONBOARD_welcome_content__5')}</li>
|
<li>{translate('ONBOARD_WELCOME_CONTENT__5')}</li>
|
||||||
<li>{translate('ONBOARD_welcome_content__6')}</li>
|
<li>{translate('ONBOARD_WELCOME_CONTENT__6')}</li>
|
||||||
<li>{translate('ONBOARD_welcome_content__7')}</li>
|
<li>{translate('ONBOARD_WELCOME_CONTENT__7')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,16 +4,16 @@ import OnboardSlide from './OnboardSlide';
|
||||||
import onboardIconSix from 'assets/images/onboarding/slide-06.svg';
|
import onboardIconSix from 'assets/images/onboarding/slide-06.svg';
|
||||||
|
|
||||||
const WhyMewSlide = () => {
|
const WhyMewSlide = () => {
|
||||||
const header = translate('ONBOARD_whymyc_title');
|
const header = translate('ONBOARD_WHYMYC_TITLE');
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<ul>
|
<ul>
|
||||||
<li>{translate('ONBOARD_whymyc_content__1')}</li>
|
<li>{translate('ONBOARD_WHYMYC_CONTENT__1')}</li>
|
||||||
<li>{translate('ONBOARD_whymyc_content__2')}</li>
|
<li>{translate('ONBOARD_WHYMYC_CONTENT__2')}</li>
|
||||||
<li>{translate('ONBOARD_whymyc_content__3')}</li>
|
<li>{translate('ONBOARD_WHYMYC_CONTENT__3')}</li>
|
||||||
<li>{translate('ONBOARD_whymyc_content__4')}</li>
|
<li>{translate('ONBOARD_WHYMYC_CONTENT__4')}</li>
|
||||||
<li>{translate('ONBOARD_whymyc_content__5')}</li>
|
<li>{translate('ONBOARD_WHYMYC_CONTENT__5')}</li>
|
||||||
<li>{translate('ONBOARD_whymyc_content__6')}</li>
|
<li>{translate('ONBOARD_WHYMYC_CONTENT__6')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
return <OnboardSlide header={header} content={content} image={onboardIconSix} imageSide="left" />;
|
return <OnboardSlide header={header} content={content} image={onboardIconSix} imageSide="left" />;
|
||||||
|
|
|
@ -4,23 +4,23 @@ import OnboardSlide from './OnboardSlide';
|
||||||
import onboardIconFive from 'assets/images/onboarding/slide-05.svg';
|
import onboardIconFive from 'assets/images/onboarding/slide-05.svg';
|
||||||
|
|
||||||
const WhySlide = () => {
|
const WhySlide = () => {
|
||||||
const header = translate('ONBOARD_why_title');
|
const header = translate('ONBOARD_WHY_TITLE');
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<div>
|
<div>
|
||||||
<h5>{translate('ONBOARD_why_content__1')}</h5>
|
<h5>{translate('ONBOARD_WHY_CONTENT__1')}</h5>
|
||||||
<ul>
|
<ul>
|
||||||
<li className="text-danger">{translate('ONBOARD_why_content__2')}</li>
|
<li className="text-danger">{translate('ONBOARD_WHY_CONTENT__2')}</li>
|
||||||
<li className="text-danger">{translate('ONBOARD_why_content__3')}</li>
|
<li className="text-danger">{translate('ONBOARD_WHY_CONTENT__3')}</li>
|
||||||
<li className="text-danger">{translate('ONBOARD_why_content__4')}</li>
|
<li className="text-danger">{translate('ONBOARD_WHY_CONTENT__4')}</li>
|
||||||
<li className="text-danger">{translate('ONBOARD_why_content__5')}</li>
|
<li className="text-danger">{translate('ONBOARD_WHY_CONTENT__5')}</li>
|
||||||
<li className="text-danger">{translate('ONBOARD_why_content__6')}</li>
|
<li className="text-danger">{translate('ONBOARD_WHY_CONTENT__6')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h5>{translate('ONBOARD_why_content__7')}</h5>
|
<h5>{translate('ONBOARD_WHY_CONTENT__7')}</h5>
|
||||||
<ul>
|
<ul>
|
||||||
<li>{translate('ONBOARD_why_content__8')}</li>
|
<li>{translate('ONBOARD_WHY_CONTENT__8')}</li>
|
||||||
<li>{translate('ONBOARD_why_content__9')}</li>
|
<li>{translate('ONBOARD_WHY_CONTENT__9')}</li>
|
||||||
<li>{translate('ONBOARD_why_content__10')}</li>
|
<li>{translate('ONBOARD_WHY_CONTENT__10')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -74,7 +74,7 @@ class OnboardModal extends React.Component<Props, State> {
|
||||||
isOpen: true
|
isOpen: true
|
||||||
});
|
});
|
||||||
|
|
||||||
const onboardResumeMessage = translate('ONBOARD_resume');
|
const onboardResumeMessage = translate('ONBOARD_RESUME');
|
||||||
|
|
||||||
// Wait a sec so it doesn't get lost in the page-load
|
// Wait a sec so it doesn't get lost in the page-load
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -91,25 +91,25 @@ class OnboardModal extends React.Component<Props, State> {
|
||||||
const firstButtons: IButton[] = [
|
const firstButtons: IButton[] = [
|
||||||
{
|
{
|
||||||
disabled: slideNumber === NUMBER_OF_SLIDES,
|
disabled: slideNumber === NUMBER_OF_SLIDES,
|
||||||
text: 'Next',
|
text: translate('ACTION_6'),
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
onClick: this.handleNextSlide
|
onClick: this.handleNextSlide
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
disabled: slideNumber === 1,
|
disabled: slideNumber === 1,
|
||||||
text: 'Back',
|
text: translate('ACTION_4'),
|
||||||
type: 'default',
|
type: 'default',
|
||||||
onClick: this.handlePreviousSlide
|
onClick: this.handlePreviousSlide
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
const lastButtons: IButton[] = [
|
const lastButtons: IButton[] = [
|
||||||
{
|
{
|
||||||
text: 'Finish',
|
text: translate('ACTION_10'),
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
onClick: this.closeModal
|
onClick: this.closeModal
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Back',
|
text: translate('ACTION_4'),
|
||||||
type: 'default',
|
type: 'default',
|
||||||
onClick: this.handlePreviousSlide
|
onClick: this.handlePreviousSlide
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import TabSection from 'containers/TabSection';
|
import TabSection from 'containers/TabSection';
|
||||||
import { translateRaw } from 'translations';
|
import translate from 'translations';
|
||||||
import {
|
import {
|
||||||
signLocalTransactionSucceeded,
|
signLocalTransactionSucceeded,
|
||||||
TSignLocalTransactionSucceeded,
|
TSignLocalTransactionSucceeded,
|
||||||
|
@ -49,14 +49,12 @@ class BroadcastTx extends Component<Props> {
|
||||||
path={currentPath}
|
path={currentPath}
|
||||||
render={() => (
|
render={() => (
|
||||||
<div className="BroadcastTx">
|
<div className="BroadcastTx">
|
||||||
<h1 className="BroadcastTx-title">Broadcast Signed Transaction</h1>
|
<h1 className="BroadcastTx-title">{translate('BROADCAST_TX_TITLE')}</h1>
|
||||||
<p className="BroadcastTx-help">
|
<p className="BroadcastTx-help">{translate('BROADCAST_TX_DESCRIPTION')}</p>
|
||||||
Paste a signed transaction and press the "SEND TRANSACTION" button.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="input-group-wrapper InteractForm-interface">
|
<div className="input-group-wrapper InteractForm-interface">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translateRaw('SEND_signed')}</div>
|
<div className="input-group-header">{translate('SEND_SIGNED')}</div>
|
||||||
<TextArea
|
<TextArea
|
||||||
className={stateTransaction ? '' : 'invalid'}
|
className={stateTransaction ? '' : 'invalid'}
|
||||||
rows={7}
|
rows={7}
|
||||||
|
|
|
@ -66,10 +66,10 @@ class TxHashInput extends React.Component<Props, State> {
|
||||||
value={hash}
|
value={hash}
|
||||||
onChange={this.handleSelectTx}
|
onChange={this.handleSelectTx}
|
||||||
options={selectOptions}
|
options={selectOptions}
|
||||||
placeholder="Select a recent transaction..."
|
placeholder={translate('SELECT_RECENT_TX')}
|
||||||
searchable={false}
|
searchable={false}
|
||||||
/>
|
/>
|
||||||
<em className="TxHashInput-recent-separator">or</em>
|
<em className="TxHashInput-recent-separator">{translate('OR')}</em>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -82,12 +82,12 @@ class TxHashInput extends React.Component<Props, State> {
|
||||||
|
|
||||||
{isValidETHAddress(hash) && (
|
{isValidETHAddress(hash) && (
|
||||||
<p className="TxHashInput-message help-block is-invalid">
|
<p className="TxHashInput-message help-block is-invalid">
|
||||||
You cannot use an address, you must use a transaction hash
|
{translate('SELECT_RECENT_TX_BY_TXHASH')}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<button className="TxHashInput-submit btn btn-primary btn-block">
|
<button className="TxHashInput-submit btn btn-primary btn-block">
|
||||||
{translate('NAV_CheckTxStatus')}
|
{translate('NAV_CHECKTXSTATUS')}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,12 +4,12 @@ import { RouteComponentProps } from 'react-router';
|
||||||
import TabSection from 'containers/TabSection';
|
import TabSection from 'containers/TabSection';
|
||||||
import TxHashInput from './components/TxHashInput';
|
import TxHashInput from './components/TxHashInput';
|
||||||
import { TransactionStatus as TransactionStatusComponent } from 'components';
|
import { TransactionStatus as TransactionStatusComponent } from 'components';
|
||||||
import { NewTabLink } from 'components/ui';
|
|
||||||
import { getNetworkConfig } from 'selectors/config';
|
import { getNetworkConfig } from 'selectors/config';
|
||||||
import { getParamFromURL } from 'utils/helpers';
|
import { getParamFromURL } from 'utils/helpers';
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
import { NetworkConfig } from 'types/network';
|
import { NetworkConfig } from 'types/network';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
interface StateProps {
|
interface StateProps {
|
||||||
network: NetworkConfig;
|
network: NetworkConfig;
|
||||||
|
@ -48,18 +48,14 @@ class CheckTransaction extends React.Component<Props, State> {
|
||||||
<TabSection>
|
<TabSection>
|
||||||
<div className="CheckTransaction Tab-content">
|
<div className="CheckTransaction Tab-content">
|
||||||
<section className="CheckTransaction-form Tab-content-pane">
|
<section className="CheckTransaction-form Tab-content-pane">
|
||||||
<h1 className="CheckTransaction-form-title">Check Transaction Status</h1>
|
<h1 className="CheckTransaction-form-title">{translate('CHECK_TX_STATUS_TITLE')}</h1>
|
||||||
<p className="CheckTransaction-form-desc">
|
<p className="CheckTransaction-form-desc">
|
||||||
Enter your Transaction Hash to check on its status.{' '}
|
{translate('CHECK_TX_STATUS_DESCRIPTION_1')}
|
||||||
{!network.isCustom && (
|
{!network.isCustom &&
|
||||||
<React.Fragment>
|
translate('CHECK_TX_STATUS_DESCRIPTION_2', {
|
||||||
If you don’t know your Transaction Hash, you can look it up on the{' '}
|
$block_explorer: network.blockExplorer.name,
|
||||||
<NewTabLink href={network.blockExplorer.origin}>
|
$block_explorer_link: network.blockExplorer.origin
|
||||||
{network.blockExplorer.name} explorer
|
})}
|
||||||
</NewTabLink>{' '}
|
|
||||||
by looking up your address.
|
|
||||||
</React.Fragment>
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
<TxHashInput hash={hash} onSubmit={this.handleHashSubmit} />
|
<TxHashInput hash={hash} onSubmit={this.handleHashSubmit} />
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -26,12 +26,12 @@ class DeployClass extends Component<DispatchProps> {
|
||||||
<main className="Deploy Tab-content-pane" role="main">
|
<main className="Deploy Tab-content-pane" role="main">
|
||||||
<button className="Deploy-field-reset btn btn-default btn-sm" onClick={this.changeWallet}>
|
<button className="Deploy-field-reset btn btn-default btn-sm" onClick={this.changeWallet}>
|
||||||
<i className="fa fa-refresh" />
|
<i className="fa fa-refresh" />
|
||||||
{translate('Change Wallet')}
|
{translate('CHANGE_WALLET')}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div className="input-group-wrapper Deploy-field">
|
<div className="input-group-wrapper Deploy-field">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translate('CONTRACT_ByteCode')}</div>
|
<div className="input-group-header">{translate('CONTRACT_BYTECODE')}</div>
|
||||||
<DataFieldFactory
|
<DataFieldFactory
|
||||||
withProps={({ data: { raw, value }, onChange, readOnly }) => (
|
withProps={({ data: { raw, value }, onChange, readOnly }) => (
|
||||||
<TextArea
|
<TextArea
|
||||||
|
@ -76,7 +76,7 @@ class DeployClass extends Component<DispatchProps> {
|
||||||
Modal={ConfirmationModal}
|
Modal={ConfirmationModal}
|
||||||
withProps={({ onClick }) => (
|
withProps={({ onClick }) => (
|
||||||
<button className="Deploy-submit btn btn-primary" onClick={onClick}>
|
<button className="Deploy-submit btn btn-primary" onClick={onClick}>
|
||||||
{translate('NAV_DeployContract')}
|
{translate('NAV_DEPLOYCONTRACT')}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -78,7 +78,7 @@ class InteractExplorerClass extends Component<Props, State> {
|
||||||
className="InteractExplorer-func-submit btn btn-primary"
|
className="InteractExplorer-func-submit btn btn-primary"
|
||||||
onClick={this.handleFunctionSend}
|
onClick={this.handleFunctionSend}
|
||||||
>
|
>
|
||||||
{translate('CONTRACT_Write')}
|
{translate('CONTRACT_WRITE')}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -87,14 +87,14 @@ class InteractExplorerClass extends Component<Props, State> {
|
||||||
<div className="input-group-wrapper">
|
<div className="input-group-wrapper">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">
|
<div className="input-group-header">
|
||||||
{translate('CONTRACT_Interact_Title')}
|
{translate('CONTRACT_INTERACT_TITLE')}
|
||||||
<div className="flex-spacer" />
|
<div className="flex-spacer" />
|
||||||
<span className="small">{to.raw}</span>
|
<span className="small">{to.raw}</span>
|
||||||
</div>
|
</div>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
name="exploreContract"
|
name="exploreContract"
|
||||||
value={selectedFunction as any}
|
value={selectedFunction as any}
|
||||||
placeholder="Please select a function..."
|
placeholder={translate('SELECT_A_THING', { $thing: 'function' })}
|
||||||
onChange={this.handleFunctionSelect}
|
onChange={this.handleFunctionSelect}
|
||||||
options={contractFunctionsOptions}
|
options={contractFunctionsOptions}
|
||||||
clearable={false}
|
clearable={false}
|
||||||
|
@ -147,7 +147,7 @@ class InteractExplorerClass extends Component<Props, State> {
|
||||||
className="InteractExplorer-func-submit btn btn-primary"
|
className="InteractExplorer-func-submit btn btn-primary"
|
||||||
onClick={this.handleFunctionCall}
|
onClick={this.handleFunctionCall}
|
||||||
>
|
>
|
||||||
{translate('CONTRACT_Read')}
|
{translate('CONTRACT_READ')}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import translate from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import { getNetworkContracts } from 'selectors/config';
|
import { getNetworkContracts } from 'selectors/config';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
|
@ -52,8 +52,8 @@ class InteractForm extends Component<Props, State> {
|
||||||
abiJson: '',
|
abiJson: '',
|
||||||
contract: null,
|
contract: null,
|
||||||
contractPlaceholder: this.isContractsValid()
|
contractPlaceholder: this.isContractsValid()
|
||||||
? 'Please select a contract...'
|
? translateRaw('SELECT_A_THING', { $thing: 'contract' })
|
||||||
: 'No contracts available'
|
: translateRaw('NO_CONTRACTS_AVAILABLE')
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ class InteractForm extends Component<Props, State> {
|
||||||
<div className="InteractForm-address row">
|
<div className="InteractForm-address row">
|
||||||
<div className="input-group-wrapper InteractForm-address-field col-sm-6">
|
<div className="input-group-wrapper InteractForm-address-field col-sm-6">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translate('CONTRACT_Title')}</div>
|
<div className="input-group-header">{translate('CONTRACT_TITLE')}</div>
|
||||||
<Input
|
<Input
|
||||||
placeholder={`ensdomain.eth or ${donationAddressMap.ETH}`}
|
placeholder={`ensdomain.eth or ${donationAddressMap.ETH}`}
|
||||||
name="contract_address"
|
name="contract_address"
|
||||||
|
@ -102,7 +102,7 @@ class InteractForm extends Component<Props, State> {
|
||||||
|
|
||||||
<div className="input-group-wrapper InteractForm-address-field col-sm-6">
|
<div className="input-group-wrapper InteractForm-address-field col-sm-6">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translate('CONTRACT_Title_2')}</div>
|
<div className="input-group-header">{translate('CONTRACT_TITLE_2')}</div>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
className={`${!contract ? 'invalid' : ''}`}
|
className={`${!contract ? 'invalid' : ''}`}
|
||||||
value={contract as any}
|
value={contract as any}
|
||||||
|
@ -118,7 +118,7 @@ class InteractForm extends Component<Props, State> {
|
||||||
|
|
||||||
<div className="input-group-wrapper InteractForm-interface">
|
<div className="input-group-wrapper InteractForm-interface">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translate('CONTRACT_Json')}</div>
|
<div className="input-group-header">{translate('CONTRACT_JSON')}</div>
|
||||||
<TextArea
|
<TextArea
|
||||||
placeholder={this.abiJsonPlaceholder}
|
placeholder={this.abiJsonPlaceholder}
|
||||||
className={`InteractForm-interface-field-input ${validAbiJson ? '' : 'invalid'}`}
|
className={`InteractForm-interface-field-input ${validAbiJson ? '' : 'invalid'}`}
|
||||||
|
@ -134,7 +134,7 @@ class InteractForm extends Component<Props, State> {
|
||||||
disabled={!showContractAccessButton}
|
disabled={!showContractAccessButton}
|
||||||
onClick={accessContract(abiJson, address)}
|
onClick={accessContract(abiJson, address)}
|
||||||
>
|
>
|
||||||
{translate('x_Access')}
|
{translate('X_ACCESS')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -18,11 +18,11 @@ interface Props {
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
path: 'interact',
|
path: 'interact',
|
||||||
name: translate('Interact')
|
name: translate('CONTRACTS_INTERACT')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'deploy',
|
path: 'deploy',
|
||||||
name: translate('Deploy')
|
name: translate('CONTRACTS_DEPLOY')
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { resolveDomainRequested, TResolveDomainRequested } from 'actions/ens';
|
||||||
import { isValidENSName } from 'libs/validators';
|
import { isValidENSName } from 'libs/validators';
|
||||||
import './NameInput.scss';
|
import './NameInput.scss';
|
||||||
import { Input } from 'components/ui';
|
import { Input } from 'components/ui';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
domainToCheck: string;
|
domainToCheck: string;
|
||||||
|
@ -26,7 +27,7 @@ class NameInput extends Component<Props, State> {
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const { domainRequests } = this.props;
|
const { domainRequests } = this.props;
|
||||||
const { isValidDomain, domainToCheck, isFocused } = this.state;
|
const { isValidDomain, domainToCheck } = this.state;
|
||||||
const req = domainRequests[domainToCheck];
|
const req = domainRequests[domainToCheck];
|
||||||
const isLoading = req && !req.data && !req.error;
|
const isLoading = req && !req.data && !req.error;
|
||||||
|
|
||||||
|
@ -48,19 +49,16 @@ class NameInput extends Component<Props, State> {
|
||||||
/>
|
/>
|
||||||
<span className="input-group-addon">.eth</span>
|
<span className="input-group-addon">.eth</span>
|
||||||
</label>
|
</label>
|
||||||
|
{domainToCheck &&
|
||||||
|
!isValidDomain && (
|
||||||
|
<p className="help-block is-invalid">{translate('ENS_INVALID_INPUT')}</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{domainToCheck &&
|
|
||||||
!isValidDomain &&
|
|
||||||
!isFocused && (
|
|
||||||
<p className="help-block is-invalid">
|
|
||||||
Must be at least 7 characters, no special characters
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
<button
|
<button
|
||||||
className="ENSInput-button btn btn-primary btn-block"
|
className="ENSInput-button btn btn-primary btn-block"
|
||||||
disabled={!isValidDomain || isLoading}
|
disabled={!isValidDomain || isLoading}
|
||||||
>
|
>
|
||||||
Check Availability
|
{translate('ACTION_9')}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import ENSTime from './components/ENSTime';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { NewTabLink } from 'components/ui';
|
import { NewTabLink } from 'components/ui';
|
||||||
import { ensV3Url } from 'utils/formatters';
|
import { ensV3Url } from 'utils/formatters';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
const getDeadlines = (registrationDate: string) => {
|
const getDeadlines = (registrationDate: string) => {
|
||||||
// Get the time to reveal bids, and the time when the action closes
|
// Get the time to reveal bids, and the time when the action closes
|
||||||
|
@ -20,9 +21,7 @@ export const NameAuction: React.SFC<IBaseDomainRequest> = props => {
|
||||||
<section className="row">
|
<section className="row">
|
||||||
<div className="auction-info text-center">
|
<div className="auction-info text-center">
|
||||||
<div className="ens-title">
|
<div className="ens-title">
|
||||||
<h1>
|
<h1>{translate('ENS_DOMAIN_AUCTION', { $name: name + '.eth' })}</h1>
|
||||||
An auction has started for <strong>{name}.eth</strong>
|
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="ens-panel-wrapper">
|
<div className="ens-panel-wrapper">
|
||||||
|
@ -35,11 +34,9 @@ export const NameAuction: React.SFC<IBaseDomainRequest> = props => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Do you want to place a bid on {name}.eth?{' '}
|
{translate('NAME_AUCTION_PROMPT_BID')}
|
||||||
<strong>
|
<strong>
|
||||||
<NewTabLink href={ensV3Url(name)}>
|
<NewTabLink href={ensV3Url(name)}>{translate('NAME_AUCTION_PROMPT_BID_2')}</NewTabLink>
|
||||||
You can do that on MyCrypto V3 by clicking here!
|
|
||||||
</NewTabLink>
|
|
||||||
</strong>
|
</strong>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { IBaseDomainRequest } from 'libs/ens';
|
import { IBaseDomainRequest } from 'libs/ens';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
export const NameForbidden: React.SFC<IBaseDomainRequest> = props => (
|
export const NameForbidden: React.SFC<IBaseDomainRequest> = props => (
|
||||||
<h1>{props.name}.eth is forbidden</h1>
|
<h1>{translate('ENS_DOMAIN_FORBIDDEN', { $name: props.name + '.eth' })}</h1>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,21 +2,19 @@ import React from 'react';
|
||||||
import { IBaseDomainRequest } from 'libs/ens';
|
import { IBaseDomainRequest } from 'libs/ens';
|
||||||
import { NewTabLink } from 'components/ui';
|
import { NewTabLink } from 'components/ui';
|
||||||
import { ensV3Url } from 'utils/formatters';
|
import { ensV3Url } from 'utils/formatters';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
export const NameOpen: React.SFC<IBaseDomainRequest> = props => (
|
export const NameOpen: React.SFC<IBaseDomainRequest> = props => (
|
||||||
<section className="row">
|
<section className="row">
|
||||||
<section className="auction-info text-center">
|
<section className="auction-info text-center">
|
||||||
<div className="ens-title">
|
<div className="ens-title">
|
||||||
<h1>
|
<h1>{translate('ENS_DOMAIN_OPEN', { $name: props.name + '.eth' })}</h1>
|
||||||
<strong>{props.name}.eth</strong> is available
|
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Do you want {props.name}.eth?{' '}
|
{translate('OPEN_AUCTION_PROMPT_1', { $name: props.name })}
|
||||||
<strong>
|
<strong>
|
||||||
<NewTabLink className="text-center" href={ensV3Url(props.name)}>
|
<NewTabLink className="text-center" href={ensV3Url(props.name)}>
|
||||||
Open an auction on MyCrypto v3!
|
{translate('OPEN_AUCTION_PROMPT_2')}
|
||||||
</NewTabLink>
|
</NewTabLink>
|
||||||
</strong>
|
</strong>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { IOwnedDomainRequest } from 'libs/ens';
|
import { IOwnedDomainRequest } from 'libs/ens';
|
||||||
import { NewTabLink, Address } from 'components/ui';
|
import { NewTabLink, Address } from 'components/ui';
|
||||||
|
import translate from 'translations';
|
||||||
const lookupLink = (name: string) => `https://etherscan.io/enslookup?q=${name}`;
|
const lookupLink = (name: string) => `https://etherscan.io/enslookup?q=${name}`;
|
||||||
|
|
||||||
type ChildrenProps = any;
|
type ChildrenProps = any;
|
||||||
|
@ -17,41 +18,39 @@ export const NameOwned: React.SFC<IOwnedDomainRequest> = ({
|
||||||
}) => (
|
}) => (
|
||||||
<section>
|
<section>
|
||||||
<div className="ens-title">
|
<div className="ens-title">
|
||||||
<h1 className="text-center">
|
<h1 className="text-center">{translate('ENS_DOMAIN_OWNED', { $name: name + '.eth' })}</h1>
|
||||||
<strong>{name}.eth</strong> is already owned
|
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="ens-table-wrapper">
|
<div className="ens-table-wrapper">
|
||||||
<table className="table table-striped">
|
<table className="table table-striped">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Name: </td>
|
<td>{translate('NAME_OWNED_NAME')}:</td>
|
||||||
<MonoTd>
|
<MonoTd>
|
||||||
<NewTabLink content={`${name}.eth`} href={lookupLink(`${name}.eth`)} />
|
<NewTabLink content={`${name}.eth`} href={lookupLink(`${name}.eth`)} />
|
||||||
</MonoTd>
|
</MonoTd>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Labelhash ({name}): </td>
|
<td>{translate('NAME_OWNED_LABELHASH', { name })}:</td>
|
||||||
<MonoTd>{labelHash}</MonoTd>
|
<MonoTd>{labelHash}</MonoTd>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Namehash ({name}.eth): </td>
|
<td>{translate('NAME_OWNED_NAMEHASH', { name })} </td>
|
||||||
<MonoTd>{nameHash}</MonoTd>
|
<MonoTd>{nameHash}</MonoTd>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Owner:</td>
|
<td>{translate('NAME_OWNED_OWNER')}:</td>
|
||||||
<MonoTd>
|
<MonoTd>
|
||||||
<Address address={ownerAddress} />
|
<Address address={ownerAddress} />
|
||||||
</MonoTd>
|
</MonoTd>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Highest Bidder (Deed Owner): </td>
|
<td>{translate('NAME_OWNED_HIGHEST_BIDDER')}</td>
|
||||||
<MonoTd>
|
<MonoTd>
|
||||||
<span>{highestBid}</span>
|
<span>{highestBid}</span>
|
||||||
</MonoTd>
|
</MonoTd>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Resolved Address: </td>
|
<td>{translate('NAME_OWNED_RESOLVED_ADDR')}:</td>
|
||||||
<MonoTd>
|
<MonoTd>
|
||||||
<Address address={resolvedAddress} />
|
<Address address={resolvedAddress} />
|
||||||
</MonoTd>
|
</MonoTd>
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { IRevealDomainRequest } from 'libs/ens';
|
import { IRevealDomainRequest } from 'libs/ens';
|
||||||
import ENSTime from './components/ENSTime';
|
import ENSTime from './components/ENSTime';
|
||||||
import { UnitDisplay, NewTabLink } from 'components/ui';
|
import { UnitDisplay } from 'components/ui';
|
||||||
import { Wei } from 'libs/units';
|
import { Wei } from 'libs/units';
|
||||||
import { ensV3Url } from 'utils/formatters';
|
import { ensV3Url } from 'utils/formatters';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
export const NameReveal: React.SFC<IRevealDomainRequest> = props => (
|
export const NameReveal: React.SFC<IRevealDomainRequest> = props => (
|
||||||
<section className="row text-center">
|
<section className="row text-center">
|
||||||
<div className="auction-info text-center">
|
<div className="auction-info text-center">
|
||||||
<div className="ens-title">
|
<div className="ens-title">
|
||||||
<h2>
|
<h2>
|
||||||
It's time to reveal the bids for <strong>{props.name}.eth</strong>
|
{translate('ENS_DOMAIN_REVEAL', { $name: props.name + '.eth' })}
|
||||||
<br />
|
<br />
|
||||||
The current highest bid is{' '}
|
{translate('ENS_DOMAIN_HIGHEST_BID')}
|
||||||
<strong>
|
<strong>
|
||||||
<UnitDisplay
|
<UnitDisplay
|
||||||
value={Wei(props.highestBid)}
|
value={Wei(props.highestBid)}
|
||||||
|
@ -33,12 +34,10 @@ export const NameReveal: React.SFC<IRevealDomainRequest> = props => (
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Did you bid on {props.name}.eth? You must reveal your bid now.{' '}
|
{translate('ENS_DOMAIN_PROMPT_REVEAL', {
|
||||||
<strong>
|
$name: props.name + '.eth',
|
||||||
<NewTabLink href={ensV3Url(props.name)}>
|
$link: ensV3Url(props.name)
|
||||||
You can do that on MyCrypto v3 by clicking here!
|
})}
|
||||||
</NewTabLink>
|
|
||||||
</strong>
|
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,16 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { NameInput, NameResolve } from './components';
|
import { NameInput, NameResolve } from './components';
|
||||||
import TabSection from 'containers/TabSection';
|
import TabSection from 'containers/TabSection';
|
||||||
import { NewTabLink } from 'components/ui';
|
|
||||||
import { donationAddressMap } from 'config';
|
import { donationAddressMap } from 'config';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
import translate from 'translations';
|
||||||
const ENSDocsLink = () => (
|
|
||||||
<NewTabLink
|
|
||||||
href="https://ens.readthedocs.io/en/latest/introduction.html"
|
|
||||||
content="Ethereum Name Service"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default class ENSClass extends React.Component<{}> {
|
export default class ENSClass extends React.Component<{}> {
|
||||||
public render() {
|
public render() {
|
||||||
|
@ -21,16 +14,14 @@ export default class ENSClass extends React.Component<{}> {
|
||||||
<div className="ENS">
|
<div className="ENS">
|
||||||
<h1 className="ENS-title">Ethereum Name Service</h1>
|
<h1 className="ENS-title">Ethereum Name Service</h1>
|
||||||
<p className="ENS-description">
|
<p className="ENS-description">
|
||||||
The <ENSDocsLink /> is a distributed, open, and extensible naming system based on
|
{translate('ENS_DESCRIPTION', {
|
||||||
the Ethereum blockchain. Once you have a name, you can tell your friends to send ETH
|
$ens_docs: 'https://ens.readthedocs.io/en/latest/introduction.html',
|
||||||
to <code>ensdomain.eth</code> instead of
|
$example_donation_addr: donationAddressMap.ETH.substr(0, 8)
|
||||||
<code>{donationAddressMap.ETH.substr(0, 12)}...</code>
|
})}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<NameInput />
|
<NameInput />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<NameResolve />
|
<NameResolve />
|
||||||
</div>
|
</div>
|
||||||
</TabSection>
|
</TabSection>
|
||||||
|
|
|
@ -17,45 +17,42 @@ interface Props {
|
||||||
const FinalSteps: React.SFC<Props> = ({ walletType }) => {
|
const FinalSteps: React.SFC<Props> = ({ walletType }) => {
|
||||||
const steps = [
|
const steps = [
|
||||||
{
|
{
|
||||||
name: 'Open MyCrypto',
|
name: translate('MNEMONIC_FINAL_STEP_1'),
|
||||||
image: SiteImage
|
image: SiteImage
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Go to the account tab',
|
name: translate('MNEMONIC_FINAL_STEP_2'),
|
||||||
image: TabImage
|
image: TabImage
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
if (walletType === WalletType.Keystore) {
|
if (walletType === WalletType.Keystore) {
|
||||||
steps.push({
|
steps.push({
|
||||||
name: 'Select your wallet type',
|
name: translate('MNEMONIC_FINAL_STEP_3'),
|
||||||
image: SelectKeystoreImage
|
image: SelectKeystoreImage
|
||||||
});
|
});
|
||||||
steps.push({
|
steps.push({
|
||||||
name: 'Provide file & password',
|
name: translate('MNEMONIC_FINAL_STEP_5'),
|
||||||
image: ProvideKeystoreImage
|
image: ProvideKeystoreImage
|
||||||
});
|
});
|
||||||
} else if (walletType === WalletType.Mnemonic) {
|
} else if (walletType === WalletType.Mnemonic) {
|
||||||
steps.push({
|
steps.push({
|
||||||
name: 'Select your wallet type',
|
name: translate('MNEMONIC_FINAL_STEP_3'),
|
||||||
image: SelectMnemonicImage
|
image: SelectMnemonicImage
|
||||||
});
|
});
|
||||||
steps.push({
|
steps.push({
|
||||||
name: 'Enter your phrase',
|
name: translate('MNEMONIC_FINAL_STEP_4'),
|
||||||
image: ProvideMnemonicImage
|
image: ProvideMnemonicImage
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="FinalSteps">
|
<div className="FinalSteps">
|
||||||
<h1 className="FinalSteps-title">{translate('ADD_Label_6')}</h1>
|
<h1 className="FinalSteps-title">{translate('ADD_LABEL_6')}</h1>
|
||||||
<p className="FinalSteps-help">
|
<p className="FinalSteps-help">{translate('MNEMONIC_FINAL_DESCRIPTION')}</p>
|
||||||
All done, you’re now ready to access your wallet. Just follow these 4 steps whenever you
|
|
||||||
want to access your wallet.
|
|
||||||
</p>
|
|
||||||
<div className="FinalSteps-steps row">
|
<div className="FinalSteps-steps row">
|
||||||
{steps.map((step, index) => (
|
{steps.map((step, index) => (
|
||||||
<div key={step.name} className="StepBox col-lg-3 col-sm-6 col-xs-12">
|
<div key={index} className="StepBox col-lg-3 col-sm-6 col-xs-12">
|
||||||
<h4 className="StepBox-title">{step.name}</h4>
|
<h4 className="StepBox-title">{step.name}</h4>
|
||||||
<div className="StepBox-screen">
|
<div className="StepBox-screen">
|
||||||
<img className="StepBox-screen-img" src={step.image} />
|
<img className="StepBox-screen-img" src={step.image} />
|
||||||
|
@ -66,7 +63,7 @@ const FinalSteps: React.SFC<Props> = ({ walletType }) => {
|
||||||
</div>
|
</div>
|
||||||
<div className="FinalSteps-buttons">
|
<div className="FinalSteps-buttons">
|
||||||
<Link to="/account" className="FinalSteps-buttons-btn btn btn-primary btn-lg">
|
<Link to="/account" className="FinalSteps-buttons-btn btn btn-primary btn-lg">
|
||||||
Go to Account
|
{translate('GO_TO_ACCOUNT')}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { IV3Wallet } from 'ethereumjs-wallet';
|
import { IV3Wallet } from 'ethereumjs-wallet';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import translate from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import { makeBlob } from 'utils/blob';
|
import { makeBlob } from 'utils/blob';
|
||||||
import './DownloadWallet.scss';
|
import './DownloadWallet.scss';
|
||||||
import Template from '../Template';
|
import Template from '../Template';
|
||||||
|
@ -27,32 +27,24 @@ export default class DownloadWallet extends Component<Props, State> {
|
||||||
return (
|
return (
|
||||||
<Template>
|
<Template>
|
||||||
<div className="DlWallet">
|
<div className="DlWallet">
|
||||||
<h1 className="DlWallet-title">{translate('GEN_Label_2')}</h1>
|
<h1 className="DlWallet-title">{translate('GEN_LABEL_2')}</h1>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
role="button"
|
role="button"
|
||||||
className="DlWallet-download btn btn-primary btn-lg"
|
className="DlWallet-download btn btn-primary btn-lg"
|
||||||
aria-label="Download Keystore File (UTC / JSON · Recommended · Encrypted)"
|
aria-label="Download Keystore File (UTC / JSON · Recommended · Encrypted)"
|
||||||
aria-describedby={translate('x_KeystoreDesc', true)}
|
aria-describedby={translateRaw('X_KEYSTOREDESC')}
|
||||||
download={filename}
|
download={filename}
|
||||||
href={this.getBlob()}
|
href={this.getBlob()}
|
||||||
onClick={this.handleDownloadKeystore}
|
onClick={this.handleDownloadKeystore}
|
||||||
>
|
>
|
||||||
{translate('x_Download')} {translate('x_Keystore2')}
|
{translate('ACTION_13', { $thing: translateRaw('X_KEYSTORE2') })}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div className="DlWallet-warning">
|
<div className="DlWallet-warning">
|
||||||
<p>
|
<p>{translate('DL_WALLET_WARNING_1')}</p>
|
||||||
<strong>Do not lose it!</strong> It cannot be recovered if you lose it.
|
<p>{translate('DL_WALLET_WARNING_2')}</p>
|
||||||
</p>
|
<p>{translate('DL_WALLET_WARNING_3')}</p>
|
||||||
<p>
|
|
||||||
<strong>Do not share it!</strong> Your funds will be stolen if you use this file on a
|
|
||||||
malicious/phishing site.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>Make a backup!</strong> Secure it like the millions of dollars it may one day
|
|
||||||
be worth.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
@ -61,7 +53,7 @@ export default class DownloadWallet extends Component<Props, State> {
|
||||||
onClick={this.handleContinue}
|
onClick={this.handleContinue}
|
||||||
disabled={!hasDownloadedWallet}
|
disabled={!hasDownloadedWallet}
|
||||||
>
|
>
|
||||||
I understand. Continue.
|
{translate('ACTION_14')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Template>
|
</Template>
|
||||||
|
|
|
@ -33,21 +33,22 @@ export default class EnterPassword extends Component<Props, State> {
|
||||||
const isPasswordValid = passwordValidity === 'valid';
|
const isPasswordValid = passwordValidity === 'valid';
|
||||||
const isConfirmValid = confirmedPassword ? password === confirmedPassword : undefined;
|
const isConfirmValid = confirmedPassword ? password === confirmedPassword : undefined;
|
||||||
const canSubmit = isPasswordValid && isConfirmValid && !isGenerating;
|
const canSubmit = isPasswordValid && isConfirmValid && !isGenerating;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template>
|
<Template>
|
||||||
<form className="EnterPw" onSubmit={canSubmit ? this.handleSubmit : undefined}>
|
<form className="EnterPw" onSubmit={canSubmit ? this.handleSubmit : undefined}>
|
||||||
<h1 className="EnterPw-title" aria-live="polite">
|
<h1 className="EnterPw-title" aria-live="polite">
|
||||||
Generate a {translate('x_Keystore2')}
|
{translate('GENERATE_KEYSTORE_TITLE')}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div className="input-group-wrapper EnterPw-password">
|
<div className="input-group-wrapper EnterPw-password">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translate('GEN_Label_1')}</div>
|
<div className="input-group-header">{translate('INPUT_PASSWORD_LABEL')}</div>
|
||||||
<TogglablePassword
|
<TogglablePassword
|
||||||
className={!isPasswordValid && password.length > 0 ? 'invalid' : ''}
|
isValid={isPasswordValid && password.length > 0}
|
||||||
value={password}
|
value={password}
|
||||||
placeholder={`Password must be uncommon and ${MINIMUM_PASSWORD_LENGTH}+ characters long`}
|
placeholder={translateRaw('INPUT_PASSWORD_PLACEHOLDER', {
|
||||||
|
$pass_length: MINIMUM_PASSWORD_LENGTH.toString()
|
||||||
|
})}
|
||||||
onChange={this.onPasswordChange}
|
onChange={this.onPasswordChange}
|
||||||
onBlur={this.showFeedback}
|
onBlur={this.showFeedback}
|
||||||
/>
|
/>
|
||||||
|
@ -62,21 +63,21 @@ export default class EnterPassword extends Component<Props, State> {
|
||||||
|
|
||||||
<div className="input-group-wrapper EnterPw-password">
|
<div className="input-group-wrapper EnterPw-password">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">Confirm password</div>
|
<div className="input-group-header">{translate('INPUT_CONFIRM_PASSWORD_LABEL')}</div>
|
||||||
<TogglablePassword
|
<TogglablePassword
|
||||||
className={!isConfirmValid && password.length > 0 ? 'invalid' : ''}
|
isValid={isConfirmValid && password.length > 0}
|
||||||
value={confirmedPassword}
|
value={confirmedPassword}
|
||||||
placeholder={translateRaw('GEN_Placeholder_1')}
|
placeholder={translateRaw('GEN_PLACEHOLDER_1')}
|
||||||
onChange={this.onConfirmChange}
|
onChange={this.onConfirmChange}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button disabled={!canSubmit} className="EnterPw-submit btn btn-primary btn-lg btn-block">
|
<button disabled={!canSubmit} className="EnterPw-submit btn btn-primary btn-lg btn-block">
|
||||||
{isGenerating ? <Spinner light={true} /> : translate('NAV_GenerateWallet')}
|
{isGenerating ? <Spinner light={true} /> : translate('NAV_GENERATEWALLET')}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<p className="EnterPw-warning">{translate('x_PasswordDesc')}</p>
|
<p className="EnterPw-warning">{translate('X_PASSWORDDESC')}</p>
|
||||||
</form>
|
</form>
|
||||||
</Template>
|
</Template>
|
||||||
);
|
);
|
||||||
|
@ -101,18 +102,20 @@ export default class EnterPassword extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getFeedback() {
|
private getFeedback() {
|
||||||
let feedback = '';
|
let feedback: string = '';
|
||||||
const validity = this.getPasswordValidity();
|
const validity = this.getPasswordValidity();
|
||||||
|
|
||||||
if (validity !== 'valid') {
|
if (validity !== 'valid') {
|
||||||
const { password, passwordValidation } = this.state;
|
const { password, passwordValidation } = this.state;
|
||||||
|
|
||||||
if (password.length < MINIMUM_PASSWORD_LENGTH) {
|
if (password.length < MINIMUM_PASSWORD_LENGTH) {
|
||||||
feedback = `Password must be ${MINIMUM_PASSWORD_LENGTH}+ characters`;
|
feedback = translateRaw('INPUT_PASSWORD_PLACEHOLDER', {
|
||||||
|
$pass_length: MINIMUM_PASSWORD_LENGTH.toString()
|
||||||
|
});
|
||||||
} else if (passwordValidation && passwordValidation.feedback) {
|
} else if (passwordValidation && passwordValidation.feedback) {
|
||||||
feedback = `This password is not strong enough. ${passwordValidation.feedback.warning}.`;
|
feedback = translateRaw('WEAK_PASSWORD') + ' ' + passwordValidation.feedback.warning;
|
||||||
} else {
|
} else {
|
||||||
feedback = 'There is something invalid about your password. Please try another.';
|
feedback = translateRaw('INVALID_PASSWORD');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,10 @@ const PaperWallet: React.SFC<Props> = props => (
|
||||||
<div className="GenPaper">
|
<div className="GenPaper">
|
||||||
{/* Private Key */}
|
{/* Private Key */}
|
||||||
<label className="input-group GenPaper-private">
|
<label className="input-group GenPaper-private">
|
||||||
{/* translateRaw isn't used here because it wont properly render the ` characters as a string of code in markdown*/}
|
<h1 className="GenPaper-title">{translate('GEN_LABEL_5')}</h1>
|
||||||
<h1 className="input-group-header">{translate('GEN_Label_5')}</h1>
|
|
||||||
<Input
|
<Input
|
||||||
value={stripHexPrefix(props.privateKey)}
|
value={stripHexPrefix(props.privateKey)}
|
||||||
aria-label={translateRaw('x_PrivKey')}
|
aria-label={translateRaw('X_PRIVKEY')}
|
||||||
aria-describedby="x_PrivKeyDesc"
|
aria-describedby="x_PrivKeyDesc"
|
||||||
type="text"
|
type="text"
|
||||||
readOnly={true}
|
readOnly={true}
|
||||||
|
@ -30,29 +29,21 @@ const PaperWallet: React.SFC<Props> = props => (
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
{/* Download Paper Wallet */}
|
{/* Download Paper Wallet */}
|
||||||
<h2 className="GenPaper-title">{translate('x_Print')}</h2>
|
<h2 className="GenPaper-title">{translate('X_PRINT')}</h2>
|
||||||
<div className="GenPaper-paper">
|
<div className="GenPaper-paper">
|
||||||
<PrintableWallet address={props.keystore.address} privateKey={props.privateKey} />
|
<PrintableWallet address={props.keystore.address} privateKey={props.privateKey} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Warning */}
|
{/* Warning */}
|
||||||
<div className="GenPaper-warning">
|
<div className="GenPaper-warning">
|
||||||
<p>
|
<p>{translate('DL_WALLET_WARNING_1')}</p>
|
||||||
<strong>Do not lose it!</strong> It cannot be recovered if you lose it.
|
<p>{translate('DL_WALLET_WARNING_2')}</p>
|
||||||
</p>
|
<p>{translate('DL_WALLET_WARNING_3')}</p>
|
||||||
<p>
|
|
||||||
<strong>Do not share it!</strong> Your funds will be stolen if you use this file on a
|
|
||||||
malicious/phishing site.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>Make a backup!</strong> Secure it like the millions of dollars it may one day be
|
|
||||||
worth.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Continue button */}
|
{/* Continue button */}
|
||||||
<button className="GenPaper-continue btn btn-default" onClick={props.continue}>
|
<button className="GenPaper-continue btn btn-default" onClick={props.continue}>
|
||||||
{translate('NAV_ViewWallet')} →
|
{translate('NAV_VIEWWALLET')} →
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Template>
|
</Template>
|
||||||
|
|
|
@ -51,19 +51,12 @@ export default class GenerateMnemonic extends React.Component<{}, State> {
|
||||||
|
|
||||||
content = (
|
content = (
|
||||||
<div className="GenerateMnemonic">
|
<div className="GenerateMnemonic">
|
||||||
<h1 className="GenerateMnemonic-title">Generate a {translate('x_Mnemonic')}</h1>
|
<h1 className="GenerateMnemonic-title">{translate('GENERATE_MNEMONIC_TITLE')}</h1>
|
||||||
|
|
||||||
<p className="GenerateMnemonic-help">
|
<p className="GenerateMnemonic-help">
|
||||||
{isConfirming
|
{isConfirming
|
||||||
? `
|
? translate('MNEMONIC_DESCRIPTOION_1')
|
||||||
Re-enter your phrase to confirm you copied it correctly. If you
|
: translate('MNEMONIC_DESCRIPTOION_2')}
|
||||||
forgot one of your words, just click the button beside the input
|
|
||||||
to reveal it.
|
|
||||||
`
|
|
||||||
: `
|
|
||||||
Write these words down. Do not copy them to your clipboard, or save
|
|
||||||
them anywhere online.
|
|
||||||
`}
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="GenerateMnemonic-words">
|
<div className="GenerateMnemonic-words">
|
||||||
|
@ -80,7 +73,7 @@ export default class GenerateMnemonic extends React.Component<{}, State> {
|
||||||
className="GenerateMnemonic-buttons-btn btn btn-default"
|
className="GenerateMnemonic-buttons-btn btn btn-default"
|
||||||
onClick={this.regenerateWordArray}
|
onClick={this.regenerateWordArray}
|
||||||
>
|
>
|
||||||
<i className="fa fa-refresh" /> Regenerate Phrase
|
<i className="fa fa-refresh" /> {translate('REGENERATE_MNEMONIC')}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
|
@ -88,7 +81,7 @@ export default class GenerateMnemonic extends React.Component<{}, State> {
|
||||||
disabled={!canContinue}
|
disabled={!canContinue}
|
||||||
onClick={this.goToNextStep}
|
onClick={this.goToNextStep}
|
||||||
>
|
>
|
||||||
Confirm Phrase
|
{translate('CONFIRM_MNEMONIC')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ export default class MnemonicWord extends React.Component<Props, State> {
|
||||||
{!isReadOnly && (
|
{!isReadOnly && (
|
||||||
<span
|
<span
|
||||||
onClick={this.toggleShow}
|
onClick={this.toggleShow}
|
||||||
aria-label={translateRaw('GEN_Aria_2')}
|
aria-label={translateRaw('GEN_ARIA_2')}
|
||||||
role="button"
|
role="button"
|
||||||
className="MnemonicWord-word-toggle input-group-addon"
|
className="MnemonicWord-word-toggle input-group-addon"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import './Template.scss';
|
import './Template.scss';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: React.ReactElement<any>;
|
children: React.ReactElement<any>;
|
||||||
|
@ -10,7 +11,7 @@ const GenerateWalletTemplate: React.SFC<Props> = ({ children }) => (
|
||||||
<div className="GenerateWallet Tab-content-pane">
|
<div className="GenerateWallet Tab-content-pane">
|
||||||
{children}
|
{children}
|
||||||
<Link className="GenerateWallet-back" to="/generate">
|
<Link className="GenerateWallet-back" to="/generate">
|
||||||
<i className="fa fa-arrow-left" /> Back
|
<i className="fa fa-arrow-left" /> {translate('MODAL_BACK')}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import translate from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import { WalletType } from '../GenerateWallet';
|
import { WalletType } from '../GenerateWallet';
|
||||||
import { NewTabLink, HelpLink } from 'components/ui';
|
|
||||||
import { HELP_ARTICLE, trezorReferralURL, ledgerReferralURL } from 'config';
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import './WalletTypes.scss';
|
import './WalletTypes.scss';
|
||||||
|
import { HelpLink } from 'components/ui';
|
||||||
|
import { HELP_ARTICLE, ledgerReferralURL, trezorReferralURL } from 'config';
|
||||||
|
|
||||||
const WalletTypes: React.SFC<{}> = () => {
|
const WalletTypes: React.SFC<{}> = () => {
|
||||||
const typeInfo = {
|
const typeInfo = {
|
||||||
[WalletType.Keystore]: {
|
[WalletType.Keystore]: {
|
||||||
name: 'x_Keystore2',
|
name: 'X_KEYSTORE2',
|
||||||
bullets: [
|
bullets: [
|
||||||
'An encrypted JSON file, protected by a password',
|
'An encrypted JSON file, protected by a password',
|
||||||
'Back it up on a USB drive',
|
'Back it up on a USB drive',
|
||||||
|
@ -19,7 +19,7 @@ const WalletTypes: React.SFC<{}> = () => {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
[WalletType.Mnemonic]: {
|
[WalletType.Mnemonic]: {
|
||||||
name: 'x_Mnemonic',
|
name: 'X_MNEMONIC',
|
||||||
bullets: [
|
bullets: [
|
||||||
'A 12-word private seed phrase',
|
'A 12-word private seed phrase',
|
||||||
'Back it up on paper or USB drive',
|
'Back it up on paper or USB drive',
|
||||||
|
@ -32,15 +32,16 @@ const WalletTypes: React.SFC<{}> = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="WalletTypes Tab-content-pane">
|
<div className="WalletTypes Tab-content-pane">
|
||||||
<h1 className="WalletTypes-title">{translate('NAV_GenerateWallet')}</h1>
|
<h1 className="WalletTypes-title">{translate('NAV_GENERATEWALLET')}</h1>
|
||||||
<p className="WalletTypes-subtitle alert alert-warning">
|
<p className="WalletTypes-subtitle alert alert-warning">
|
||||||
<strong>Warning</strong>: Managing your own keys can be risky and a single mistake can lead
|
<strong>{translate('NOTIFICATION_TYPE_WARNING')}</strong>:{' '}
|
||||||
to irrecoverable loss. If you are new to cryptocurrencies, we strongly recommend using{' '}
|
{translate('GENERATE_WALLET_WARNING', {
|
||||||
<NewTabLink href="https://metamask.io/">MetaMask</NewTabLink>, or purchasing a{' '}
|
$metamask_link: 'https://metamask.io/',
|
||||||
<NewTabLink href={ledgerReferralURL}>Ledger</NewTabLink> or{' '}
|
$ledger_link: ledgerReferralURL,
|
||||||
<NewTabLink href={trezorReferralURL}>TREZOR</NewTabLink> hardware wallet.{' '}
|
$trezor_link: trezorReferralURL
|
||||||
|
})}
|
||||||
<HelpLink article={HELP_ARTICLE.DIFFERENCE_BETWEEN_PKEY_AND_KEYSTORE}>
|
<HelpLink article={HELP_ARTICLE.DIFFERENCE_BETWEEN_PKEY_AND_KEYSTORE}>
|
||||||
Learn more about different wallet types & staying secure.
|
{translate('GENERATE_WALLET_HELPLINK_1')}
|
||||||
</HelpLink>
|
</HelpLink>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ const WalletTypes: React.SFC<{}> = () => {
|
||||||
className="WalletType-select-btn btn btn-primary btn-block"
|
className="WalletType-select-btn btn btn-primary btn-block"
|
||||||
to={`/generate/${type}`}
|
to={`/generate/${type}`}
|
||||||
>
|
>
|
||||||
Generate a {translate(typeInfo[type].name)}
|
{translate('GENERATE_THING', { $thing: translateRaw(typeInfo[type].name) })}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { donationAddressMap } from 'config';
|
||||||
|
import React from 'react';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
onDonate(address: string, amount: string, unit: string): void;
|
||||||
|
}
|
||||||
|
interface State {
|
||||||
|
clicked: boolean;
|
||||||
|
}
|
||||||
|
export default class Donate extends React.Component<Props, State> {
|
||||||
|
public state = {
|
||||||
|
clicked: false
|
||||||
|
};
|
||||||
|
public render() {
|
||||||
|
return (
|
||||||
|
<div className="well">
|
||||||
|
<p>{translate('SIDEBAR_DONATION')}</p>
|
||||||
|
<a className="btn btn-primary btn-block" onClick={this.onClick}>
|
||||||
|
{translate('SIDEBAR_DONATE')}
|
||||||
|
</a>
|
||||||
|
{this.state.clicked && (
|
||||||
|
<div className="text-success text-center marg-v-sm">{translate('SIDEBAR_THANKS')}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public onClick = () => {
|
||||||
|
// FIXME move to config
|
||||||
|
this.props.onDonate(donationAddressMap.ETH, '1', 'ETH');
|
||||||
|
|
||||||
|
this.setState({ clicked: true });
|
||||||
|
};
|
||||||
|
}
|
|
@ -52,7 +52,7 @@ const QueryWarning: React.SFC<{}> = () => (
|
||||||
<WhenQueryExists
|
<WhenQueryExists
|
||||||
whenQueryExists={
|
whenQueryExists={
|
||||||
<div className="alert alert-info">
|
<div className="alert alert-info">
|
||||||
<p>{translate('WARN_Send_Link')}</p>
|
<p>{translate('WARN_SEND_LINK')}</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import translate from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import { getRecentWalletTransactions } from 'selectors/transactions';
|
import { getRecentWalletTransactions } from 'selectors/transactions';
|
||||||
import { getNetworkConfig } from 'selectors/config';
|
import { getNetworkConfig } from 'selectors/config';
|
||||||
import { NewTabLink } from 'components/ui';
|
|
||||||
import RecentTransaction from './RecentTransaction';
|
import RecentTransaction from './RecentTransaction';
|
||||||
import { TransactionStatus } from 'components';
|
import { TransactionStatus } from 'components';
|
||||||
import { IWallet } from 'libs/wallet';
|
import { IWallet } from 'libs/wallet';
|
||||||
|
@ -39,7 +38,7 @@ class RecentTransactions extends React.Component<Props> {
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<TransactionStatus txHash={activeTxHash} />
|
<TransactionStatus txHash={activeTxHash} />
|
||||||
<button className="RecentTxs-back btn btn-default" onClick={this.clearActiveTxHash}>
|
<button className="RecentTxs-back btn btn-default" onClick={this.clearActiveTxHash}>
|
||||||
<i className="fa fa-arrow-left" /> Back to Recent Transactions
|
<i className="fa fa-arrow-left" /> {translate('BACK_TO_RECENT_TXS')}
|
||||||
</button>
|
</button>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
@ -53,15 +52,13 @@ class RecentTransactions extends React.Component<Props> {
|
||||||
private renderTxList() {
|
private renderTxList() {
|
||||||
const { wallet, recentTransactions, network } = this.props;
|
const { wallet, recentTransactions, network } = this.props;
|
||||||
|
|
||||||
let explorer: React.ReactElement<string>;
|
let explorer: string;
|
||||||
if (network.isCustom) {
|
if (network.isCustom) {
|
||||||
explorer = <span>an explorer for the {network.name} network</span>;
|
explorer = translateRaw('RECENT_TX_NETWORK_EXPLORER', { $network_name: network.name });
|
||||||
} else {
|
} else {
|
||||||
explorer = (
|
explorer = `[${network.blockExplorer.name}](${network.blockExplorer.addressUrl(
|
||||||
<NewTabLink href={network.blockExplorer.addressUrl(wallet.getAddressString())}>
|
wallet.getAddressString()
|
||||||
{network.blockExplorer.name}
|
)})`;
|
||||||
</NewTabLink>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -69,9 +66,9 @@ class RecentTransactions extends React.Component<Props> {
|
||||||
{recentTransactions.length ? (
|
{recentTransactions.length ? (
|
||||||
<table className="RecentTxs-txs">
|
<table className="RecentTxs-txs">
|
||||||
<thead>
|
<thead>
|
||||||
<td>{translate('SEND_addr')}</td>
|
<td>{translate('SEND_ADDR')}</td>
|
||||||
<td>{translate('SEND_amount_short')}</td>
|
<td>{translate('SEND_AMOUNT_SHORT')}</td>
|
||||||
<td>{translate('Sent')}</td>
|
<td>{translate('SENT')}</td>
|
||||||
<td />
|
<td />
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -88,13 +85,12 @@ class RecentTransactions extends React.Component<Props> {
|
||||||
) : (
|
) : (
|
||||||
<div className="RecentTxs-empty well">
|
<div className="RecentTxs-empty well">
|
||||||
<h2 className="RecentTxs-empty-text">
|
<h2 className="RecentTxs-empty-text">
|
||||||
No recent MyCrypto transactions found, try checking on {explorer}.
|
{translate('NO_RECENT_TX_FOUND', { $explorer: explorer })}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<p className="RecentTxs-help">
|
<p className="RecentTxs-help">
|
||||||
Only recent transactions sent from this address via MyCrypto on the {network.name} network
|
{translate('RECENT_TX_HELP', { $network: network.name, $explorer: explorer })}
|
||||||
are listed here. If you don't see your transaction, you can view all of them on {explorer}.
|
|
||||||
</p>
|
</p>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
|
@ -123,7 +123,9 @@ class RequestPayment extends React.Component<Props, {}> {
|
||||||
|
|
||||||
{!!eip681String.length && (
|
{!!eip681String.length && (
|
||||||
<div className="row form-group">
|
<div className="row form-group">
|
||||||
<label className="RequestPayment-title">{translate('Payment QR & Code')}</label>
|
<label className="RequestPayment-title">
|
||||||
|
{translate('REQUEST_PAYMENT_QR_TITLE')}
|
||||||
|
</label>
|
||||||
<div className="col-xs-6">
|
<div className="col-xs-6">
|
||||||
<div className="RequestPayment-qr well well-lg">
|
<div className="RequestPayment-qr well well-lg">
|
||||||
<QRCode data={eip681String} />
|
<QRCode data={eip681String} />
|
||||||
|
|
|
@ -46,7 +46,7 @@ export default class WalletInfo extends React.PureComponent<Props, State> {
|
||||||
<div className="col-xs-11">
|
<div className="col-xs-11">
|
||||||
<div className="input-group-wrapper">
|
<div className="input-group-wrapper">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translate('x_Address')}</div>
|
<div className="input-group-header">{translate('X_ADDRESS')}</div>
|
||||||
<Input readOnly={true} value={address} />
|
<Input readOnly={true} value={address} />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -59,12 +59,12 @@ export default class WalletInfo extends React.PureComponent<Props, State> {
|
||||||
{privateKey && (
|
{privateKey && (
|
||||||
<div className="row form-group">
|
<div className="row form-group">
|
||||||
<div className="col-xs-12">
|
<div className="col-xs-12">
|
||||||
<label>{translate('x_PrivKey')}</label>
|
<label>{translate('X_PRIVKEY')}</label>
|
||||||
<TogglablePassword
|
<TogglablePassword
|
||||||
disabled={true}
|
disabled={true}
|
||||||
value={privateKey}
|
value={privateKey}
|
||||||
isVisible={isPrivateKeyVisible}
|
isVisible={isPrivateKeyVisible}
|
||||||
toggleAriaLabel={translateRaw('GEN_Aria_2')}
|
toggleAriaLabel={translateRaw('GEN_ARIA_2')}
|
||||||
handleToggleVisibility={this.togglePrivateKey}
|
handleToggleVisibility={this.togglePrivateKey}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -75,7 +75,7 @@ export default class WalletInfo extends React.PureComponent<Props, State> {
|
||||||
<div className="Tab-content-pane">
|
<div className="Tab-content-pane">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-xs-6">
|
<div className="col-xs-6">
|
||||||
<label>Public Address</label>
|
<label>{translate('TOKEN_ADDR')}</label>
|
||||||
<div className="WalletInfo-qr well well-lg">
|
<div className="WalletInfo-qr well well-lg">
|
||||||
<QRCode data={address} />
|
<QRCode data={address} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -83,7 +83,7 @@ export default class WalletInfo extends React.PureComponent<Props, State> {
|
||||||
{privateKey && (
|
{privateKey && (
|
||||||
<div>
|
<div>
|
||||||
<div className="col-xs-6">
|
<div className="col-xs-6">
|
||||||
<label>Private Key</label>
|
<label>{translate('X_PRIVKEY2')}</label>
|
||||||
<div className="WalletInfo-qr well well-lg" onClick={this.togglePrivateKey}>
|
<div className="WalletInfo-qr well well-lg" onClick={this.togglePrivateKey}>
|
||||||
<QRCode data={isPrivateKeyVisible ? privateKey : '0'} />
|
<QRCode data={isPrivateKeyVisible ? privateKey : '0'} />
|
||||||
{!isPrivateKeyVisible && (
|
{!isPrivateKeyVisible && (
|
||||||
|
@ -95,14 +95,14 @@ export default class WalletInfo extends React.PureComponent<Props, State> {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-xs-6">
|
<div className="col-xs-6">
|
||||||
<label>Utilities</label>
|
<label>{translate('WALLET_INFO_UTILITIES')}</label>
|
||||||
|
|
||||||
<button className="btn btn-info btn-block" onClick={print(address, privateKey)}>
|
<button className="btn btn-info btn-block" onClick={print(address, privateKey)}>
|
||||||
{translate('x_Print')}
|
{translate('X_PRINT')}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button className="btn btn-info btn-block" onClick={this.toggleKeystoreModal}>
|
<button className="btn btn-info btn-block" onClick={this.toggleKeystoreModal}>
|
||||||
Generate Keystore File
|
{translate('GENERATE_KEYSTORE_TITLE')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import translate from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import TabSection from 'containers/TabSection';
|
import TabSection from 'containers/TabSection';
|
||||||
import { UnlockHeader } from 'components/ui';
|
import { UnlockHeader } from 'components/ui';
|
||||||
import { getWalletInst } from 'selectors/wallet';
|
import { getWalletInst } from 'selectors/wallet';
|
||||||
|
@ -40,28 +40,28 @@ class SendTransaction extends React.Component<Props> {
|
||||||
const tabs: Tab[] = [
|
const tabs: Tab[] = [
|
||||||
{
|
{
|
||||||
path: 'send',
|
path: 'send',
|
||||||
name: translate('NAV_SendEther'),
|
name: translate('NAV_SENDETHER'),
|
||||||
disabled: !!wallet && !!wallet.isReadOnly
|
disabled: !!wallet && !!wallet.isReadOnly
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'request',
|
path: 'request',
|
||||||
name: translate('Request Payment'),
|
name: translate('NAV_REQUESTPAYMENT'),
|
||||||
disabled: this.props.requestDisabled
|
disabled: this.props.requestDisabled
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'info',
|
path: 'info',
|
||||||
name: translate('NAV_ViewWallet')
|
name: translate('NAV_VIEWWALLET')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'recent-txs',
|
path: 'recent-txs',
|
||||||
name: translate('Recent Transactions')
|
name: translate('NAV_RECENT_TX')
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TabSection>
|
<TabSection>
|
||||||
<section className="Tab-content">
|
<section className="Tab-content">
|
||||||
<UnlockHeader title={translate('Account')} showGenerateLink={true} />
|
<UnlockHeader title={translateRaw('ACCOUNT')} showGenerateLink={true} />
|
||||||
{wallet && (
|
{wallet && (
|
||||||
<div className="SubTabs row">
|
<div className="SubTabs row">
|
||||||
<div className="col-sm-8">
|
<div className="col-sm-8">
|
||||||
|
|
|
@ -15,7 +15,7 @@ export default class SignMessageButton extends React.Component<Props, {}> {
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<button className="SignMessage-sign btn btn-primary btn-lg" onClick={this.handleSignMessage}>
|
<button className="SignMessage-sign btn btn-primary btn-lg" onClick={this.handleSignMessage}>
|
||||||
{translate('NAV_SignMsg')}
|
{translate('NAV_SIGNMSG')}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -34,10 +34,10 @@ export default class SignMessageButton extends React.Component<Props, {}> {
|
||||||
onSignMessage(signedMessage);
|
onSignMessage(signedMessage);
|
||||||
showNotification(
|
showNotification(
|
||||||
'success',
|
'success',
|
||||||
`Successfully signed message with address ${signedMessage.address}.`
|
translate('SIGN_MSG_SUCCESS', { $address: signedMessage.address })
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showNotification('danger', `Error signing message: ${err.message}`);
|
showNotification('danger', translate('SIGN_MSG_FAIL', { $err: err.message }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import WalletDecrypt, { DISABLE_WALLETS } from 'components/WalletDecrypt';
|
import WalletDecrypt, { DISABLE_WALLETS } from 'components/WalletDecrypt';
|
||||||
import translate from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import { showNotification, TShowNotification } from 'actions/notifications';
|
import { showNotification, TShowNotification } from 'actions/notifications';
|
||||||
import { resetWallet, TResetWallet } from 'actions/wallet';
|
import { resetWallet, TResetWallet } from 'actions/wallet';
|
||||||
import { ISignedMessage } from 'libs/signing';
|
import { ISignedMessage } from 'libs/signing';
|
||||||
|
@ -29,8 +29,7 @@ const initialState: State = {
|
||||||
signedMessage: null
|
signedMessage: null
|
||||||
};
|
};
|
||||||
|
|
||||||
const messagePlaceholder =
|
const messagePlaceholder = translateRaw('SIGN_MSG_PLACEHOLDER');
|
||||||
'This is a sweet message that you are signing to prove that you own the address you say you own.';
|
|
||||||
|
|
||||||
export class SignMessage extends Component<Props, State> {
|
export class SignMessage extends Component<Props, State> {
|
||||||
public state: State = initialState;
|
public state: State = initialState;
|
||||||
|
@ -52,12 +51,12 @@ export class SignMessage extends Component<Props, State> {
|
||||||
onClick={this.changeWallet}
|
onClick={this.changeWallet}
|
||||||
>
|
>
|
||||||
<i className="fa fa-refresh" />
|
<i className="fa fa-refresh" />
|
||||||
{translate('Change Wallet')}
|
{translate('CHANGE_WALLET')}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div className="input-group-wrapper Deploy-field">
|
<div className="input-group-wrapper Deploy-field">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translate('MSG_message')}</div>
|
<div className="input-group-header">{translate('MSG_MESSAGE')}</div>
|
||||||
<TextArea
|
<TextArea
|
||||||
className={`SignMessage-inputBox ${message ? 'is-valid' : 'is-invalid'}`}
|
className={`SignMessage-inputBox ${message ? 'is-valid' : 'is-invalid'}`}
|
||||||
placeholder={messagePlaceholder}
|
placeholder={messagePlaceholder}
|
||||||
|
@ -65,7 +64,7 @@ export class SignMessage extends Component<Props, State> {
|
||||||
onChange={this.handleMessageChange}
|
onChange={this.handleMessageChange}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<div className="SignMessage-help">{translate('MSG_info2')}</div>
|
<div className="SignMessage-help">{translate('MSG_INFO2')}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SignButton
|
<SignButton
|
||||||
|
@ -78,7 +77,7 @@ export class SignMessage extends Component<Props, State> {
|
||||||
{!!signedMessage && (
|
{!!signedMessage && (
|
||||||
<div className="input-group-wrapper SignMessage-inputBox">
|
<div className="input-group-wrapper SignMessage-inputBox">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translate('MSG_signature')}</div>
|
<div className="input-group-header">{translate('MSG_SIGNATURE')}</div>
|
||||||
<TextArea
|
<TextArea
|
||||||
className="SignMessage-inputBox"
|
className="SignMessage-inputBox"
|
||||||
value={JSON.stringify(signedMessage, null, 2)}
|
value={JSON.stringify(signedMessage, null, 2)}
|
||||||
|
|
|
@ -39,7 +39,7 @@ export class VerifyMessage extends Component<Props, State> {
|
||||||
<div className="Tab-content-pane">
|
<div className="Tab-content-pane">
|
||||||
<div className="input-group-wrapper ">
|
<div className="input-group-wrapper ">
|
||||||
<label className="input-group">
|
<label className="input-group">
|
||||||
<div className="input-group-header">{translate('MSG_signature')}</div>
|
<div className="input-group-header">{translate('MSG_SIGNATURE')}</div>
|
||||||
<TextArea
|
<TextArea
|
||||||
className={`VerifyMessage-inputBox ${signature ? 'is-valid' : 'is-invalid'}`}
|
className={`VerifyMessage-inputBox ${signature ? 'is-valid' : 'is-invalid'}`}
|
||||||
placeholder={signaturePlaceholder}
|
placeholder={signaturePlaceholder}
|
||||||
|
@ -55,13 +55,13 @@ export class VerifyMessage extends Component<Props, State> {
|
||||||
onClick={this.handleVerifySignedMessage}
|
onClick={this.handleVerifySignedMessage}
|
||||||
disabled={false}
|
disabled={false}
|
||||||
>
|
>
|
||||||
{translate('MSG_verify')}
|
{translate('MSG_VERIFY')}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{!!verifiedAddress &&
|
{!!verifiedAddress &&
|
||||||
!!verifiedMessage && (
|
!!verifiedMessage && (
|
||||||
<div className="VerifyMessage-success alert alert-success">
|
<div className="VerifyMessage-success alert alert-success">
|
||||||
<strong>{verifiedAddress}</strong> did sign the message{' '}
|
<strong>{verifiedAddress}</strong> {translate('SIGNED')}
|
||||||
<strong>{verifiedMessage}</strong>.
|
<strong>{verifiedMessage}</strong>.
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -25,11 +25,11 @@ export default class SignAndVerifyMessage extends Component<RouteComponentProps<
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
path: 'sign',
|
path: 'sign',
|
||||||
name: translate('NAV_SignMsg')
|
name: translate('NAV_SIGNMSG')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'verify',
|
path: 'verify',
|
||||||
name: translate('MSG_verify')
|
name: translate('MSG_VERIFY')
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import translate from 'translations';
|
||||||
import QRCode from 'qrcode.react';
|
import QRCode from 'qrcode.react';
|
||||||
import './BitcoinQR.scss';
|
import './BitcoinQR.scss';
|
||||||
|
|
||||||
|
@ -13,19 +14,15 @@ export default class BitcoinQR extends PureComponent<Props, {}> {
|
||||||
return (
|
return (
|
||||||
<div className="BitcoinQR">
|
<div className="BitcoinQR">
|
||||||
<section className="row block swap-address text-center">
|
<section className="row block swap-address text-center">
|
||||||
<label> Your Address </label>
|
<label>{translate('X_ADDRESS')}</label>
|
||||||
<div className="BitcoinQR-qr">
|
<div className="BitcoinQR-qr">
|
||||||
<QRCode value={`bitcoin:${paymentAddress}amount=${destinationAmount}`} />
|
<QRCode value={`bitcoin:${paymentAddress}amount=${destinationAmount}`} />
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<p className="text-danger">
|
<p className="text-danger">{translate('SWAP_TIME_LIMIT_WARNING')}</p>
|
||||||
Orders that take too long will have to be processed manually & and may delay the
|
{translate('SWAP_RECOMMENDED_TX_FEES', {
|
||||||
amount of time it takes to receive your coins.
|
$link: 'https://shapeshift.io/#/btcfee'
|
||||||
<br />
|
})}
|
||||||
<a href="https://shapeshift.io/#/btcfee" target="_blank" rel="noopener noreferrer">
|
|
||||||
Please use the recommended TX fees seen here.
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
import SimpleButton from 'components/ui/SimpleButton';
|
import SimpleButton from 'components/ui/SimpleButton';
|
||||||
import { generateKindMax, generateKindMin, WhitelistedCoins, bityConfig } from 'config/bity';
|
import { generateKindMax, generateKindMin, WhitelistedCoins, bityConfig } from 'config/bity';
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import translate from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import { combineAndUpper } from 'utils/formatters';
|
import { combineAndUpper } from 'utils/formatters';
|
||||||
import { SwapDropdown, Input } from 'components/ui';
|
import { SwapDropdown, Input } from 'components/ui';
|
||||||
import Spinner from 'components/ui/Spinner';
|
import Spinner from 'components/ui/Spinner';
|
||||||
|
@ -81,9 +81,15 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
const rate = this.getMinMax(originKind, destKind);
|
const rate = this.getMinMax(originKind, destKind);
|
||||||
let errString;
|
let errString;
|
||||||
if (amount > rate.max) {
|
if (amount > rate.max) {
|
||||||
errString = `Maximum ${rate.max} ${originKind}`;
|
errString = translateRaw('SWAP_MAX_ERROR', {
|
||||||
|
$rate_max: rate.max.toString(),
|
||||||
|
$origin_id: originKind
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
errString = `Minimum ${rate.min} ${originKind}`;
|
errString = translateRaw('SWAP_MIN_ERROR', {
|
||||||
|
$rate_max: rate.min.toString(),
|
||||||
|
$origin_id: originKind
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return errString;
|
return errString;
|
||||||
};
|
};
|
||||||
|
@ -340,7 +346,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
<div className="CurrencySwap-inner-wrap">
|
<div className="CurrencySwap-inner-wrap">
|
||||||
<div className="flex-spacer" />
|
<div className="flex-spacer" />
|
||||||
<div className="input-group-wrapper">
|
<div className="input-group-wrapper">
|
||||||
<div className="input-group-header">Deposit</div>
|
<div className="input-group-header">{translate('SWAP_DEPOSIT_INPUT_LABEL')}</div>
|
||||||
<label className="input-group input-group-inline">
|
<label className="input-group input-group-inline">
|
||||||
<Input
|
<Input
|
||||||
id="origin-swap-input"
|
id="origin-swap-input"
|
||||||
|
@ -351,7 +357,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
: 'invalid'
|
: 'invalid'
|
||||||
}`}
|
}`}
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="Amount"
|
placeholder={translateRaw('SEND_AMOUNT_SHORT')}
|
||||||
value={isNaN(origin.amount) ? '' : origin.amount}
|
value={isNaN(origin.amount) ? '' : origin.amount}
|
||||||
onChange={this.onChangeAmount}
|
onChange={this.onChangeAmount}
|
||||||
/>
|
/>
|
||||||
|
@ -366,7 +372,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
|
|
||||||
<div className="input-group-wrapper">
|
<div className="input-group-wrapper">
|
||||||
<label className="input-group input-group-inline">
|
<label className="input-group input-group-inline">
|
||||||
<div className="input-group-header">Recieve</div>
|
<div className="input-group-header">{translate('SWAP_RECIEVE_INPUT_LABEL')}</div>
|
||||||
<Input
|
<Input
|
||||||
id="destination-swap-input"
|
id="destination-swap-input"
|
||||||
className={`${
|
className={`${
|
||||||
|
@ -376,7 +382,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
: 'invalid'
|
: 'invalid'
|
||||||
}`}
|
}`}
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="Amount"
|
placeholder={translateRaw('SEND_AMOUNT_SHORT')}
|
||||||
value={isNaN(destination.amount) ? '' : destination.amount}
|
value={isNaN(destination.amount) ? '' : destination.amount}
|
||||||
onChange={this.onChangeAmount}
|
onChange={this.onChangeAmount}
|
||||||
/>
|
/>
|
||||||
|
@ -395,7 +401,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
<div className="CurrencySwap-submit">
|
<div className="CurrencySwap-submit">
|
||||||
<SimpleButton
|
<SimpleButton
|
||||||
onClick={this.onClickStartSwap}
|
onClick={this.onClickStartSwap}
|
||||||
text={translate('SWAP_init_CTA')}
|
text={translateRaw('SWAP_INIT_CTA')}
|
||||||
disabled={this.state.disabled}
|
disabled={this.state.disabled}
|
||||||
type="primary"
|
type="primary"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -122,7 +122,7 @@ class CurrentRates extends PureComponent<Props> {
|
||||||
public swapEl = (providerURL: string, providerLogo: string, children: any) => {
|
public swapEl = (providerURL: string, providerLogo: string, children: any) => {
|
||||||
return (
|
return (
|
||||||
<article className="SwapRates">
|
<article className="SwapRates">
|
||||||
<h3 className="SwapRates-title">{translate('SWAP_rates')}</h3>
|
<h3 className="SwapRates-title">{translate('SWAP_RATES')}</h3>
|
||||||
|
|
||||||
<section className="SwapRates-panel row">
|
<section className="SwapRates-panel row">
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -31,7 +31,7 @@ class FieldsClass extends Component<Props> {
|
||||||
onClick={this.changeWallet}
|
onClick={this.changeWallet}
|
||||||
>
|
>
|
||||||
<i className="fa fa-refresh" />
|
<i className="fa fa-refresh" />
|
||||||
{translate('Change Wallet')}
|
{translate('CHANGE_WALLET')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-xs-12">
|
<div className="col-xs-12">
|
||||||
|
@ -46,7 +46,7 @@ class FieldsClass extends Component<Props> {
|
||||||
|
|
||||||
<div className="row form-group">
|
<div className="row form-group">
|
||||||
<div className="col-xs-12">
|
<div className="col-xs-12">
|
||||||
<label>{translate('SEND_amount')}</label>
|
<label>{translate('SEND_AMOUNT')}</label>
|
||||||
{currentBalance === null ? (
|
{currentBalance === null ? (
|
||||||
<div className="row text-center">
|
<div className="row text-center">
|
||||||
<Spinner />
|
<Spinner />
|
||||||
|
@ -56,10 +56,7 @@ class FieldsClass extends Component<Props> {
|
||||||
withProps={({ currentValue, isValid }) => (
|
withProps={({ currentValue, isValid }) => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{!isValid && (
|
{!isValid && (
|
||||||
<h5 style={{ color: 'red' }}>
|
<h5 style={{ color: 'red' }}>{translate('INSUFFICIENT_FUNDS')}</h5>
|
||||||
WARNING: Your ether or token balance is not high enough to complete this
|
|
||||||
transaction! Please send more funds or switch to a different wallet
|
|
||||||
</h5>
|
|
||||||
)}
|
)}
|
||||||
{isValid && (
|
{isValid && (
|
||||||
<Input
|
<Input
|
||||||
|
|
|
@ -14,19 +14,17 @@ export default class PaymentInfo extends PureComponent<Props, {}> {
|
||||||
const { origin } = this.props;
|
const { origin } = this.props;
|
||||||
return (
|
return (
|
||||||
<section className="SwapPayment">
|
<section className="SwapPayment">
|
||||||
<h1>
|
<h2>
|
||||||
<span>{translate('SWAP_order_CTA')}</span>
|
{translate('SWAP_SEND_TO', {
|
||||||
<strong>
|
$origin_amount: origin.amount.toString(),
|
||||||
{' '}
|
$origin_label: origin.label
|
||||||
{origin.amount} {origin.label}
|
})}
|
||||||
</strong>
|
|
||||||
<span> {translate('SENDModal_Content_2')}</span>
|
|
||||||
<Input
|
<Input
|
||||||
className="SwapPayment-address"
|
className="SwapPayment-address"
|
||||||
value={this.props.paymentAddress || undefined}
|
value={this.props.paymentAddress || undefined}
|
||||||
disabled={true}
|
disabled={true}
|
||||||
/>
|
/>
|
||||||
</h1>
|
</h2>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import SimpleButton from 'components/ui/SimpleButton';
|
||||||
import { donationAddressMap } from 'config';
|
import { donationAddressMap } from 'config';
|
||||||
import { isValidBTCAddress, isValidETHAddress } from 'libs/validators';
|
import { isValidBTCAddress, isValidETHAddress } from 'libs/validators';
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import translate from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import { combineAndUpper } from 'utils/formatters';
|
import { combineAndUpper } from 'utils/formatters';
|
||||||
import './ReceivingAddress.scss';
|
import './ReceivingAddress.scss';
|
||||||
import { Input } from 'components/ui';
|
import { Input } from 'components/ui';
|
||||||
|
@ -75,7 +75,7 @@ export default class ReceivingAddress extends PureComponent<StateProps & ActionP
|
||||||
<div className="col-sm-8 col-sm-offset-2 col-xs-12">
|
<div className="col-sm-8 col-sm-offset-2 col-xs-12">
|
||||||
<label className="SwapAddress-address">
|
<label className="SwapAddress-address">
|
||||||
<h4 className="SwapAddress-address-label">
|
<h4 className="SwapAddress-address-label">
|
||||||
{translate('SWAP_rec_add')} ({destinationId})
|
{translate('SWAP_REC_ADD')} ({destinationId})
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
|
@ -95,7 +95,7 @@ export default class ReceivingAddress extends PureComponent<StateProps & ActionP
|
||||||
|
|
||||||
<section className="SwapAddress-submit row">
|
<section className="SwapAddress-submit row">
|
||||||
<SimpleButton
|
<SimpleButton
|
||||||
text={translate('SWAP_start_CTA')}
|
text={translateRaw('SWAP_START_CTA')}
|
||||||
onClick={this.onClickPartTwoComplete}
|
onClick={this.onClickPartTwoComplete}
|
||||||
disabled={!validAddress}
|
disabled={!validAddress}
|
||||||
loading={isPostingOrder}
|
loading={isPostingOrder}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import './SupportFooter.scss';
|
||||||
import { SwapInput } from 'actions/swap';
|
import { SwapInput } from 'actions/swap';
|
||||||
import { NormalizedBityRates, NormalizedShapeshiftRates } from 'reducers/swap/types';
|
import { NormalizedBityRates, NormalizedShapeshiftRates } from 'reducers/swap/types';
|
||||||
import { TextArea } from 'components/ui';
|
import { TextArea } from 'components/ui';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
origin: SwapInput;
|
origin: SwapInput;
|
||||||
|
@ -75,11 +76,11 @@ Rate: ${rates[pair].rate} ${origin.label}/${destination.label}`;
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
Issue with your Swap? Contact support
|
{translate('SWAP_SUPPORT')}
|
||||||
</a>
|
</a>
|
||||||
<div className="SupportFooter-fallback">
|
<div className="SupportFooter-fallback">
|
||||||
<p onClick={this.toggleFallback}>
|
<p onClick={this.toggleFallback}>
|
||||||
<small>Click here if link doesn't work</small>
|
<small>{translate('SWAP_SUPPORT_LINK_BROKEN')}</small>
|
||||||
</p>
|
</p>
|
||||||
{open ? (
|
{open ? (
|
||||||
<TextArea defaultValue={fallbackBody} className="form-control input-sm" rows={9} />
|
<TextArea defaultValue={fallbackBody} className="form-control input-sm" rows={9} />
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue