Wallet Loading States & Spinner Update (#334)

* Add disclaimer modal to footer

* Remove duplicate code & unnecessary styles

* Fix formatting noise

* remove un-used css style

* Fix tslint error & add media query for modals

* Nest Media Query

* Replace '???' with Spinner & update spinner

* Add loading states for wallet balances

* Update wallet test

* Remove excess data passed to wallet balance reducer & Fix wallet balance types

* Merge 'develop' into 'loading-indicator'

* Add 'light' prop to Spinner

* Only show spinners when fetching data

* Remove format diff

* Apply naming conventions

* Remove network name when offline
This commit is contained in:
James Prado 2017-11-14 22:44:55 -05:00 committed by Daniel Ternyak
parent 7e7c070abe
commit 0d5d0cea9a
23 changed files with 215 additions and 79 deletions

View File

@ -47,14 +47,28 @@ export function setWallet(value: IWallet): types.SetWalletAction {
}; };
} }
export type TSetBalance = typeof setBalance; export function setBalancePending(): types.SetBalancePendingAction {
export function setBalance(value: Wei): types.SetBalanceAction {
return { return {
type: TypeKeys.WALLET_SET_BALANCE, type: TypeKeys.WALLET_SET_BALANCE_PENDING
};
}
export type TSetBalance = typeof setBalanceFullfilled;
export function setBalanceFullfilled(
value: Wei
): types.SetBalanceFullfilledAction {
return {
type: TypeKeys.WALLET_SET_BALANCE_FULFILLED,
payload: value payload: value
}; };
} }
export function setBalanceRejected(): types.SetBalanceRejectedAction {
return {
type: TypeKeys.WALLET_SET_BALANCE_REJECTED
};
}
export type TSetTokenBalances = typeof setTokenBalances; export type TSetTokenBalances = typeof setTokenBalances;
export function setTokenBalances(payload: { export function setTokenBalances(payload: {
[key: string]: TokenValue; [key: string]: TokenValue;

View File

@ -33,10 +33,16 @@ export interface ResetWalletAction {
} }
/*** Set Balance ***/ /*** Set Balance ***/
export interface SetBalanceAction { export interface SetBalancePendingAction {
type: TypeKeys.WALLET_SET_BALANCE; type: TypeKeys.WALLET_SET_BALANCE_PENDING;
}
export interface SetBalanceFullfilledAction {
type: TypeKeys.WALLET_SET_BALANCE_FULFILLED;
payload: Wei; payload: Wei;
} }
export interface SetBalanceRejectedAction {
type: TypeKeys.WALLET_SET_BALANCE_REJECTED;
}
/*** Set Token Balance ***/ /*** Set Token Balance ***/
export interface SetTokenBalancesAction { export interface SetTokenBalancesAction {
@ -94,7 +100,9 @@ export type WalletAction =
| UnlockPrivateKeyAction | UnlockPrivateKeyAction
| SetWalletAction | SetWalletAction
| ResetWalletAction | ResetWalletAction
| SetBalanceAction | SetBalancePendingAction
| SetBalanceFullfilledAction
| SetBalanceRejectedAction
| SetTokenBalancesAction | SetTokenBalancesAction
| BroadcastTxRequestedAction | BroadcastTxRequestedAction
| BroadcastTxFailedAction | BroadcastTxFailedAction

View File

@ -4,7 +4,9 @@ export enum TypeKeys {
WALLET_UNLOCK_MNEMONIC = 'WALLET_UNLOCK_MNEMONIC', WALLET_UNLOCK_MNEMONIC = 'WALLET_UNLOCK_MNEMONIC',
WALLET_UNLOCK_WEB3 = 'WALLET_UNLOCK_WEB3', WALLET_UNLOCK_WEB3 = 'WALLET_UNLOCK_WEB3',
WALLET_SET = 'WALLET_SET', WALLET_SET = 'WALLET_SET',
WALLET_SET_BALANCE = 'WALLET_SET_BALANCE', WALLET_SET_BALANCE_PENDING = 'WALLET_SET_BALANCE_PENDING',
WALLET_SET_BALANCE_FULFILLED = 'WALLET_SET_BALANCE_FULFILLED',
WALLET_SET_BALANCE_REJECTED = 'WALLET_SET_BALANCE_REJECTED',
WALLET_SET_TOKEN_BALANCES = 'WALLET_SET_TOKEN_BALANCES', WALLET_SET_TOKEN_BALANCES = 'WALLET_SET_TOKEN_BALANCES',
WALLET_BROADCAST_TX_REQUESTED = 'WALLET_BROADCAST_TX_REQUESTED', WALLET_BROADCAST_TX_REQUESTED = 'WALLET_BROADCAST_TX_REQUESTED',
WALLET_BROADCAST_TX_FAILED = 'WALLET_BROADCAST_TX_FAILED', WALLET_BROADCAST_TX_FAILED = 'WALLET_BROADCAST_TX_FAILED',

View File

@ -1,14 +1,14 @@
import { TFetchCCRates } from 'actions/rates'; import { TFetchCCRates } from 'actions/rates';
import { Identicon, UnitDisplay } from 'components/ui'; import { Identicon, UnitDisplay } from 'components/ui';
import { NetworkConfig } from 'config/data'; import { NetworkConfig } from 'config/data';
import { IWallet } from 'libs/wallet'; import { IWallet, Balance } from 'libs/wallet';
import { Wei } from 'libs/units';
import React from 'react'; import React from 'react';
import translate from 'translations'; import translate from 'translations';
import './AccountInfo.scss'; import './AccountInfo.scss';
import Spinner from 'components/ui/Spinner';
interface Props { interface Props {
balance: Wei; balance: Balance;
wallet: IWallet; wallet: IWallet;
network: NetworkConfig; network: NetworkConfig;
fetchCCRates: TFetchCCRates; fetchCCRates: TFetchCCRates;
@ -79,13 +79,17 @@ export default class AccountInfo extends React.Component<Props, State> {
className="AccountInfo-list-item-clickable mono wrap" className="AccountInfo-list-item-clickable mono wrap"
onClick={this.toggleShowLongBalance} onClick={this.toggleShowLongBalance}
> >
<UnitDisplay {balance.isPending ? (
value={balance} <Spinner />
unit={'ether'} ) : (
displayShortBalance={!showLongBalance} <UnitDisplay
/> value={balance.wei}
unit={'ether'}
displayShortBalance={!showLongBalance}
/>
)}
</span> </span>
{` ${network.name}`} {balance ? `${network.name}` : null}
</li> </li>
</ul> </ul>
</div> </div>

View File

@ -1,5 +1,5 @@
@import "common/sass/variables"; @import 'common/sass/variables';
@import "common/sass/mixins"; @import 'common/sass/mixins';
.EquivalentValues { .EquivalentValues {
&-title { &-title {
@ -25,6 +25,7 @@
} }
&-label { &-label {
white-space: pre-wrap;
display: inline-block; display: inline-block;
min-width: 36px; min-width: 36px;
} }

View File

@ -1,13 +1,14 @@
import { Wei } from 'libs/units';
import React from 'react'; import React from 'react';
import translate from 'translations'; import translate from 'translations';
import './EquivalentValues.scss'; import './EquivalentValues.scss';
import { State } from 'reducers/rates'; import { State } from 'reducers/rates';
import { symbols } from 'actions/rates'; import { symbols } from 'actions/rates';
import { UnitDisplay } from 'components/ui'; import { UnitDisplay } from 'components/ui';
import { Balance } from 'libs/wallet';
import Spinner from 'components/ui/Spinner';
interface Props { interface Props {
balance?: Wei; balance: Balance;
rates?: State['rates']; rates?: State['rates'];
ratesError?: State['ratesError']; ratesError?: State['ratesError'];
} }
@ -29,18 +30,19 @@ export default class EquivalentValues extends React.Component<Props, {}> {
return ( return (
<li className="EquivalentValues-values-currency" key={key}> <li className="EquivalentValues-values-currency" key={key}>
<span className="EquivalentValues-values-currency-label"> <span className="EquivalentValues-values-currency-label">
{key}: {key + ': '}
</span> </span>
<span className="EquivalentValues-values-currency-value"> <span className="EquivalentValues-values-currency-value">
{' '} {balance.isPending ? (
{balance ? ( <Spinner />
) : (
<UnitDisplay <UnitDisplay
unit={'ether'} unit={'ether'}
value={balance.muln(rates[key])} value={
balance.wei ? balance.wei.muln(rates[key]) : null
}
displayShortBalance={2} displayShortBalance={2}
/> />
) : (
'???'
)} )}
</span> </span>
</li> </li>

View File

@ -7,8 +7,7 @@ import {
import { showNotification, TShowNotification } from 'actions/notifications'; import { showNotification, TShowNotification } from 'actions/notifications';
import { fetchCCRates as dFetchCCRates, TFetchCCRates } from 'actions/rates'; import { fetchCCRates as dFetchCCRates, TFetchCCRates } from 'actions/rates';
import { NetworkConfig } from 'config/data'; import { NetworkConfig } from 'config/data';
import { Wei } from 'libs/units'; import { IWallet, Balance } from 'libs/wallet';
import { IWallet } from 'libs/wallet/IWallet';
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';
@ -27,7 +26,7 @@ import OfflineToggle from './OfflineToggle';
interface Props { interface Props {
wallet: IWallet; wallet: IWallet;
balance: Wei; balance: Balance;
network: NetworkConfig; network: NetworkConfig;
tokenBalances: TokenBalance[]; tokenBalances: TokenBalance[];
rates: State['rates']; rates: State['rates'];

View File

@ -0,0 +1,66 @@
.Spinner {
animation: rotate 2s linear infinite;
&-x1 {
height: 1em;
width: 1em;
}
&-x2 {
height: 2em;
width: 2em;
}
&-x3 {
height: 3em;
width: 3em;
}
&-x4 {
height: 4em;
width: 4em;
}
&-x5 {
height: 5em;
width: 5em;
}
& .path {
stroke-linecap: round;
animation: dash 1.5s ease-in-out infinite;
}
&-light {
& .path {
stroke: white;
}
}
&-dark {
& .path {
stroke: #163151;
}
}
}
@keyframes rotate {
100% {
transform: rotate(360deg);
}
}
@keyframes dash {
0% {
stroke-dasharray: 1, 150;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -35;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -124;
}
}

View File

@ -1,13 +1,27 @@
import React from 'react'; import React from 'react';
import './Spinner.scss';
type Size = 'lg' | '2x' | '3x' | '4x' | '5x'; type Size = 'x1' | 'x2' | 'x3' | 'x4' | 'x5';
interface SpinnerProps { interface SpinnerProps {
size?: Size; size?: Size;
light?: boolean;
} }
const Spinner = ({ size = 'fa-' }: SpinnerProps) => { const Spinner = ({ size = 'x1', light = false }: SpinnerProps) => {
return <i className={`fa fa-spinner fa-spin fa-${size ? size : 'fw'}`} />; const color = light ? 'Spinner-light' : 'Spinner-dark';
return (
<svg className={`Spinner Spinner-${size} ${color}`} viewBox="0 0 50 50">
<circle
className="path"
cx="25"
cy="25"
r="20"
fill="none"
strokeWidth="5"
/>
</svg>
);
}; };
export default Spinner; export default Spinner;

View File

@ -14,7 +14,7 @@ interface Props {
* @type {TokenValue | Wei} * @type {TokenValue | Wei}
* @memberof Props * @memberof Props
*/ */
value?: TokenValue | Wei; value?: TokenValue | Wei | null;
/** /**
* @description Symbol to display to the right of the value, such as 'ETH' * @description Symbol to display to the right of the value, such as 'ETH'
* @type {string} * @type {string}
@ -43,7 +43,7 @@ const UnitDisplay: React.SFC<EthProps | TokenProps> = params => {
const { value, symbol, displayShortBalance } = params; const { value, symbol, displayShortBalance } = params;
if (!value) { if (!value) {
return <span>???</span>; return <span>Balance isn't available offline</span>;
} }
const convertedValue = isEthereumUnit(params) const convertedValue = isEthereumUnit(params)

View File

@ -1,5 +1,5 @@
import { Wei } from 'libs/units'; import { Wei } from 'libs/units';
import { IWallet } from 'libs/wallet/IWallet'; import { IWallet, Balance } from 'libs/wallet';
import { RPCNode } from 'libs/nodes'; import { RPCNode } from 'libs/nodes';
import { NodeConfig, NetworkConfig } from 'config/data'; import { NodeConfig, NetworkConfig } from 'config/data';
import { TBroadcastTx } from 'actions/wallet'; import { TBroadcastTx } from 'actions/wallet';
@ -7,7 +7,7 @@ import { TShowNotification } from 'actions/notifications';
export interface Props { export interface Props {
wallet: IWallet; wallet: IWallet;
balance: Wei; balance: Balance;
node: NodeConfig; node: NodeConfig;
nodeLib: RPCNode; nodeLib: RPCNode;
chainId: NetworkConfig['chainId']; chainId: NetworkConfig['chainId'];

View File

@ -4,13 +4,13 @@ import { toWei, Wei, getDecimal } from 'libs/units';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { showNotification, TShowNotification } from 'actions/notifications'; import { showNotification, TShowNotification } from 'actions/notifications';
import { broadcastTx, TBroadcastTx } from 'actions/wallet'; import { broadcastTx, TBroadcastTx } from 'actions/wallet';
import { IWallet } from 'libs/wallet/IWallet'; import { IWallet, Balance } from 'libs/wallet';
import { RPCNode } from 'libs/nodes'; import { RPCNode } from 'libs/nodes';
import { NodeConfig, NetworkConfig } from 'config/data'; import { NodeConfig, NetworkConfig } from 'config/data';
export interface IWithTx { export interface IWithTx {
wallet: IWallet; wallet: IWallet;
balance: Wei; balance: Balance;
node: NodeConfig; node: NodeConfig;
nodeLib: RPCNode; nodeLib: RPCNode;
chainId: NetworkConfig['chainId']; chainId: NetworkConfig['chainId'];

View File

@ -1,13 +1,13 @@
import React from 'react'; import React from 'react';
import translate, { translateRaw } from 'translations'; import translate, { translateRaw } from 'translations';
import UnitDropdown from './UnitDropdown'; import UnitDropdown from './UnitDropdown';
import { Wei } from 'libs/units'; import { Balance } from 'libs/wallet';
import { UnitConverter } from 'components/renderCbs'; import { UnitConverter } from 'components/renderCbs';
interface Props { interface Props {
decimal: number; decimal: number;
unit: string; unit: string;
tokens: string[]; tokens: string[];
balance: number | null | Wei; balance: number | null | Balance;
isReadOnly: boolean; isReadOnly: boolean;
onAmountChange(value: string, unit: string): void; onAmountChange(value: string, unit: string): void;
onUnitChange(unit: string): void; onUnitChange(unit: string): void;
@ -30,10 +30,11 @@ export default class AmountField extends React.Component {
<UnitConverter decimal={decimal} onChange={this.callWithBaseUnit}> <UnitConverter decimal={decimal} onChange={this.callWithBaseUnit}>
{({ onUserInput, convertedUnit }) => ( {({ onUserInput, convertedUnit }) => (
<input <input
className={`form-control ${isFinite(Number(convertedUnit)) && className={`form-control ${
Number(convertedUnit) > 0 isFinite(Number(convertedUnit)) && Number(convertedUnit) > 0
? 'is-valid' ? 'is-valid'
: 'is-invalid'}`} : 'is-invalid'
}`}
type="text" type="text"
placeholder={translateRaw('SEND_amount_short')} placeholder={translateRaw('SEND_amount_short')}
value={convertedUnit} value={convertedUnit}

View File

@ -115,7 +115,7 @@ class ConfirmationModal extends React.Component<Props, State> {
<div className="ConfModal"> <div className="ConfModal">
{isBroadcasting ? ( {isBroadcasting ? (
<div className="ConfModal-loading"> <div className="ConfModal-loading">
<Spinner size="5x" /> <Spinner size="x5" />
</div> </div>
) : ( ) : (
<div> <div>

View File

@ -32,7 +32,7 @@ import {
import { UnitKey, Wei, getDecimal, toWei } from 'libs/units'; import { UnitKey, Wei, getDecimal, toWei } from 'libs/units';
import { isValidETHAddress } from 'libs/validators'; import { isValidETHAddress } from 'libs/validators';
// LIBS // LIBS
import { IWallet, Web3Wallet } from 'libs/wallet'; import { IWallet, Balance, Web3Wallet } from 'libs/wallet';
import pickBy from 'lodash/pickBy'; import pickBy from 'lodash/pickBy';
import React from 'react'; import React from 'react';
// REDUX // REDUX
@ -92,7 +92,7 @@ interface State {
interface Props { interface Props {
wallet: IWallet; wallet: IWallet;
balance: Wei; balance: Balance;
nodeLib: RPCNode; nodeLib: RPCNode;
network: NetworkConfig; network: NetworkConfig;
tokens: MergedToken[]; tokens: MergedToken[];
@ -353,7 +353,7 @@ export class SendTransaction extends React.Component<Props, State> {
{generateTxProcessing && ( {generateTxProcessing && (
<div className="container"> <div className="container">
<div className="row form-group text-center"> <div className="row form-group text-center">
<Spinner size="5x" /> <Spinner size="x5" />
</div> </div>
</div> </div>
)} )}
@ -574,7 +574,7 @@ export class SendTransaction extends React.Component<Props, State> {
value = getBalanceMinusGasCosts( value = getBalanceMinusGasCosts(
bigGasLimit, bigGasLimit,
gasPrice, gasPrice,
balance balance.wei
).toString(); ).toString();
} else { } else {
const tokenBalance = this.props.tokenBalances.find( const tokenBalance = this.props.tokenBalances.find(

View File

@ -44,14 +44,13 @@ export default class CurrentRates extends Component<Pairs, State> {
name={pair + 'Amount'} name={pair + 'Amount'}
/> />
<span className="SwapRates-panel-rate-amount"> <span className="SwapRates-panel-rate-amount">
{` ${origin} = ${toFixedIfLarger( {` ${origin} = ${toFixedIfLarger(statePair * propsPair, 6)} ${
statePair * propsPair, destination
6 }`}
)} ${destination}`}
</span> </span>
</div> </div>
) : ( ) : (
<Spinner /> <Spinner size="x1" light={true} />
)} )}
</div> </div>
); );

View File

@ -183,11 +183,9 @@ EncodedCall:${data}`);
//TODO: parse args based on type //TODO: parse args based on type
if (!suppliedArgs[name]) { if (!suppliedArgs[name]) {
throw Error( throw Error(
`Expected argument "${name}" of type "${type}" missing, suppliedArgs: ${JSON.stringify( `Expected argument "${name}" of type "${
suppliedArgs, type
null, }" missing, suppliedArgs: ${JSON.stringify(suppliedArgs, null, 2)}`
2
)}`
); );
} }
const value = suppliedArgs[name]; const value = suppliedArgs[name];

View File

@ -0,0 +1,6 @@
import { Wei } from 'libs/units';
export interface Balance {
wei: Wei;
isPending: boolean;
}

View File

@ -1,3 +1,4 @@
export { IWallet } from './IWallet'; export { IWallet } from './IWallet';
export { Balance } from './balance';
export * from './deterministic'; export * from './deterministic';
export * from './non-deterministic'; export * from './non-deterministic';

View File

@ -1,19 +1,19 @@
import { SetBalanceFullfilledAction } from 'actions/wallet/actionTypes';
import { import {
SetBalanceAction,
SetTokenBalancesAction, SetTokenBalancesAction,
SetWalletAction, SetWalletAction,
WalletAction, WalletAction,
TypeKeys TypeKeys
} from 'actions/wallet'; } from 'actions/wallet';
import { Wei, TokenValue } from 'libs/units'; import { TokenValue } from 'libs/units';
import { BroadcastTransactionStatus } from 'libs/transaction'; import { BroadcastTransactionStatus } from 'libs/transaction';
import { IWallet } from 'libs/wallet'; import { IWallet, Balance } from 'libs/wallet';
import { getTxFromBroadcastTransactionStatus } from 'selectors/wallet'; import { getTxFromBroadcastTransactionStatus } from 'selectors/wallet';
export interface State { export interface State {
inst?: IWallet | null; inst?: IWallet | null;
// in ETH // in ETH
balance?: Wei | null; balance: Balance | { wei: null };
tokens: { tokens: {
[key: string]: TokenValue; [key: string]: TokenValue;
}; };
@ -22,18 +22,36 @@ export interface State {
export const INITIAL_STATE: State = { export const INITIAL_STATE: State = {
inst: null, inst: null,
balance: null, balance: { isPending: false, wei: null },
tokens: {}, tokens: {},
transactions: [] transactions: []
}; };
function setWallet(state: State, action: SetWalletAction): State { function setWallet(state: State, action: SetWalletAction): State {
return { ...state, inst: action.payload, balance: null, tokens: {} }; return {
...state,
inst: action.payload,
balance: INITIAL_STATE.balance,
tokens: INITIAL_STATE.tokens
};
} }
function setBalance(state: State, action: SetBalanceAction): State { function setBalancePending(state: State): State {
const weiBalance = action.payload; return { ...state, balance: { ...state.balance, isPending: true } };
return { ...state, balance: weiBalance }; }
function setBalanceFullfilled(
state: State,
action: SetBalanceFullfilledAction
): State {
return {
...state,
balance: { wei: action.payload, isPending: false }
};
}
function setBalanceRejected(state: State): State {
return { ...state, balance: { ...state.balance, isPending: false } };
} }
function setTokenBalances(state: State, action: SetTokenBalancesAction): State { function setTokenBalances(state: State, action: SetTokenBalancesAction): State {
@ -111,8 +129,12 @@ export function wallet(
return setWallet(state, action); return setWallet(state, action);
case TypeKeys.WALLET_RESET: case TypeKeys.WALLET_RESET:
return INITIAL_STATE; return INITIAL_STATE;
case TypeKeys.WALLET_SET_BALANCE: case TypeKeys.WALLET_SET_BALANCE_PENDING:
return setBalance(state, action); return setBalancePending(state);
case TypeKeys.WALLET_SET_BALANCE_FULFILLED:
return setBalanceFullfilled(state, action);
case TypeKeys.WALLET_SET_BALANCE_REJECTED:
return setBalanceRejected(state);
case TypeKeys.WALLET_SET_TOKEN_BALANCES: case TypeKeys.WALLET_SET_TOKEN_BALANCES:
return setTokenBalances(state, action); return setTokenBalances(state, action);
case TypeKeys.WALLET_BROADCAST_TX_REQUESTED: case TypeKeys.WALLET_BROADCAST_TX_REQUESTED:

View File

@ -3,7 +3,9 @@ import {
broadCastTxFailed, broadCastTxFailed,
BroadcastTxRequestedAction, BroadcastTxRequestedAction,
broadcastTxSucceded, broadcastTxSucceded,
setBalance, setBalanceFullfilled,
setBalancePending,
setBalanceRejected,
setTokenBalances, setTokenBalances,
setWallet, setWallet,
UnlockKeystoreAction, UnlockKeystoreAction,
@ -39,6 +41,7 @@ import translate from 'translations';
function* updateAccountBalance(): SagaIterator { function* updateAccountBalance(): SagaIterator {
try { try {
yield put(setBalancePending());
const wallet: null | IWallet = yield select(getWalletInst); const wallet: null | IWallet = yield select(getWalletInst);
if (!wallet) { if (!wallet) {
return; return;
@ -47,9 +50,9 @@ function* updateAccountBalance(): SagaIterator {
const address = yield apply(wallet, wallet.getAddressString); const address = yield apply(wallet, wallet.getAddressString);
// network request // network request
const balance: Wei = yield apply(node, node.getBalance, [address]); const balance: Wei = yield apply(node, node.getBalance, [address]);
yield put(setBalance(balance)); yield put(setBalanceFullfilled(balance));
} catch (error) { } catch (error) {
yield put({ type: 'updateAccountBalance_error', error }); yield put(setBalanceRejected());
} }
} }
@ -191,8 +194,6 @@ function* broadcastTx(action: BroadcastTxRequestedAction): SagaIterator {
} }
export default function* walletSaga(): SagaIterator { export default function* walletSaga(): SagaIterator {
// useful for development
yield call(updateBalances);
yield [ yield [
takeEvery('WALLET_UNLOCK_PRIVATE_KEY', unlockPrivateKey), takeEvery('WALLET_UNLOCK_PRIVATE_KEY', unlockPrivateKey),
takeEvery('WALLET_UNLOCK_KEYSTORE', unlockKeystore), takeEvery('WALLET_UNLOCK_KEYSTORE', unlockKeystore),

View File

@ -369,7 +369,7 @@ declare module 'bn.js' {
* @description reduct * @description reduct
*/ */
modn(b: number): number; //API consistency https://github.com/indutny/bn.js/pull/130 modn(b: number): BN;
/** /**
* @description rounded division * @description rounded division

View File

@ -16,9 +16,7 @@ describe('wallet reducer', () => {
expect(wallet(undefined, walletActions.setWallet(walletInstance))).toEqual({ expect(wallet(undefined, walletActions.setWallet(walletInstance))).toEqual({
...INITIAL_STATE, ...INITIAL_STATE,
inst: walletInstance, inst: walletInstance
balance: null,
tokens: {}
}); });
}); });