diff --git a/common/components/ExtendedNotifications/TransactionSucceeded.tsx b/common/components/ExtendedNotifications/TransactionSucceeded.tsx
index ea0cb9b0..c2198890 100644
--- a/common/components/ExtendedNotifications/TransactionSucceeded.tsx
+++ b/common/components/ExtendedNotifications/TransactionSucceeded.tsx
@@ -1,26 +1,33 @@
import React from 'react';
-import { translateRaw } from 'translations';
+import { Link } from 'react-router-dom';
+import translate from 'translations';
+import { NewTabLink } from 'components/ui';
import { BlockExplorerConfig } from 'types/network';
export interface TransactionSucceededProps {
txHash: string;
- blockExplorer: BlockExplorerConfig;
+ blockExplorer?: BlockExplorerConfig;
}
const TransactionSucceeded = ({ txHash, blockExplorer }: TransactionSucceededProps) => {
- const txHashLink = blockExplorer.txUrl(txHash);
+ let verifyBtn: React.ReactElement | undefined;
+ if (blockExplorer) {
+ verifyBtn = (
+
+ Verify Transaction on {blockExplorer.name}
+
+ );
+ }
return (
-
{translateRaw('SUCCESS_3') + txHash}
-
- Verify Transaction
-
+
+ {translate('SUCCESS_3')} {txHash}
+
+ {verifyBtn}
+
+ {translate('NAV_CheckTxStatus')}
+
);
};
diff --git a/common/components/Footer/DisclaimerModal.tsx b/common/components/Footer/DisclaimerModal.tsx
index 8ec1b62b..3c18a17a 100644
--- a/common/components/Footer/DisclaimerModal.tsx
+++ b/common/components/Footer/DisclaimerModal.tsx
@@ -41,7 +41,11 @@ const DisclaimerModal: React.SFC = ({ isOpen, handleClose }) => {
English and, because of this, the English version of our website is the official text.
- MIT License Copyright © 2015-2017 MyCrypto LLC
+ MIT License
+
+ Copyright (c) 2015-2017 MyEtherWallet LLC
+
+ Copyright (c) 2018 MyCrypto, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this
diff --git a/common/components/LogOutPrompt.tsx b/common/components/LogOutPrompt.tsx
index a7921b75..dadde8f1 100644
--- a/common/components/LogOutPrompt.tsx
+++ b/common/components/LogOutPrompt.tsx
@@ -62,7 +62,7 @@ class LogOutPromptClass extends React.Component {
};
private onConfirm = () => {
- const { nextLocation } = this.state;
+ const { nextLocation: next } = this.state;
this.props.resetWallet();
this.setState(
{
@@ -70,8 +70,8 @@ class LogOutPromptClass extends React.Component {
nextLocation: null
},
() => {
- if (nextLocation) {
- this.props.history.push(nextLocation.pathname);
+ if (next) {
+ this.props.history.push(`${next.pathname}${next.search}${next.hash}`);
}
}
);
diff --git a/common/components/TXMetaDataPanel/TXMetaDataPanel.tsx b/common/components/TXMetaDataPanel/TXMetaDataPanel.tsx
index 5428b31e..71f9165f 100644
--- a/common/components/TXMetaDataPanel/TXMetaDataPanel.tsx
+++ b/common/components/TXMetaDataPanel/TXMetaDataPanel.tsx
@@ -10,7 +10,8 @@ import {
getNonceRequested,
TGetNonceRequested,
reset,
- TReset
+ TReset,
+ ResetAction
} from 'actions/transaction';
import { fetchCCRatesRequested, TFetchCCRatesRequested } from 'actions/rates';
import { getNetworkConfig, getOffline } from 'selectors/config';
@@ -44,6 +45,7 @@ interface DefaultProps {
}
interface OwnProps {
+ resetIncludeExcludeProperties?: ResetAction['payload'];
initialState?: SliderStates;
disableToggle?: boolean;
advancedGasOptions?: AdvancedOptions;
@@ -69,7 +71,7 @@ class TXMetaDataPanel extends React.Component {
public componentDidMount() {
if (!this.props.offline) {
- this.props.reset();
+ this.props.reset(this.props.resetIncludeExcludeProperties);
this.props.fetchCCRates([this.props.network.unit]);
this.props.getNonceRequested();
}
diff --git a/common/components/WalletDecrypt/WalletDecrypt.tsx b/common/components/WalletDecrypt/WalletDecrypt.tsx
index c1546264..b94a1c67 100644
--- a/common/components/WalletDecrypt/WalletDecrypt.tsx
+++ b/common/components/WalletDecrypt/WalletDecrypt.tsx
@@ -17,7 +17,7 @@ import {
resetWallet,
TResetWallet
} from 'actions/wallet';
-import { reset, TReset } from 'actions/transaction';
+import { reset, TReset, ResetAction } from 'actions/transaction';
import translate from 'translations';
import {
KeystoreDecrypt,
@@ -55,6 +55,7 @@ interface OwnProps {
hidden?: boolean;
disabledWallets?: DisabledWallets;
showGenerateLink?: boolean;
+ resetIncludeExcludeProperties?: ResetAction['payload'];
}
interface DispatchProps {
@@ -348,7 +349,7 @@ export class WalletDecrypt extends Component {
{this.props.showGenerateLink && (
- Don’t have a wallet? Click here to get one.
+ Don’t have an account yet? Click here to get one.
)}
@@ -430,7 +431,7 @@ export class WalletDecrypt extends Component {
// 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.resetTransactionState(this.props.resetIncludeExcludeProperties);
};
private isWalletDisabled = (walletKey: WalletName) => {
diff --git a/common/components/ui/Input.tsx b/common/components/ui/Input.tsx
index 6643287f..16895e80 100644
--- a/common/components/ui/Input.tsx
+++ b/common/components/ui/Input.tsx
@@ -9,6 +9,7 @@ class Input extends React.Component, State> {
public state: State = {
hasBlurred: false
};
+
public render() {
return (
, State> {
this.props.onBlur(e);
}
}}
+ onWheel={this.props.type === 'number' ? this.preventNumberScroll : undefined}
className={`input-group-input ${this.props.className} ${
this.state.hasBlurred ? 'has-blurred' : ''
} ${!!this.props.value && this.props.value.toString().length > 0 ? 'has-value' : ''}`}
/>
);
}
+
+ // When number inputs are scrolled on while in focus, the number changes. So we blur
+ // it if it's focused to prevent that behavior, without preventing the scroll.
+ private preventNumberScroll(ev: React.WheelEvent) {
+ if (document.activeElement === ev.currentTarget) {
+ ev.currentTarget.blur();
+ }
+ }
}
export default Input;
diff --git a/common/components/ui/Modal.scss b/common/components/ui/Modal.scss
index fa036cae..ea9d2d02 100644
--- a/common/components/ui/Modal.scss
+++ b/common/components/ui/Modal.scss
@@ -4,6 +4,8 @@
$m-background: #fff;
$m-window-padding-w: 20px;
$m-window-padding-h: 30px;
+$m-window-padding-w-mobile: 10px;
+$m-window-padding-h-mobile: 10px;
$m-header-height: 62px;
$m-header-padding: 1rem 2rem 0.5rem 2rem;
$m-content-padding: 1.5rem 2rem;
@@ -24,7 +26,7 @@ $m-anim-speed: 400ms;
.Modal {
position: fixed;
- top: 50%;
+ top: $m-window-padding-h;
left: 50%;
width: initial;
max-width: 95%;
@@ -33,7 +35,7 @@ $m-anim-speed: 400ms;
max-height: calc(100% - #{$m-window-padding-h * 2});
background: $m-background;
border-radius: 2px;
- transform: translate(-50%, -50%);
+ transform: translateX(-50%);
z-index: $zindex-modal;
overflow: hidden;
display: flex;
@@ -111,7 +113,10 @@ $m-anim-speed: 400ms;
// Mobile styles
@media(max-width: $screen-sm) {
- width: calc(100% - 40px) !important;
+ top: $m-window-padding-h-mobile;
+ width: calc(100% - #{$m-window-padding-w-mobile}) !important;
+ max-width: calc(100% - #{$m-window-padding-w-mobile * 2});
+ max-height: calc(100% - #{$m-window-padding-h-mobile * 2});
}
}
diff --git a/common/components/ui/Modal.tsx b/common/components/ui/Modal.tsx
index dbe3ca5b..ff0e2f13 100644
--- a/common/components/ui/Modal.tsx
+++ b/common/components/ui/Modal.tsx
@@ -97,6 +97,10 @@ export default class Modal extends PureComponent {
};
private escapeListner = (ev: KeyboardEvent) => {
+ if (!this.props.isOpen) {
+ return;
+ }
+
// Don't trigger if they hit escape while on an input
if (ev.target) {
if (
diff --git a/common/containers/Tabs/CheckTransaction/index.tsx b/common/containers/Tabs/CheckTransaction/index.tsx
index a4bb4429..0fae96f0 100644
--- a/common/containers/Tabs/CheckTransaction/index.tsx
+++ b/common/containers/Tabs/CheckTransaction/index.tsx
@@ -1,15 +1,17 @@
import React from 'react';
import { connect } from 'react-redux';
+import { RouteComponentProps } from 'react-router';
import TabSection from 'containers/TabSection';
import TxHashInput from './components/TxHashInput';
import { TransactionStatus as TransactionStatusComponent } from 'components';
import { NewTabLink } from 'components/ui';
import { getNetworkConfig } from 'selectors/config';
+import { getParamFromURL } from 'utils/helpers';
import { AppState } from 'reducers';
import { NetworkConfig } from 'types/network';
import './index.scss';
-interface Props {
+interface StateProps {
network: NetworkConfig;
}
@@ -17,11 +19,20 @@ interface State {
hash: string;
}
+type Props = StateProps & RouteComponentProps<{}>;
+
class CheckTransaction extends React.Component {
public state: State = {
hash: ''
};
+ public componentDidMount() {
+ const hash = getParamFromURL(this.props.location.search, 'txHash');
+ if (hash) {
+ this.setState({ hash });
+ }
+ }
+
public render() {
const { network } = this.props;
const { hash } = this.state;
@@ -43,7 +54,7 @@ class CheckTransaction extends React.Component {
)}
-
+
{hash && (
@@ -64,6 +75,6 @@ class CheckTransaction extends React.Component {
};
}
-export default connect((state: AppState) => ({
+export default connect((state: AppState): StateProps => ({
network: getNetworkConfig(state)
}))(CheckTransaction);
diff --git a/common/containers/Tabs/Contracts/components/Interact/components/InteractExplorer/components/Fields.tsx b/common/containers/Tabs/Contracts/components/Interact/components/InteractExplorer/components/Fields.tsx
index b3e0e920..7ff8a829 100644
--- a/common/containers/Tabs/Contracts/components/Interact/components/InteractExplorer/components/Fields.tsx
+++ b/common/containers/Tabs/Contracts/components/Interact/components/InteractExplorer/components/Fields.tsx
@@ -7,6 +7,7 @@ import { FullWalletOnly } from 'components/renderCbs';
interface OwnProps {
button: React.ReactElement;
}
+
export class Fields extends Component {
public render() {
const makeContent = () => (
@@ -17,6 +18,7 @@ export class Fields extends Component {
initialState="advanced"
disableToggle={true}
advancedGasOptions={{ dataField: false }}
+ resetIncludeExcludeProperties={{ exclude: { fields: ['to'] }, include: {} }}
/>
{this.props.button}
@@ -24,7 +26,12 @@ export class Fields extends Component {
);
- const makeDecrypt = () => ;
+ const makeDecrypt = () => (
+
+ );
return ;
}
diff --git a/common/sagas/transaction/broadcast/helpers.tsx b/common/sagas/transaction/broadcast/helpers.tsx
index 81e0fdf0..bacb0ae3 100644
--- a/common/sagas/transaction/broadcast/helpers.tsx
+++ b/common/sagas/transaction/broadcast/helpers.tsx
@@ -20,6 +20,7 @@ import React from 'react';
import { getNetworkConfig } from 'selectors/config';
import TransactionSucceeded from 'components/ExtendedNotifications/TransactionSucceeded';
import { computeIndexingHash } from 'libs/transaction';
+import { NetworkConfig } from 'types/network';
export const broadcastTransactionWrapper = (func: (serializedTx: string) => SagaIterator) =>
function* handleBroadcastTransaction(action: BroadcastRequestedAction) {
@@ -29,7 +30,7 @@ export const broadcastTransactionWrapper = (func: (serializedTx: string) => Saga
);
try {
- const shouldBroadcast = yield call(shouldBroadcastTransaction, indexingHash);
+ const shouldBroadcast: boolean = yield call(shouldBroadcastTransaction, indexingHash);
if (!shouldBroadcast) {
yield put(
showNotification(
@@ -46,16 +47,19 @@ export const broadcastTransactionWrapper = (func: (serializedTx: string) => Saga
});
yield put(queueAction);
const stringTx: string = yield call(bufferToHex, serializedTransaction);
- const broadcastedHash = yield call(func, stringTx); // convert to string because node / web3 doesnt support buffers
+ const broadcastedHash: string = yield call(func, stringTx); // convert to string because node / web3 doesnt support buffers
yield put(broadcastTransactionSucceeded({ indexingHash, broadcastedHash }));
- const network = yield select(getNetworkConfig);
- //TODO: make this not ugly
+ const network: NetworkConfig = yield select(getNetworkConfig);
+
yield put(
showNotification(
'success',
- ,
- 0
+ ,
+ Infinity
)
);
} catch (error) {
diff --git a/common/sagas/transaction/meta/unitSwap.ts b/common/sagas/transaction/meta/unitSwap.ts
index c5c056d0..7c31226c 100644
--- a/common/sagas/transaction/meta/unitSwap.ts
+++ b/common/sagas/transaction/meta/unitSwap.ts
@@ -32,7 +32,7 @@ export function* handleSetUnitMeta({ payload: currentUnit }: SetUnitMetaAction):
const tokenToToken = !currUnit && !prevUnit;
const decimal: number = yield select(getDecimalFromUnit, currentUnit);
- if (etherToEther) {
+ if (etherToEther || previousUnit === '') {
return;
}
diff --git a/common/sass/styles/overrides/alerts.scss b/common/sass/styles/overrides/alerts.scss
index 6d3f7a39..4ce8690a 100644
--- a/common/sass/styles/overrides/alerts.scss
+++ b/common/sass/styles/overrides/alerts.scss
@@ -1,7 +1,7 @@
// Extends Bootstrap's `.alert`
-@import "common/sass/variables";
-@import "common/sass/mixins";
-@import "~bootstrap-sass/assets/stylesheets/bootstrap/alerts";
+@import 'common/sass/variables';
+@import 'common/sass/mixins';
+@import '~bootstrap-sass/assets/stylesheets/bootstrap/alerts';
.alert {
margin-bottom: 1rem;
@@ -16,6 +16,13 @@
opacity: 0.8;
}
}
+
+ // Alerts have their own button style
+ .btn {
+ @include button-variant($text-color, #FFF, darken(#FFF, 5%));
+ text-decoration: none;
+ margin-right: $space-xs;
+ }
}
// Alert icons
diff --git a/common/sass/styles/overrides/buttons.scss b/common/sass/styles/overrides/buttons.scss
index 63858628..28654b3a 100644
--- a/common/sass/styles/overrides/buttons.scss
+++ b/common/sass/styles/overrides/buttons.scss
@@ -100,24 +100,6 @@
}
// Contextual color overrides (?)
-.alert .btn-info {
- background-color: white;
- text-decoration: none;
- color: $brand-info;
- &:hover,
- &:focus,
- &.focus {
- text-decoration: none;
- opacity: 1;
- }
- &.disabled {
- background-color: white;
- text-decoration: none;
- color: $brand-info;
- opacity: 0.6;
- }
-}
-
.btn-group .btn-default {
border-bottom-width: 1px;
border-color: transparent;
diff --git a/common/utils/consoleAdvertisement.ts b/common/utils/consoleAdvertisement.ts
index 83f544e5..dd78f6a7 100644
--- a/common/utils/consoleAdvertisement.ts
+++ b/common/utils/consoleAdvertisement.ts
@@ -18,7 +18,7 @@ export default function consoleAdvertisement() {
┃ ,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |__| | (_) | | | | | | |__| \\__ \\_| ┃
┃ ;;;;;;;;;;;; ;;;;;;;;; ;;;;;;;;;;;; \\____/ \\___/|_|_| |_| \\____/|___(_) ┃
┃ ;;;;;;;;;;;; ;;;;; ;;;;;;;;;;;, ┃
-┃ ;;;;;;;;;;;;: :;;;;;;;;;;;; https://github.com/MyCrypto/MyCrypto ┃
+┃ ;;;;;;;;;;;;: :;;;;;;;;;;;; https://github.com/MyCryptoHQ/MyCrypto ┃
┃ ;;;;;;;;;;;;;: :;;;;;;;;;;;;; ┃
┃ ;;;;;;;;;;;;;;: :;;;;;;;;;;;;;; ┃
┃ ';;;;;;;;;;;;;;;;;;;;;;;;;;;;; ┃
diff --git a/common/utils/helpers.ts b/common/utils/helpers.ts
index ddeb5009..b6d1fe2c 100644
--- a/common/utils/helpers.ts
+++ b/common/utils/helpers.ts
@@ -1,3 +1,4 @@
+import qs from 'query-string';
import has from 'lodash/has';
export function objectContainsObjectKeys(checkingObject, containingObject) {
@@ -19,6 +20,10 @@ export function getParam(query: { [key: string]: string }, key: string) {
return query[keys[index]];
}
+export function getParamFromURL(url: string, param: string): string | undefined {
+ return qs.parse(qs.extract(url))[param];
+}
+
export function isPositiveInteger(n: number) {
return Number.isInteger(n) && n > 0;
}
diff --git a/package.json b/package.json
index 380ed46b..4672bb13 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "MyCrypto",
"author": "MyCryptoHQ",
- "version": "0.4.0",
+ "version": "0.5.0",
"main": "main.js",
"description": "MyCrypto web and electron app",
"repository": "https://github.com/MyCryptoHQ/MyCrypto",
@@ -15,20 +15,20 @@
"bn.js": "4.11.8",
"bootstrap-sass": "3.3.7",
"classnames": "2.2.5",
- "electron-updater": "2.20.1",
+ "electron-updater": "2.21.0",
"ethereum-blockies": "git+https://github.com/MyCryptoHQ/blockies.git",
"ethereumjs-abi": "0.6.5",
"ethereumjs-tx": "1.3.3",
"ethereumjs-util": "5.1.5",
"ethereumjs-wallet": "0.6.0",
"font-awesome": "4.7.0",
- "hard-source-webpack-plugin": "0.5.16",
+ "hard-source-webpack-plugin": "0.6.4",
"hdkey": "0.8.0",
"idna-uts46": "1.1.0",
"jsonschema": "1.2.2",
"ledgerco": "1.2.1",
"lodash": "4.17.5",
- "moment": "2.20.1",
+ "moment": "2.21.0",
"normalizr": "3.2.4",
"qrcode": "1.2.0",
"qrcode.react": "0.8.0",
@@ -81,7 +81,7 @@
"copy-webpack-plugin": "4.5.0",
"css-loader": "0.28.10",
"electron": "1.8.2",
- "electron-builder": "20.2.0",
+ "electron-builder": "20.2.1",
"empty": "0.10.1",
"enzyme": "3.3.0",
"enzyme-adapter-react-16": "1.1.1",
@@ -111,12 +111,12 @@
"react-test-renderer": "16.2.0",
"redux-devtools-extension": "2.13.2",
"redux-test-utils": "0.2.2",
- "resolve-url-loader": "2.2.1",
+ "resolve-url-loader": "2.3.0",
"rimraf": "2.6.2",
- "sass-loader": "6.0.6",
+ "sass-loader": "6.0.7",
"style-loader": "0.20.2",
"thread-loader": "1.1.5",
- "ts-jest": "22.4.0",
+ "ts-jest": "22.4.1",
"ts-loader": "3.3.1",
"tslint": "5.9.1",
"tslint-config-prettier": "1.9.0",
@@ -124,7 +124,7 @@
"tslint-react": "3.5.1",
"types-rlp": "0.0.1",
"typescript": "2.6.2",
- "url-loader": "0.6.2",
+ "url-loader": "1.0.1",
"url-search-params-polyfill": "2.0.3",
"webpack": "3.11.0",
"webpack-dev-middleware": "2.0.6",
diff --git a/spec/sagas/transaction/broadcast/helpers.spec.tsx b/spec/sagas/transaction/broadcast/helpers.spec.tsx
index 11eb3657..0a8845f5 100644
--- a/spec/sagas/transaction/broadcast/helpers.spec.tsx
+++ b/spec/sagas/transaction/broadcast/helpers.spec.tsx
@@ -128,7 +128,7 @@ describe('broadcastTransactionWrapper*', () => {
showNotification(
'success',
,
- 0
+ Infinity
)
)
);