Enable no-implicit-any (#1263)
* Progress commit * Update more types * Fix more types * Fix abi function types * Fix lib types * Fix rest of types * Address wbobeirne changes * Change origin and destination check
This commit is contained in:
parent
0e26f7af4c
commit
c340246ca0
|
@ -29,7 +29,7 @@ export function loadBityRatesSucceededSwap(
|
||||||
|
|
||||||
export type TLoadShapeshiftRatesSucceededSwap = typeof loadShapeshiftRatesSucceededSwap;
|
export type TLoadShapeshiftRatesSucceededSwap = typeof loadShapeshiftRatesSucceededSwap;
|
||||||
export function loadShapeshiftRatesSucceededSwap(
|
export function loadShapeshiftRatesSucceededSwap(
|
||||||
payload
|
payload: interfaces.LoadShapeshiftRatesSucceededSwapAction['payload']
|
||||||
): interfaces.LoadShapeshiftRatesSucceededSwapAction {
|
): interfaces.LoadShapeshiftRatesSucceededSwapAction {
|
||||||
return {
|
return {
|
||||||
type: TypeKeys.SWAP_LOAD_SHAPESHIFT_RATES_SUCCEEDED,
|
type: TypeKeys.SWAP_LOAD_SHAPESHIFT_RATES_SUCCEEDED,
|
||||||
|
|
|
@ -29,10 +29,14 @@ const repOptions = {
|
||||||
name: 'Augur'
|
name: 'Augur'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface MappedRates {
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
export function getAllRates() {
|
export function getAllRates() {
|
||||||
const mappedRates = {};
|
const mappedRates: MappedRates = {};
|
||||||
return _getAllRates().then(bityRates => {
|
return _getAllRates().then(bityRates => {
|
||||||
bityRates.objects.forEach(each => {
|
bityRates.objects.forEach((each: any) => {
|
||||||
const pairName = each.pair;
|
const pairName = each.pair;
|
||||||
const from = { id: pairName.substring(0, 3) };
|
const from = { id: pairName.substring(0, 3) };
|
||||||
const to = { id: pairName.substring(3, 6) };
|
const to = { id: pairName.substring(3, 6) };
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { checkHttpStatus, parseJSON } from './utils';
|
import { checkHttpStatus, parseJSON } from './utils';
|
||||||
|
import { Omit } from 'react-redux';
|
||||||
|
|
||||||
const MAX_GAS_FAST = 250;
|
const MAX_GAS_FAST = 250;
|
||||||
|
|
||||||
|
@ -21,15 +22,29 @@ export interface GasEstimates {
|
||||||
isDefault: boolean;
|
isDefault: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GasExpressResponse {
|
||||||
|
block_time: number;
|
||||||
|
blockNum: number;
|
||||||
|
fast: number;
|
||||||
|
fastest: number;
|
||||||
|
safeLow: number;
|
||||||
|
standard: number;
|
||||||
|
}
|
||||||
|
|
||||||
export function fetchGasEstimates(): Promise<GasEstimates> {
|
export function fetchGasEstimates(): Promise<GasEstimates> {
|
||||||
return fetch('https://dev.blockscale.net/api/gasexpress.json', {
|
return fetch('https://dev.blockscale.net/api/gasexpress.json', {
|
||||||
mode: 'cors'
|
mode: 'cors'
|
||||||
})
|
})
|
||||||
.then(checkHttpStatus)
|
.then(checkHttpStatus)
|
||||||
.then(parseJSON)
|
.then(parseJSON)
|
||||||
.then((res: object) => {
|
.then((res: GasExpressResponse) => {
|
||||||
// Make sure it looks like a raw gas estimate, and it has valid values
|
// Make sure it looks like a raw gas estimate, and it has valid values
|
||||||
const keys = ['safeLow', 'standard', 'fast', 'fastest'];
|
const keys: (keyof Omit<GasExpressResponse, 'block_time' | 'blockNum'>)[] = [
|
||||||
|
'safeLow',
|
||||||
|
'standard',
|
||||||
|
'fast',
|
||||||
|
'fastest'
|
||||||
|
];
|
||||||
keys.forEach(key => {
|
keys.forEach(key => {
|
||||||
if (typeof res[key] !== 'number') {
|
if (typeof res[key] !== 'number') {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|
|
@ -28,6 +28,44 @@ export const SHAPESHIFT_TOKEN_WHITELIST = [
|
||||||
];
|
];
|
||||||
export const SHAPESHIFT_WHITELIST = [...SHAPESHIFT_TOKEN_WHITELIST, 'ETH', 'ETC', 'BTC'];
|
export const SHAPESHIFT_WHITELIST = [...SHAPESHIFT_TOKEN_WHITELIST, 'ETH', 'ETC', 'BTC'];
|
||||||
|
|
||||||
|
interface IPairData {
|
||||||
|
limit: number;
|
||||||
|
maxLimit: number;
|
||||||
|
min: number;
|
||||||
|
minerFee: number;
|
||||||
|
pair: string;
|
||||||
|
rate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IExtraPairData {
|
||||||
|
status: string;
|
||||||
|
image: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IAvailablePairData {
|
||||||
|
[pairName: string]: IExtraPairData;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ShapeshiftMarketInfo {
|
||||||
|
rate: string;
|
||||||
|
limit: number;
|
||||||
|
pair: string;
|
||||||
|
maxLimit: number;
|
||||||
|
min: number;
|
||||||
|
minerFee: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TokenMap {
|
||||||
|
[pairName: string]: {
|
||||||
|
id: string;
|
||||||
|
rate: string;
|
||||||
|
limit: number;
|
||||||
|
min: number;
|
||||||
|
options: (IExtraPairData & { id: string })[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
class ShapeshiftService {
|
class ShapeshiftService {
|
||||||
public whitelist = SHAPESHIFT_WHITELIST;
|
public whitelist = SHAPESHIFT_WHITELIST;
|
||||||
private url = SHAPESHIFT_BASE_URL;
|
private url = SHAPESHIFT_BASE_URL;
|
||||||
|
@ -36,13 +74,18 @@ class ShapeshiftService {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
};
|
};
|
||||||
|
|
||||||
public checkStatus(address) {
|
public checkStatus(address: string) {
|
||||||
return fetch(`${this.url}/txStat/${address}`)
|
return fetch(`${this.url}/txStat/${address}`)
|
||||||
.then(checkHttpStatus)
|
.then(checkHttpStatus)
|
||||||
.then(parseJSON);
|
.then(parseJSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sendAmount(withdrawal, originKind, destinationKind, destinationAmount) {
|
public sendAmount(
|
||||||
|
withdrawal: string,
|
||||||
|
originKind: string,
|
||||||
|
destinationKind: string,
|
||||||
|
destinationAmount: number
|
||||||
|
) {
|
||||||
const pair = `${originKind.toLowerCase()}_${destinationKind.toLowerCase()}`;
|
const pair = `${originKind.toLowerCase()}_${destinationKind.toLowerCase()}`;
|
||||||
|
|
||||||
return fetch(`${this.url}/sendamount`, {
|
return fetch(`${this.url}/sendamount`, {
|
||||||
|
@ -81,7 +124,7 @@ class ShapeshiftService {
|
||||||
return mappedRates;
|
return mappedRates;
|
||||||
};
|
};
|
||||||
|
|
||||||
private getPairRates(marketInfo) {
|
private getPairRates(marketInfo: ShapeshiftMarketInfo[]) {
|
||||||
const filteredMarketInfo = marketInfo.filter(obj => {
|
const filteredMarketInfo = marketInfo.filter(obj => {
|
||||||
const { pair } = obj;
|
const { pair } = obj;
|
||||||
const pairArr = pair.split('_');
|
const pairArr = pair.split('_');
|
||||||
|
@ -97,7 +140,7 @@ class ShapeshiftService {
|
||||||
return pairRates;
|
return pairRates;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async checkAvl(pairRates) {
|
private async checkAvl(pairRates: IPairData[]) {
|
||||||
const avlCoins = await this.getAvlCoins();
|
const avlCoins = await this.getAvlCoins();
|
||||||
const mapAvl = pairRates.map(p => {
|
const mapAvl = pairRates.map(p => {
|
||||||
const { pair } = p;
|
const { pair } = p;
|
||||||
|
@ -121,7 +164,8 @@ class ShapeshiftService {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return mapAvl;
|
const filered = mapAvl.filter(v => v);
|
||||||
|
return filered as (IPairData & IAvailablePairData)[];
|
||||||
}
|
}
|
||||||
|
|
||||||
private getAvlCoins() {
|
private getAvlCoins() {
|
||||||
|
@ -130,7 +174,7 @@ class ShapeshiftService {
|
||||||
.then(parseJSON);
|
.then(parseJSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getSinglePairRate(pair) {
|
private getSinglePairRate(pair: string) {
|
||||||
return fetch(`${this.url}/rate/${pair}`)
|
return fetch(`${this.url}/rate/${pair}`)
|
||||||
.then(checkHttpStatus)
|
.then(checkHttpStatus)
|
||||||
.then(parseJSON);
|
.then(parseJSON);
|
||||||
|
@ -142,12 +186,12 @@ class ShapeshiftService {
|
||||||
.then(parseJSON);
|
.then(parseJSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
private isWhitelisted(coin) {
|
private isWhitelisted(coin: string) {
|
||||||
return this.whitelist.includes(coin);
|
return this.whitelist.includes(coin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private mapMarketInfo(marketInfo) {
|
private mapMarketInfo(marketInfo: (IPairData & IAvailablePairData)[]) {
|
||||||
const tokenMap = {};
|
const tokenMap: TokenMap = {};
|
||||||
marketInfo.forEach(m => {
|
marketInfo.forEach(m => {
|
||||||
const originKind = m.pair.substring(0, 3);
|
const originKind = m.pair.substring(0, 3);
|
||||||
const destinationKind = m.pair.substring(4, 7);
|
const destinationKind = m.pair.substring(4, 7);
|
||||||
|
|
|
@ -37,5 +37,8 @@ export const AmountField: React.SFC<Props> = ({
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const isAmountValid = (raw, customValidator, isValid) =>
|
const isAmountValid = (
|
||||||
customValidator ? customValidator(raw) : isValid;
|
raw: string,
|
||||||
|
customValidator: ((rawAmount: string) => boolean) | undefined,
|
||||||
|
isValid: boolean
|
||||||
|
) => (customValidator ? customValidator(raw) : isValid);
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { chain, flatMap } from 'lodash';
|
||||||
import { TokenBalance, getShownTokenBalances } from 'selectors/wallet';
|
import { TokenBalance, getShownTokenBalances } from 'selectors/wallet';
|
||||||
import { Balance } from 'libs/wallet';
|
import { Balance } from 'libs/wallet';
|
||||||
import './EquivalentValues.scss';
|
import './EquivalentValues.scss';
|
||||||
import { Wei } from 'libs/units';
|
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
import { getNetworkConfig, getOffline } from 'selectors/config';
|
import { getNetworkConfig, getOffline } from 'selectors/config';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
@ -16,6 +15,7 @@ import btcIco from 'assets/images/bitcoin.png';
|
||||||
import ethIco from 'assets/images/ether.png';
|
import ethIco from 'assets/images/ether.png';
|
||||||
import repIco from 'assets/images/augur.png';
|
import repIco from 'assets/images/augur.png';
|
||||||
import { NetworkConfig } from 'types/network';
|
import { NetworkConfig } from 'types/network';
|
||||||
|
import BN from 'bn.js';
|
||||||
|
|
||||||
interface AllValue {
|
interface AllValue {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
|
@ -51,6 +51,14 @@ interface DispatchProps {
|
||||||
fetchCCRates: TFetchCCRatesRequested;
|
fetchCCRates: TFetchCCRatesRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface FiatSymbols {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Rates {
|
||||||
|
[rate: string]: number;
|
||||||
|
}
|
||||||
|
|
||||||
type Props = StateProps & DispatchProps;
|
type Props = StateProps & DispatchProps;
|
||||||
|
|
||||||
class EquivalentValues extends React.Component<Props, State> {
|
class EquivalentValues extends React.Component<Props, State> {
|
||||||
|
@ -110,7 +118,7 @@ class EquivalentValues extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public selectOption = equivalentValues => {
|
public selectOption = (equivalentValues: Option) => {
|
||||||
this.setState({ equivalentValues });
|
this.setState({ equivalentValues });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -120,28 +128,38 @@ class EquivalentValues extends React.Component<Props, State> {
|
||||||
const isFetching =
|
const isFetching =
|
||||||
!balance || balance.isPending || !tokenBalances || Object.keys(rates).length === 0;
|
!balance || balance.isPending || !tokenBalances || Object.keys(rates).length === 0;
|
||||||
const pairRates = this.generateValues(equivalentValues.label, equivalentValues.value);
|
const pairRates = this.generateValues(equivalentValues.label, equivalentValues.value);
|
||||||
const fiatSymbols = {
|
const fiatSymbols: FiatSymbols = {
|
||||||
USD: '$',
|
USD: '$',
|
||||||
EUR: '€',
|
EUR: '€',
|
||||||
GBP: '£',
|
GBP: '£',
|
||||||
CHF: ' '
|
CHF: ' '
|
||||||
};
|
};
|
||||||
const coinAndTokenSymbols = {
|
const coinAndTokenSymbols: any = {
|
||||||
BTC: btcIco,
|
BTC: btcIco,
|
||||||
ETH: ethIco,
|
ETH: ethIco,
|
||||||
REP: repIco
|
REP: repIco
|
||||||
};
|
};
|
||||||
|
interface ValueProps {
|
||||||
|
className: string;
|
||||||
|
rate: string;
|
||||||
|
value: BN | null;
|
||||||
|
symbol?: string;
|
||||||
|
icon?: string;
|
||||||
|
key?: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
const Value = ({ className = '', rate, value, symbol = '', icon = '' }) => (
|
const Value = (props: ValueProps) => (
|
||||||
<div className={`EquivalentValues-values-currency ${className}`}>
|
<div className={`EquivalentValues-values-currency ${props.className}`}>
|
||||||
<img src={icon} />
|
<img src={props.icon} />
|
||||||
{!!symbol && <span className="EquivalentValues-values-currency-fiat-symbol">{symbol}</span>}
|
{!!props.symbol && (
|
||||||
<span className="EquivalentValues-values-currency-label">{rate}</span>{' '}
|
<span className="EquivalentValues-values-currency-fiat-symbol">{props.symbol}</span>
|
||||||
|
)}
|
||||||
|
<span className="EquivalentValues-values-currency-label">{props.rate}</span>{' '}
|
||||||
<span className="EquivalentValues-values-currency-value">
|
<span className="EquivalentValues-values-currency-value">
|
||||||
<UnitDisplay
|
<UnitDisplay
|
||||||
unit={'ether'}
|
unit={'ether'}
|
||||||
value={value}
|
value={props.value}
|
||||||
displayShortBalance={rateSymbols.isFiat(rate) ? 2 : 3}
|
displayShortBalance={rateSymbols.isFiat(props.rate) ? 2 : 3}
|
||||||
checkOffline={true}
|
checkOffline={true}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
@ -157,7 +175,7 @@ class EquivalentValues extends React.Component<Props, State> {
|
||||||
// TODO: Update type
|
// TODO: Update type
|
||||||
value={equivalentValues as any}
|
value={equivalentValues as any}
|
||||||
options={options as any}
|
options={options as any}
|
||||||
onChange={this.selectOption}
|
onChange={this.selectOption as any}
|
||||||
clearable={false}
|
clearable={false}
|
||||||
searchable={false}
|
searchable={false}
|
||||||
/>
|
/>
|
||||||
|
@ -224,7 +242,7 @@ class EquivalentValues extends React.Component<Props, State> {
|
||||||
const allRates = Object.values(balance).map(
|
const allRates = Object.values(balance).map(
|
||||||
value => !!rates[value.symbol] && rates[value.symbol]
|
value => !!rates[value.symbol] && rates[value.symbol]
|
||||||
);
|
);
|
||||||
const allEquivalentValues = allRates.map((rateType, i) => {
|
const allEquivalentValues = allRates.map((rateType: any, i) => {
|
||||||
return {
|
return {
|
||||||
symbol: Object.keys(rates)[i],
|
symbol: Object.keys(rates)[i],
|
||||||
equivalentValues: [
|
equivalentValues: [
|
||||||
|
@ -260,9 +278,9 @@ class EquivalentValues extends React.Component<Props, State> {
|
||||||
// return equivalent value (unit * rate * balance)
|
// return equivalent value (unit * rate * balance)
|
||||||
private handleValues(unit: string, balance: Balance['wei']) {
|
private handleValues(unit: string, balance: Balance['wei']) {
|
||||||
const { rates } = this.props;
|
const { rates } = this.props;
|
||||||
const ratesObj = { ...rates[unit] };
|
const ratesObj: Rates = { ...rates[unit] };
|
||||||
return Object.keys(ratesObj).map(key => {
|
return Object.keys(ratesObj).map(key => {
|
||||||
const value = (balance as Wei).muln(ratesObj[key]);
|
const value = balance!.muln(ratesObj[key]);
|
||||||
return { rate: key, value };
|
return { rate: key, value };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import './Promos.scss';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { AppState } from '../../reducers';
|
import { AppState } from '../../reducers';
|
||||||
|
|
||||||
const CarouselAnimation = ({ children, ...props }) => (
|
const CarouselAnimation = ({ children, ...props }: any) => (
|
||||||
<CSSTransition {...props} timeout={300} classNames="carousel">
|
<CSSTransition {...props} timeout={300} classNames="carousel">
|
||||||
{children}
|
{children}
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
|
|
|
@ -15,19 +15,23 @@ interface Props {
|
||||||
onRemoveCustomToken(symbol: string): any;
|
onRemoveCustomToken(symbol: string): any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface TrackedTokens {
|
||||||
|
[symbol: string]: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
trackedTokens: { [symbol: string]: boolean };
|
trackedTokens: { [symbol: string]: boolean };
|
||||||
showCustomTokenForm: boolean;
|
showCustomTokenForm: boolean;
|
||||||
}
|
}
|
||||||
export default class TokenBalances extends React.PureComponent<Props, State> {
|
export default class TokenBalances extends React.PureComponent<Props, State> {
|
||||||
public state = {
|
public state: State = {
|
||||||
trackedTokens: {},
|
trackedTokens: {},
|
||||||
showCustomTokenForm: false
|
showCustomTokenForm: false
|
||||||
};
|
};
|
||||||
|
|
||||||
public componentWillReceiveProps(nextProps: Props) {
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
if (nextProps.tokenBalances !== this.props.tokenBalances) {
|
if (nextProps.tokenBalances !== this.props.tokenBalances) {
|
||||||
const trackedTokens = nextProps.tokenBalances.reduce((prev, t) => {
|
const trackedTokens = nextProps.tokenBalances.reduce<TrackedTokens>((prev, t) => {
|
||||||
prev[t.symbol] = !t.balance.isZero();
|
prev[t.symbol] = !t.balance.isZero();
|
||||||
return prev;
|
return prev;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
|
@ -13,7 +13,7 @@ interface StateProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
withProps(props: CallBackProps);
|
withProps(props: CallBackProps): null | React.ReactElement<any>;
|
||||||
onChange(value: React.FormEvent<HTMLInputElement>): void;
|
onChange(value: React.FormEvent<HTMLInputElement>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,9 @@ export default class GenerateKeystoreModal extends React.Component<Props, State>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillReceiveProps(nextProps) {
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
if (nextProps.privateKey !== this.props.privateKey) {
|
if (nextProps.privateKey !== this.props.privateKey) {
|
||||||
this.setState({ privateKey: nextProps.privateKey });
|
this.setState({ privateKey: nextProps.privateKey || '' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { Input } from 'components/ui';
|
||||||
const CUSTOM = 'custom';
|
const CUSTOM = 'custom';
|
||||||
|
|
||||||
interface InputProps {
|
interface InputProps {
|
||||||
name: string;
|
name: keyof Omit<State, 'hasAuth'>;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
type?: string;
|
type?: string;
|
||||||
autoComplete?: 'off';
|
autoComplete?: 'off';
|
||||||
|
|
|
@ -18,7 +18,7 @@ interface State {
|
||||||
}
|
}
|
||||||
|
|
||||||
class LogOutPromptClass extends React.Component<Props, State> {
|
class LogOutPromptClass extends React.Component<Props, State> {
|
||||||
constructor(props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
nextLocation: null,
|
nextLocation: null,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Slider from 'rc-slider';
|
import Slider, { createSliderWithTooltip } from 'rc-slider';
|
||||||
import translate, { translateRaw } from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import FeeSummary from './FeeSummary';
|
import FeeSummary from './FeeSummary';
|
||||||
import './SimpleGas.scss';
|
import './SimpleGas.scss';
|
||||||
|
@ -16,12 +16,13 @@ import { getEstimates, getIsEstimating } from 'selectors/gas';
|
||||||
import { Wei, fromWei } from 'libs/units';
|
import { Wei, fromWei } from 'libs/units';
|
||||||
import { gasPriceDefaults } from 'config';
|
import { gasPriceDefaults } from 'config';
|
||||||
import { InlineSpinner } from 'components/ui/InlineSpinner';
|
import { InlineSpinner } from 'components/ui/InlineSpinner';
|
||||||
const SliderWithTooltip = Slider.createSliderWithTooltip(Slider);
|
import { TInputGasPrice } from 'actions/transaction';
|
||||||
|
const SliderWithTooltip = createSliderWithTooltip(Slider);
|
||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
gasPrice: AppState['transaction']['fields']['gasPrice'];
|
gasPrice: AppState['transaction']['fields']['gasPrice'];
|
||||||
inputGasPrice(rawGas: string);
|
setGasPrice: TInputGasPrice;
|
||||||
setGasPrice(rawGas: string);
|
inputGasPrice(rawGas: string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StateProps {
|
interface StateProps {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { connect } from 'react-redux';
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
import { getUnit } from 'selectors/transaction';
|
import { getUnit } from 'selectors/transaction';
|
||||||
import { getNetworkUnit } from 'selectors/config';
|
import { getNetworkUnit } from 'selectors/config';
|
||||||
|
import { Option } from 'react-select';
|
||||||
|
|
||||||
interface DispatchProps {
|
interface DispatchProps {
|
||||||
setUnitMeta: TSetUnitMeta;
|
setUnitMeta: TSetUnitMeta;
|
||||||
|
@ -41,7 +42,10 @@ class UnitDropdownClass extends Component<DispatchProps & StateProps> {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
private handleOnChange = unit => {
|
private handleOnChange = (unit: Option<string>) => {
|
||||||
|
if (!unit.value) {
|
||||||
|
throw Error('No unit value found');
|
||||||
|
}
|
||||||
this.props.setUnitMeta(unit.value);
|
this.props.setUnitMeta(unit.value);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ type InsecureWallets = { [key in InsecureWalletName]: InsecureWalletInfo };
|
||||||
type MiscWallet = { [key in MiscWalletName]: MiscWalletInfo };
|
type MiscWallet = { [key in MiscWalletName]: MiscWalletInfo };
|
||||||
type Wallets = SecureWallets & InsecureWallets & MiscWallet;
|
type Wallets = SecureWallets & InsecureWallets & MiscWallet;
|
||||||
|
|
||||||
const WEB3_TYPE: string | false =
|
const WEB3_TYPE: keyof typeof WEB3_TYPES | false =
|
||||||
(window as any).web3 && (window as any).web3.currentProvider.constructor.name;
|
(window as any).web3 && (window as any).web3.currentProvider.constructor.name;
|
||||||
|
|
||||||
const SECURE_WALLETS = Object.values(SecureWalletName);
|
const SECURE_WALLETS = Object.values(SecureWalletName);
|
||||||
|
|
|
@ -73,7 +73,7 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
|
||||||
this.getAddresses();
|
this.getAddresses();
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillReceiveProps(nextProps) {
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
const { publicKey, chainCode, seed, dPath } = this.props;
|
const { publicKey, chainCode, seed, dPath } = this.props;
|
||||||
if (
|
if (
|
||||||
nextProps.publicKey !== publicKey ||
|
nextProps.publicKey !== publicKey ||
|
||||||
|
@ -245,7 +245,7 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private selectAddress(selectedAddress, selectedAddrIndex) {
|
private selectAddress(selectedAddress: string, selectedAddrIndex: number) {
|
||||||
this.setState({ selectedAddress, selectedAddrIndex });
|
this.setState({ selectedAddress, selectedAddrIndex });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,7 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
|
||||||
showTip: false
|
showTip: false
|
||||||
});
|
});
|
||||||
|
|
||||||
ledger.comm_u2f.create_async().then(comm => {
|
ledger.comm_u2f.create_async().then((comm: any) => {
|
||||||
new ledger.eth(comm)
|
new ledger.eth(comm)
|
||||||
.getAddress_async(dPath, false, true)
|
.getAddress_async(dPath, false, true)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
@ -139,7 +139,7 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
|
||||||
isLoading: false
|
isLoading: false
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch((err: any) => {
|
||||||
if (err && err.metaData && err.metaData.code === 5) {
|
if (err && err.metaData && err.metaData.code === 5) {
|
||||||
this.showTip();
|
this.showTip();
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ class MnemonicDecryptClass extends PureComponent<Props, State> {
|
||||||
isValid={isValidMnemonic}
|
isValid={isValidMnemonic}
|
||||||
isTextareaWhenVisible={true}
|
isTextareaWhenVisible={true}
|
||||||
onChange={this.onMnemonicChange}
|
onChange={this.onMnemonicChange}
|
||||||
onEnter={isValidMnemonic && this.onDWModalOpen}
|
onEnter={isValidMnemonic ? this.onDWModalOpen : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
|
@ -134,7 +134,7 @@ class MnemonicDecryptClass extends PureComponent<Props, State> {
|
||||||
this.setState({ dPath });
|
this.setState({ dPath });
|
||||||
};
|
};
|
||||||
|
|
||||||
private handleUnlock = (address, index) => {
|
private handleUnlock = (address: string, index: number) => {
|
||||||
const { formattedPhrase, pass, dPath } = this.state;
|
const { formattedPhrase, pass, dPath } = this.state;
|
||||||
|
|
||||||
this.props.onUnlock({
|
this.props.onUnlock({
|
||||||
|
|
|
@ -108,7 +108,7 @@ class TrezorDecryptClass extends PureComponent<Props, State> {
|
||||||
|
|
||||||
(TrezorConnect as any).getXPubKey(
|
(TrezorConnect as any).getXPubKey(
|
||||||
dPath,
|
dPath,
|
||||||
res => {
|
(res: any) => {
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
this.setState({
|
this.setState({
|
||||||
dPath,
|
dPath,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Select, { ReactSelectProps } from 'react-select';
|
import Select, { ReactSelectProps, Option } from 'react-select';
|
||||||
|
|
||||||
interface Props extends ReactSelectProps {
|
interface Props extends ReactSelectProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -13,11 +13,11 @@ export default class Dropdown extends React.Component<Props> {
|
||||||
hasBlurred: false
|
hasBlurred: false
|
||||||
};
|
};
|
||||||
|
|
||||||
public handleChange = selectedOption => {
|
public handleChange = (selectedOption: Option) => {
|
||||||
this.setState({ selectedOption });
|
this.setState({ selectedOption });
|
||||||
};
|
};
|
||||||
|
|
||||||
public formatOptions = options => {
|
public formatOptions = (options: Option[]) => {
|
||||||
if (typeof options[0] === 'object') {
|
if (typeof options[0] === 'object') {
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ export default class Dropdown extends React.Component<Props> {
|
||||||
// use ref to prevent <label /> from stealing focus when used inline with an input
|
// use ref to prevent <label /> from stealing focus when used inline with an input
|
||||||
ref={el => {
|
ref={el => {
|
||||||
if (!!el && !!(el as any).control) {
|
if (!!el && !!(el as any).control) {
|
||||||
(el as any).control.addEventListener('click', e => {
|
(el as any).control.addEventListener('click', (e: React.FormEvent<any>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ export default class Dropdown extends React.Component<Props> {
|
||||||
className={`${this.props.className} ${this.state.hasBlurred ? 'has-blurred' : ''}`}
|
className={`${this.props.className} ${this.state.hasBlurred ? 'has-blurred' : ''}`}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={obj => {
|
onChange={obj => {
|
||||||
this.handleChange(obj);
|
this.handleChange(obj as any);
|
||||||
onChange();
|
onChange();
|
||||||
}}
|
}}
|
||||||
{...this.props}
|
{...this.props}
|
||||||
|
@ -56,7 +56,7 @@ export default class Dropdown extends React.Component<Props> {
|
||||||
this.props.onBlur(e);
|
this.props.onBlur(e);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
options={options}
|
options={options as any}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ interface ModalStyle {
|
||||||
maxWidth?: string;
|
maxWidth?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Fade = ({ children, ...props }) => (
|
const Fade = ({ children, ...props }: any) => (
|
||||||
<CSSTransition {...props} timeout={300} classNames="animate-modal">
|
<CSSTransition {...props} timeout={300} classNames="animate-modal">
|
||||||
{children}
|
{children}
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
|
|
|
@ -64,8 +64,8 @@ export default class DropdownComponent<T> extends PureComponent<Props<T>, State>
|
||||||
overflowY: 'auto'
|
overflowY: 'auto'
|
||||||
};
|
};
|
||||||
const searchRegex = new RegExp(search, 'gi');
|
const searchRegex = new RegExp(search, 'gi');
|
||||||
const onSearchChange = e => {
|
const onSearchChange = (e: React.FormEvent<HTMLInputElement>) => {
|
||||||
this.setState({ search: e.target.value });
|
this.setState({ search: e.currentTarget.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -25,15 +25,15 @@ const ValueComp: React.SFC = (props: any) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const OptionComp: React.SFC = (props: any) => {
|
const OptionComp: React.SFC = (props: any) => {
|
||||||
const handleMouseDown = event => {
|
const handleMouseDown = (event: React.MouseEvent<any>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
props.onSelect(props.option, event);
|
props.onSelect(props.option, event);
|
||||||
};
|
};
|
||||||
const handleMouseEnter = event => {
|
const handleMouseEnter = (event: React.MouseEvent<any>) => {
|
||||||
props.onFocus(props.option, event);
|
props.onFocus(props.option, event);
|
||||||
};
|
};
|
||||||
const handleMouseMove = event => {
|
const handleMouseMove = (event: React.MouseEvent<any>) => {
|
||||||
if (props.isFocused) {
|
if (props.isFocused) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,11 @@ import { HELP_ARTICLE } from 'config';
|
||||||
import OnboardSlide from './OnboardSlide';
|
import OnboardSlide from './OnboardSlide';
|
||||||
import onboardIconTen from 'assets/images/onboarding/slide-10.svg';
|
import onboardIconTen from 'assets/images/onboarding/slide-10.svg';
|
||||||
|
|
||||||
const FinalSlide = ({ closeModal }) => {
|
interface Props {
|
||||||
|
closeModal(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
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');
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ interface Props {
|
||||||
class OnboardModal extends React.Component<Props, State> {
|
class OnboardModal extends React.Component<Props, State> {
|
||||||
private modal: Modal | null = null;
|
private modal: Modal | null = null;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
isOpen: false
|
isOpen: false
|
||||||
|
|
|
@ -36,7 +36,7 @@ interface State {
|
||||||
inputs: {
|
inputs: {
|
||||||
[key: string]: { rawData: string; parsedData: string[] | string };
|
[key: string]: { rawData: string; parsedData: string[] | string };
|
||||||
};
|
};
|
||||||
outputs;
|
outputs: any;
|
||||||
selectedFunction: null | ContractOption;
|
selectedFunction: null | ContractOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ class InteractExplorerClass extends Component<Props, State> {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{selectedFunction.contract.outputs.map((output, index) => {
|
{selectedFunction.contract.outputs.map((output: any, index: number) => {
|
||||||
const { type, name } = output;
|
const { type, name } = output;
|
||||||
const parsedName = name === '' ? index : name;
|
const parsedName = name === '' ? index : name;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ interface StateProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
accessContract(contractAbi: string, address: string): (ev) => void;
|
accessContract(contractAbi: string, address: string): (ev: any) => void;
|
||||||
resetState(): void;
|
resetState(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ const abiJsonPlaceholder = [
|
||||||
class InteractForm extends Component<Props, State> {
|
class InteractForm extends Component<Props, State> {
|
||||||
private abiJsonPlaceholder = JSON.stringify(abiJsonPlaceholder, null, 0);
|
private abiJsonPlaceholder = JSON.stringify(abiJsonPlaceholder, null, 0);
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
address: '',
|
address: '',
|
||||||
|
@ -140,7 +140,9 @@ class InteractForm extends Component<Props, State> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleInput = name => (ev: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
private handleInput = (name: any) => (
|
||||||
|
ev: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>
|
||||||
|
) => {
|
||||||
this.props.resetState();
|
this.props.resetState();
|
||||||
this.setState({ [name]: ev.currentTarget.value });
|
this.setState({ [name]: ev.currentTarget.value });
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +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';
|
||||||
const lookupLink = name => `https://etherscan.io/enslookup?q=${name}`;
|
const lookupLink = (name: string) => `https://etherscan.io/enslookup?q=${name}`;
|
||||||
|
|
||||||
type ChildrenProps = any;
|
type ChildrenProps = any;
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ class CountDown extends Component<Props, State> {
|
||||||
|
|
||||||
private startCountDown = () => {
|
private startCountDown = () => {
|
||||||
const time = moment(this.props.initialTime);
|
const time = moment(this.props.initialTime);
|
||||||
let intervalId;
|
let intervalId: number;
|
||||||
|
|
||||||
const setTimeDisplay = () => {
|
const setTimeDisplay = () => {
|
||||||
const diff = moment.duration(time.diff(moment()));
|
const diff = moment.duration(time.diff(moment()));
|
||||||
|
@ -44,7 +44,7 @@ class CountDown extends Component<Props, State> {
|
||||||
this.setState({ timeDisplay });
|
this.setState({ timeDisplay });
|
||||||
};
|
};
|
||||||
|
|
||||||
intervalId = setInterval(setTimeDisplay, 1000);
|
intervalId = window.setInterval(setTimeDisplay, 1000);
|
||||||
setTimeDisplay();
|
setTimeDisplay();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ const WalletTypes: React.SFC<{}> = () => {
|
||||||
|
|
||||||
<div className="WalletTypes-types row">
|
<div className="WalletTypes-types row">
|
||||||
<div className="col-md-1" />
|
<div className="col-md-1" />
|
||||||
{Object.keys(typeInfo).map(type => (
|
{Object.keys(typeInfo).map((type: keyof typeof typeInfo) => (
|
||||||
<div key={type} className="WalletType col-md-5">
|
<div key={type} className="WalletType col-md-5">
|
||||||
<h2 className="WalletType-title">{translate(typeInfo[type].name)}</h2>
|
<h2 className="WalletType-title">{translate(typeInfo[type].name)}</h2>
|
||||||
<ul className="WalletType-features">
|
<ul className="WalletType-features">
|
||||||
|
|
|
@ -44,7 +44,8 @@ interface ActionProps {
|
||||||
|
|
||||||
type Props = OwnProps & StateProps & ActionProps;
|
type Props = OwnProps & StateProps & ActionProps;
|
||||||
|
|
||||||
const isValidAmount = decimal => amount => validNumber(+amount) && validDecimal(amount, decimal);
|
const isValidAmount = (decimal: number) => (amount: string) =>
|
||||||
|
validNumber(+amount) && validDecimal(amount, decimal);
|
||||||
|
|
||||||
class RequestPayment extends React.Component<Props, {}> {
|
class RequestPayment extends React.Component<Props, {}> {
|
||||||
public state = {
|
public state = {
|
||||||
|
@ -145,7 +146,7 @@ class RequestPayment extends React.Component<Props, {}> {
|
||||||
private generateEIP681String(
|
private generateEIP681String(
|
||||||
currentTo: string,
|
currentTo: string,
|
||||||
tokenContractAddress: string,
|
tokenContractAddress: string,
|
||||||
currentValue,
|
currentValue: { raw: string; value: BN | null },
|
||||||
gasLimit: { raw: string; value: BN | null },
|
gasLimit: { raw: string; value: BN | null },
|
||||||
unit: string,
|
unit: string,
|
||||||
decimal: number,
|
decimal: number,
|
||||||
|
@ -162,7 +163,11 @@ class RequestPayment extends React.Component<Props, {}> {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.isNetworkUnit) {
|
const currentValueIsEther = (
|
||||||
|
_: AppState['transaction']['fields']['value'] | AppState['transaction']['meta']['tokenTo']
|
||||||
|
): _ is AppState['transaction']['fields']['value'] => this.props.isNetworkUnit;
|
||||||
|
|
||||||
|
if (currentValueIsEther(currentValue)) {
|
||||||
return buildEIP681EtherRequest(currentTo, chainId, currentValue);
|
return buildEIP681EtherRequest(currentTo, chainId, currentValue);
|
||||||
} else {
|
} else {
|
||||||
return buildEIP681TokenRequest(
|
return buildEIP681TokenRequest(
|
||||||
|
|
|
@ -30,8 +30,8 @@ export interface ActionProps {
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
origin: SwapInput;
|
origin: SwapOpt;
|
||||||
destination: SwapInput;
|
destination: SwapOpt;
|
||||||
originKindOptions: any[];
|
originKindOptions: any[];
|
||||||
destinationKindOptions: any[];
|
destinationKindOptions: any[];
|
||||||
originErr: string;
|
originErr: string;
|
||||||
|
@ -49,7 +49,7 @@ interface SwapOpt extends SwapInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class CurrencySwap extends PureComponent<Props, State> {
|
export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
public state = {
|
public state: State = {
|
||||||
disabled: true,
|
disabled: true,
|
||||||
origin: {
|
origin: {
|
||||||
label: 'BTC',
|
label: 'BTC',
|
||||||
|
@ -57,14 +57,14 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
status: 'available',
|
status: 'available',
|
||||||
image: 'https://shapeshift.io/images/coins/bitcoin.png',
|
image: 'https://shapeshift.io/images/coins/bitcoin.png',
|
||||||
amount: NaN
|
amount: NaN
|
||||||
} as SwapOpt,
|
},
|
||||||
destination: {
|
destination: {
|
||||||
label: 'ETH',
|
label: 'ETH',
|
||||||
value: 'Ether',
|
value: 'Ether',
|
||||||
status: 'available',
|
status: 'available',
|
||||||
image: 'https://shapeshift.io/images/coins/ether.png',
|
image: 'https://shapeshift.io/images/coins/ether.png',
|
||||||
amount: NaN
|
amount: NaN
|
||||||
} as SwapOpt,
|
},
|
||||||
originKindOptions: [],
|
originKindOptions: [],
|
||||||
destinationKindOptions: [],
|
destinationKindOptions: [],
|
||||||
originErr: '',
|
originErr: '',
|
||||||
|
@ -151,7 +151,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
return merge(shapeshiftRates, bityRates);
|
return merge(shapeshiftRates, bityRates);
|
||||||
};
|
};
|
||||||
|
|
||||||
public getMinMax = (originKind: WhitelistedCoins, destinationKind) => {
|
public getMinMax = (originKind: WhitelistedCoins, destinationKind: string) => {
|
||||||
let min;
|
let min;
|
||||||
let max;
|
let max;
|
||||||
|
|
||||||
|
@ -176,7 +176,11 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
return { min, max };
|
return { min, max };
|
||||||
};
|
};
|
||||||
|
|
||||||
public isMinMaxValid = (originAmount: number, originKind: WhitelistedCoins, destinationKind) => {
|
public isMinMaxValid = (
|
||||||
|
originAmount: number,
|
||||||
|
originKind: WhitelistedCoins,
|
||||||
|
destinationKind: string
|
||||||
|
) => {
|
||||||
const rate = this.getMinMax(originKind, destinationKind);
|
const rate = this.getMinMax(originKind, destinationKind);
|
||||||
const higherThanMin = originAmount >= rate.min;
|
const higherThanMin = originAmount >= rate.min;
|
||||||
const lowerThanMax = originAmount <= rate.max;
|
const lowerThanMax = originAmount <= rate.max;
|
||||||
|
@ -201,7 +205,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
this.debouncedCreateErrString(origin, destination, showError);
|
this.debouncedCreateErrString(origin, destination, showError);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setErrorMessages = (originErr, destinationErr) => {
|
public setErrorMessages = (originErr: string, destinationErr: string) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
originErr,
|
originErr,
|
||||||
destinationErr
|
destinationErr
|
||||||
|
@ -269,15 +273,17 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
: this.updateDestinationAmount(origin, destination, amount);
|
: this.updateDestinationAmount(origin, destination, amount);
|
||||||
};
|
};
|
||||||
|
|
||||||
public onChangeOriginKind = newOption => {
|
public onChangeOriginKind = (newOption: any) => {
|
||||||
const { origin, destination, destinationKindOptions } = this.state;
|
const { origin, destination, destinationKindOptions } = this.state;
|
||||||
const { options, initSwap } = this.props;
|
const { options, initSwap } = this.props;
|
||||||
|
|
||||||
const newOrigin = { ...origin, label: newOption.label, value: newOption.value, amount: '' };
|
const newOrigin = { ...origin, label: newOption.label, value: newOption.value, amount: 0 };
|
||||||
const newDest = {
|
const newDest = {
|
||||||
label: newOption.label === destination.label ? origin.label : destination.label,
|
label: newOption.label === destination.label ? origin.label : destination.label,
|
||||||
value: newOption.value === destination.value ? origin.value : destination.value,
|
value: newOption.value === destination.value ? origin.value : destination.value,
|
||||||
amount: ''
|
amount: 0,
|
||||||
|
status: '',
|
||||||
|
image: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -292,16 +298,16 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
initSwap({ origin: newOrigin, destination: newDest });
|
initSwap({ origin: newOrigin, destination: newDest });
|
||||||
};
|
};
|
||||||
|
|
||||||
public onChangeDestinationKind = newOption => {
|
public onChangeDestinationKind = (newOption: any) => {
|
||||||
const { initSwap } = this.props;
|
const { initSwap } = this.props;
|
||||||
const { origin, destination } = this.state;
|
const { origin, destination } = this.state;
|
||||||
|
|
||||||
const newOrigin = {
|
const newOrigin = {
|
||||||
...origin,
|
...origin,
|
||||||
amount: ''
|
amount: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
const newDest = { ...destination, label: newOption.label, value: newOption.value, amount: '' };
|
const newDest = { ...destination, label: newOption.label, value: newOption.value, amount: 0 };
|
||||||
this.setState({
|
this.setState({
|
||||||
origin: newOrigin,
|
origin: newOrigin,
|
||||||
destination: newDest
|
destination: newDest
|
||||||
|
@ -339,7 +345,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
<Input
|
<Input
|
||||||
id="origin-swap-input"
|
id="origin-swap-input"
|
||||||
className={`input-group-input ${
|
className={`input-group-input ${
|
||||||
String(origin.amount) !== '' &&
|
!origin.amount &&
|
||||||
this.isMinMaxValid(origin.amount, origin.label, destination.label)
|
this.isMinMaxValid(origin.amount, origin.label, destination.label)
|
||||||
? ''
|
? ''
|
||||||
: 'invalid'
|
: 'invalid'
|
||||||
|
@ -364,7 +370,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
||||||
<Input
|
<Input
|
||||||
id="destination-swap-input"
|
id="destination-swap-input"
|
||||||
className={`${
|
className={`${
|
||||||
String(destination.amount) !== '' &&
|
!destination.amount &&
|
||||||
this.isMinMaxValid(origin.amount, origin.label, destination.label)
|
this.isMinMaxValid(origin.amount, origin.label, destination.label)
|
||||||
? ''
|
? ''
|
||||||
: 'invalid'
|
: 'invalid'
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { getOffline } from 'selectors/config';
|
||||||
import Rates from './Rates';
|
import Rates from './Rates';
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
import './CurrentRates.scss';
|
import './CurrentRates.scss';
|
||||||
|
import { Optional } from 'utils/types';
|
||||||
|
|
||||||
interface StateProps {
|
interface StateProps {
|
||||||
isOffline: boolean;
|
isOffline: boolean;
|
||||||
|
@ -40,7 +41,7 @@ interface ActionProps {
|
||||||
type Props = StateProps & ActionProps;
|
type Props = StateProps & ActionProps;
|
||||||
|
|
||||||
class CurrentRates extends PureComponent<Props> {
|
class CurrentRates extends PureComponent<Props> {
|
||||||
private shapeShiftRateCache = null;
|
private shapeShiftRateCache: any = null;
|
||||||
|
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
if (!this.props.isOffline) {
|
if (!this.props.isOffline) {
|
||||||
|
@ -79,7 +80,7 @@ class CurrentRates extends PureComponent<Props> {
|
||||||
|
|
||||||
public buildSSPairs = (shapeshiftRates: NormalizedShapeshiftRates, n: number = 4) => {
|
public buildSSPairs = (shapeshiftRates: NormalizedShapeshiftRates, n: number = 4) => {
|
||||||
const pairCollection = times(n, () => this.getRandomSSPairData(shapeshiftRates));
|
const pairCollection = times(n, () => this.getRandomSSPairData(shapeshiftRates));
|
||||||
const byId = pairCollection.reduce((acc, cur) => {
|
const byId = pairCollection.reduce<{ [id: string]: NormalizedShapeshiftRate }>((acc, cur) => {
|
||||||
acc[cur.id] = cur;
|
acc[cur.id] = cur;
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
@ -90,7 +91,7 @@ class CurrentRates extends PureComponent<Props> {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
public isValidRates = rates => {
|
public isValidRates = (rates: Optional<NormalizedShapeshiftRates>) => {
|
||||||
return rates && rates.allIds && rates.allIds.length > 0;
|
return rates && rates.allIds && rates.allIds.length > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,7 +119,7 @@ class CurrentRates extends PureComponent<Props> {
|
||||||
return fixedRates;
|
return fixedRates;
|
||||||
};
|
};
|
||||||
|
|
||||||
public swapEl = (providerURL, providerLogo, children) => {
|
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>
|
||||||
|
|
|
@ -47,7 +47,7 @@ interface State {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Rates extends Component<Props, State> {
|
export default class Rates extends Component<Props, State> {
|
||||||
public state = {
|
public state: State = {
|
||||||
pairs: {}
|
pairs: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ export default class Rates extends Component<Props, State> {
|
||||||
public getPairs = () => {
|
public getPairs = () => {
|
||||||
const { rates } = this.props;
|
const { rates } = this.props;
|
||||||
const { allIds } = rates;
|
const { allIds } = rates;
|
||||||
return allIds.reduce((acc, cur) => {
|
return allIds.reduce<{ [id: string]: 1 }>((acc, cur) => {
|
||||||
acc[cur] = 1;
|
acc[cur] = 1;
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
import abi from 'ethereumjs-abi';
|
import abi from 'ethereumjs-abi';
|
||||||
import { toChecksumAddress, addHexPrefix } from 'ethereumjs-util';
|
import { toChecksumAddress, addHexPrefix } from 'ethereumjs-util';
|
||||||
import BN from 'bn.js';
|
import BN from 'bn.js';
|
||||||
import { FuncParams, FunctionOutputMappings, Output, Input } from './types';
|
import {
|
||||||
|
FuncParams,
|
||||||
|
FunctionOutputMappings,
|
||||||
|
Output,
|
||||||
|
Input,
|
||||||
|
ITypeMapping,
|
||||||
|
ISuppliedArgs
|
||||||
|
} from './types';
|
||||||
|
|
||||||
export default class AbiFunction {
|
export default class AbiFunction {
|
||||||
public constant: boolean;
|
public constant: boolean;
|
||||||
|
@ -53,7 +60,6 @@ export default class AbiFunction {
|
||||||
|
|
||||||
// Convert argdata to a hex buffer for ethereumjs-abi
|
// Convert argdata to a hex buffer for ethereumjs-abi
|
||||||
const argBuffer = new Buffer(argString, 'hex');
|
const argBuffer = new Buffer(argString, 'hex');
|
||||||
|
|
||||||
// Decode!
|
// Decode!
|
||||||
const argArr = abi.rawDecode(this.outputTypes, argBuffer);
|
const argArr = abi.rawDecode(this.outputTypes, argBuffer);
|
||||||
|
|
||||||
|
@ -80,13 +86,13 @@ export default class AbiFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private parsePostDecodedValue = (type: string, value: any) => {
|
private parsePostDecodedValue = (type: string, value: any) => {
|
||||||
const valueMapping = {
|
const valueMapping: ITypeMapping = {
|
||||||
address: val => toChecksumAddress(val.toString(16))
|
address: (val: any) => toChecksumAddress(val.toString(16))
|
||||||
};
|
};
|
||||||
|
|
||||||
return valueMapping[type]
|
const mapppedType = valueMapping[type];
|
||||||
? valueMapping[type](value)
|
|
||||||
: BN.isBN(value) ? value.toString() : value;
|
return mapppedType ? mapppedType(value) : BN.isBN(value) ? value.toString() : value;
|
||||||
};
|
};
|
||||||
|
|
||||||
private parsePreEncodedValue = (_: string, value: any) =>
|
private parsePreEncodedValue = (_: string, value: any) =>
|
||||||
|
@ -95,7 +101,7 @@ export default class AbiFunction {
|
||||||
private makeFuncParams = () =>
|
private makeFuncParams = () =>
|
||||||
this.inputs.reduce((accumulator, currInput) => {
|
this.inputs.reduce((accumulator, currInput) => {
|
||||||
const { name, type } = currInput;
|
const { name, type } = currInput;
|
||||||
const inputHandler = inputToParse =>
|
const inputHandler = (inputToParse: any) =>
|
||||||
//TODO: introduce typechecking and typecasting mapping for inputs
|
//TODO: introduce typechecking and typecasting mapping for inputs
|
||||||
({ name, type, value: this.parsePreEncodedValue(type, inputToParse) });
|
({ name, type, value: this.parsePreEncodedValue(type, inputToParse) });
|
||||||
|
|
||||||
|
@ -110,7 +116,7 @@ export default class AbiFunction {
|
||||||
return addHexPrefix(`${this.methodSelector}${encodedArgs}`);
|
return addHexPrefix(`${this.methodSelector}${encodedArgs}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
private processSuppliedArgs = (suppliedArgs: object) =>
|
private processSuppliedArgs = (suppliedArgs: ISuppliedArgs) =>
|
||||||
this.inputNames.map(name => {
|
this.inputNames.map(name => {
|
||||||
const type = this.funcParams[name].type;
|
const type = this.funcParams[name].type;
|
||||||
//TODO: parse args based on type
|
//TODO: parse args based on type
|
||||||
|
|
|
@ -6,6 +6,11 @@ const ABIFUNC_METHOD_NAMES = ['encodeInput', 'decodeInput', 'decodeOutput'];
|
||||||
enum ABIMethodTypes {
|
enum ABIMethodTypes {
|
||||||
FUNC = 'function'
|
FUNC = 'function'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default interface Contract {
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
|
||||||
export type TContract = typeof Contract;
|
export type TContract = typeof Contract;
|
||||||
|
|
||||||
export default class Contract {
|
export default class Contract {
|
||||||
|
@ -22,14 +27,14 @@ export default class Contract {
|
||||||
return isFunc ? { ...accu, [currContractMethodName]: currContractMethod } : accu;
|
return isFunc ? { ...accu, [currContractMethodName]: currContractMethod } : accu;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
public abi;
|
public abi: any;
|
||||||
|
|
||||||
constructor(abi, outputMappings: ContractOutputMappings = {}) {
|
constructor(abi: any, outputMappings: ContractOutputMappings = {}) {
|
||||||
this.assignABIFuncs(abi, outputMappings);
|
this.assignABIFuncs(abi, outputMappings);
|
||||||
}
|
}
|
||||||
|
|
||||||
private assignABIFuncs = (abi, outputMappings: ContractOutputMappings) => {
|
private assignABIFuncs = (abi: any, outputMappings: ContractOutputMappings) => {
|
||||||
abi.forEach(currentABIMethod => {
|
abi.forEach((currentABIMethod: any) => {
|
||||||
const { name, type } = currentABIMethod;
|
const { name, type } = currentABIMethod;
|
||||||
if (type === ABIMethodTypes.FUNC) {
|
if (type === ABIMethodTypes.FUNC) {
|
||||||
//only grab the functions we need
|
//only grab the functions we need
|
||||||
|
|
|
@ -36,3 +36,11 @@ export interface FuncParams {
|
||||||
processInput(value: any): any;
|
processInput(value: any): any;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ITypeMapping {
|
||||||
|
[type: string]: (value: any) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISuppliedArgs {
|
||||||
|
[argumentName: string]: any;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { mnemonicToSeed, validateMnemonic } from 'bip39';
|
import { mnemonicToSeed, validateMnemonic } from 'bip39';
|
||||||
import { createDecipheriv, createHash } from 'crypto';
|
import { createDecipheriv, createHash } from 'crypto';
|
||||||
import { privateToAddress } from 'ethereumjs-util';
|
import { privateToAddress } from 'ethereumjs-util';
|
||||||
import { fromMasterSeed } from 'hdkey';
|
import HDkey from 'hdkey';
|
||||||
import { stripHexPrefixAndLower } from 'libs/values';
|
import { stripHexPrefixAndLower } from 'libs/values';
|
||||||
|
|
||||||
// adapted from https://github.com/kvhnuke/etherwallet/blob/de536ffebb4f2d1af892a32697e89d1a0d906b01/app/scripts/myetherwallet.js#L230
|
// adapted from https://github.com/kvhnuke/etherwallet/blob/de536ffebb4f2d1af892a32697e89d1a0d906b01/app/scripts/myetherwallet.js#L230
|
||||||
|
@ -37,7 +37,7 @@ export function decodeCryptojsSalt(input: string): any {
|
||||||
export function evp_kdf(data: Buffer, salt: Buffer, opts: any) {
|
export function evp_kdf(data: Buffer, salt: Buffer, opts: any) {
|
||||||
// A single EVP iteration, returns `D_i`, where block equlas to `D_(i-1)`
|
// A single EVP iteration, returns `D_i`, where block equlas to `D_(i-1)`
|
||||||
|
|
||||||
function iter(block) {
|
function iter(block: Buffer) {
|
||||||
let hash = createHash(opts.digest || 'md5');
|
let hash = createHash(opts.digest || 'md5');
|
||||||
hash.update(block);
|
hash.update(block);
|
||||||
hash.update(data);
|
hash.update(data);
|
||||||
|
@ -83,7 +83,7 @@ export function decryptMnemonicToPrivKey(
|
||||||
}
|
}
|
||||||
|
|
||||||
const seed = mnemonicToSeed(phrase, pass);
|
const seed = mnemonicToSeed(phrase, pass);
|
||||||
const derived = fromMasterSeed(seed).derive(path);
|
const derived = HDkey.fromMasterSeed(seed).derive(path);
|
||||||
const dPrivKey = derived.privateKey;
|
const dPrivKey = derived.privateKey;
|
||||||
const dAddress = privateToAddress(dPrivKey).toString('hex');
|
const dAddress = privateToAddress(dPrivKey).toString('hex');
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import uts46 from 'idna-uts46';
|
import uts46 from 'idna-uts46';
|
||||||
import ethUtil from 'ethereumjs-util';
|
import ethUtil from 'ethereumjs-util';
|
||||||
|
|
||||||
export function normalise(name: string) {
|
export function normalise(name: string): string {
|
||||||
try {
|
try {
|
||||||
return uts46.toUnicode(name, { useStd3ASCII: true, transitional: false });
|
return uts46.toUnicode(name, { useStd3ASCII: true, transitional: false });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -65,7 +65,7 @@ export enum NameState {
|
||||||
NotYetAvailable = '5'
|
NotYetAvailable = '5'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const modeStrMap = name => [
|
export const modeStrMap = (name: string) => [
|
||||||
`${name} is available and the auction hasn’t started`,
|
`${name} is available and the auction hasn’t started`,
|
||||||
`${name} is available and the auction has been started`,
|
`${name} is available and the auction has been started`,
|
||||||
`${name} is taken and currently owned by someone`,
|
`${name} is taken and currently owned by someone`,
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
GetCurrentBlockRequest
|
GetCurrentBlockRequest
|
||||||
} from './types';
|
} from './types';
|
||||||
import { Token } from 'types/network';
|
import { Token } from 'types/network';
|
||||||
|
import { IHexStrWeb3Transaction, IHexStrTransaction } from 'libs/transaction';
|
||||||
|
|
||||||
export default class EtherscanRequests extends RPCRequests {
|
export default class EtherscanRequests extends RPCRequests {
|
||||||
public sendRawTx(signedTx: string): SendRawTxRequest {
|
public sendRawTx(signedTx: string): SendRawTxRequest {
|
||||||
|
@ -21,7 +22,7 @@ export default class EtherscanRequests extends RPCRequests {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public estimateGas(transaction): EstimateGasRequest {
|
public estimateGas(transaction: IHexStrWeb3Transaction): EstimateGasRequest {
|
||||||
return {
|
return {
|
||||||
module: 'proxy',
|
module: 'proxy',
|
||||||
action: 'eth_estimateGas',
|
action: 'eth_estimateGas',
|
||||||
|
@ -41,7 +42,7 @@ export default class EtherscanRequests extends RPCRequests {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public ethCall(transaction): CallRequest {
|
public ethCall(transaction: Pick<IHexStrTransaction, 'to' | 'data'>): CallRequest {
|
||||||
return {
|
return {
|
||||||
module: 'proxy',
|
module: 'proxy',
|
||||||
action: 'eth_call',
|
action: 'eth_call',
|
||||||
|
|
|
@ -41,10 +41,10 @@ export default class RPCClient {
|
||||||
}).then(r => r.json());
|
}).then(r => r.json());
|
||||||
};
|
};
|
||||||
|
|
||||||
private createHeaders = headerObject => {
|
private createHeaders = (headerObject: HeadersInit) => {
|
||||||
const headers = new Headers();
|
const headers = new Headers();
|
||||||
Object.keys(headerObject).forEach(name => {
|
Object.entries(headerObject).forEach(([name, value]) => {
|
||||||
headers.append(name, headerObject[name]);
|
headers.append(name, value);
|
||||||
});
|
});
|
||||||
return headers;
|
return headers;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,6 @@ import BN from 'bn.js';
|
||||||
import { IHexStrTransaction } from 'libs/transaction';
|
import { IHexStrTransaction } from 'libs/transaction';
|
||||||
import { Wei, TokenValue } from 'libs/units';
|
import { Wei, TokenValue } from 'libs/units';
|
||||||
import { stripHexPrefix } from 'libs/values';
|
import { stripHexPrefix } from 'libs/values';
|
||||||
import { hexToNumber } from 'utils/formatters';
|
|
||||||
import { INode, TxObj, TransactionData, TransactionReceipt } from '../INode';
|
import { INode, TxObj, TransactionData, TransactionReceipt } from '../INode';
|
||||||
import RPCClient from './client';
|
import RPCClient from './client';
|
||||||
import RPCRequests from './requests';
|
import RPCRequests from './requests';
|
||||||
|
@ -18,6 +17,7 @@ import {
|
||||||
isValidRawTxApi
|
isValidRawTxApi
|
||||||
} from 'libs/validators';
|
} from 'libs/validators';
|
||||||
import { Token } from 'types/network';
|
import { Token } from 'types/network';
|
||||||
|
import { hexToNumber } from 'utils/formatters';
|
||||||
|
|
||||||
export default class RpcNode implements INode {
|
export default class RpcNode implements INode {
|
||||||
public client: RPCClient;
|
public client: RPCClient;
|
||||||
|
|
|
@ -13,14 +13,13 @@ import {
|
||||||
import { hexEncodeData } from './utils';
|
import { hexEncodeData } from './utils';
|
||||||
import { TxObj } from '../INode';
|
import { TxObj } from '../INode';
|
||||||
import { Token } from 'types/network';
|
import { Token } from 'types/network';
|
||||||
|
import { IHexStrTransaction } from 'libs/transaction';
|
||||||
|
|
||||||
export default class RPCRequests {
|
export default class RPCRequests {
|
||||||
public getNetVersion() {
|
public getNetVersion() {
|
||||||
return { method: 'net_version' };
|
return { method: 'net_version' };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Fix `| any` on all of these */
|
|
||||||
|
|
||||||
public sendRawTx(signedTx: string): SendRawTxRequest | any {
|
public sendRawTx(signedTx: string): SendRawTxRequest | any {
|
||||||
return {
|
return {
|
||||||
method: 'eth_sendRawTransaction',
|
method: 'eth_sendRawTransaction',
|
||||||
|
@ -28,7 +27,7 @@ export default class RPCRequests {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public estimateGas(transaction): EstimateGasRequest | any {
|
public estimateGas(transaction: Partial<IHexStrTransaction>): EstimateGasRequest | any {
|
||||||
return {
|
return {
|
||||||
method: 'eth_estimateGas',
|
method: 'eth_estimateGas',
|
||||||
params: [transaction]
|
params: [transaction]
|
||||||
|
|
|
@ -27,7 +27,7 @@ export interface GetAccountsRequest extends RPCRequestBase {
|
||||||
method: 'eth_accounts';
|
method: 'eth_accounts';
|
||||||
}
|
}
|
||||||
|
|
||||||
type TWeb3ProviderCallback = (error, result: JsonRpcResponse | JsonRpcResponse[]) => any;
|
type TWeb3ProviderCallback = (error: string, result: JsonRpcResponse | JsonRpcResponse[]) => any;
|
||||||
type TSendAsync = (request: RPCRequest | any, callback: TWeb3ProviderCallback) => void;
|
type TSendAsync = (request: RPCRequest | any, callback: TWeb3ProviderCallback) => void;
|
||||||
|
|
||||||
export interface IWeb3Provider {
|
export interface IWeb3Provider {
|
||||||
|
|
|
@ -10,9 +10,9 @@ export interface ITransaction {
|
||||||
gasPrice: Wei;
|
gasPrice: Wei;
|
||||||
nonce: BN;
|
nonce: BN;
|
||||||
chainId: number;
|
chainId: number;
|
||||||
v;
|
v: Buffer;
|
||||||
r;
|
r: Buffer;
|
||||||
s;
|
s: Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IHexStrTransaction {
|
export interface IHexStrTransaction {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { IFullWallet } from 'libs/wallet';
|
||||||
import { translateRaw } from 'translations';
|
import { translateRaw } from 'translations';
|
||||||
import { ITransaction, IHexStrTransaction } from '../typings';
|
import { ITransaction, IHexStrTransaction } from '../typings';
|
||||||
import { hexEncodeQuantity, hexEncodeData } from 'libs/nodes/rpc/utils';
|
import { hexEncodeQuantity, hexEncodeData } from 'libs/nodes/rpc/utils';
|
||||||
|
import { TransactionFieldValues } from 'selectors/transaction/helpers';
|
||||||
|
|
||||||
// we dont include the signature paramaters because web3 transactions are unsigned
|
// we dont include the signature paramaters because web3 transactions are unsigned
|
||||||
const computeIndexingHash = (tx: Buffer) => bufferToHex(makeTransaction(tx).hash(false));
|
const computeIndexingHash = (tx: Buffer) => bufferToHex(makeTransaction(tx).hash(false));
|
||||||
|
@ -75,7 +76,13 @@ const validAddress = (t: ITransaction) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const makeTransaction = (
|
const makeTransaction = (
|
||||||
t: Partial<Tx> | Partial<ITransaction> | Partial<IHexStrTransaction> | Buffer | string
|
t:
|
||||||
|
| Partial<Tx>
|
||||||
|
| Partial<ITransaction>
|
||||||
|
| Partial<IHexStrTransaction>
|
||||||
|
| Buffer
|
||||||
|
| string
|
||||||
|
| TransactionFieldValues
|
||||||
) => new Tx(t);
|
) => new Tx(t);
|
||||||
|
|
||||||
//TODO: check that addresses are always checksummed
|
//TODO: check that addresses are always checksummed
|
||||||
|
|
|
@ -184,7 +184,7 @@ export const isValidNonce = (value: string): boolean => {
|
||||||
return valid;
|
return valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
function isValidResult(response: JsonRpcResponse, schemaFormat): boolean {
|
function isValidResult(response: JsonRpcResponse, schemaFormat: typeof schema.RpcNode): boolean {
|
||||||
return v.validate(response, schemaFormat).valid;
|
return v.validate(response, schemaFormat).valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,9 +204,25 @@ function formatErrors(response: JsonRpcResponse, apiType: string) {
|
||||||
return `Invalid ${apiType} Error`;
|
return `Invalid ${apiType} Error`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum API_NAME {
|
||||||
|
Get_Balance = 'Get Balance',
|
||||||
|
Estimate_Gas = 'Estimate Gas',
|
||||||
|
Call_Request = 'Call Request',
|
||||||
|
Token_Balance = 'Token Balance',
|
||||||
|
Transaction_Count = 'Transaction Count',
|
||||||
|
Current_Block = 'Current Block',
|
||||||
|
Raw_Tx = 'Raw Tx',
|
||||||
|
Send_Transaction = 'Send Transaction',
|
||||||
|
Sign_Message = 'Sign Message',
|
||||||
|
Get_Accounts = 'Get Accounts',
|
||||||
|
Net_Version = 'Net Version',
|
||||||
|
Transaction_By_Hash = 'Transaction By Hash',
|
||||||
|
Transaction_Receipt = 'Transaction Receipt'
|
||||||
|
}
|
||||||
|
|
||||||
const isValidEthCall = (response: JsonRpcResponse, schemaType: typeof schema.RpcNode) => (
|
const isValidEthCall = (response: JsonRpcResponse, schemaType: typeof schema.RpcNode) => (
|
||||||
apiName,
|
apiName: API_NAME,
|
||||||
cb?
|
cb?: (res: JsonRpcResponse) => any
|
||||||
) => {
|
) => {
|
||||||
if (!isValidResult(response, schemaType)) {
|
if (!isValidResult(response, schemaType)) {
|
||||||
if (cb) {
|
if (cb) {
|
||||||
|
@ -218,45 +234,44 @@ const isValidEthCall = (response: JsonRpcResponse, schemaType: typeof schema.Rpc
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isValidGetBalance = (response: JsonRpcResponse) =>
|
export const isValidGetBalance = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Get Balance');
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Get_Balance);
|
||||||
|
|
||||||
export const isValidEstimateGas = (response: JsonRpcResponse) =>
|
export const isValidEstimateGas = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Estimate Gas');
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Estimate_Gas);
|
||||||
|
|
||||||
export const isValidCallRequest = (response: JsonRpcResponse) =>
|
export const isValidCallRequest = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Call Request');
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Call_Request);
|
||||||
|
|
||||||
export const isValidTokenBalance = (response: JsonRpcResponse) =>
|
export const isValidTokenBalance = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Token Balance', () => ({
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Token_Balance, () => ({
|
||||||
result: 'Failed'
|
result: 'Failed'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const isValidTransactionCount = (response: JsonRpcResponse) =>
|
export const isValidTransactionCount = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Transaction Count');
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Transaction_Count);
|
||||||
|
|
||||||
export const isValidTransactionByHash = (response: JsonRpcResponse) =>
|
export const isValidTransactionByHash = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Transaction By Hash');
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Transaction_By_Hash);
|
||||||
|
|
||||||
export const isValidTransactionReceipt = (response: JsonRpcResponse) =>
|
export const isValidTransactionReceipt = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Transaction Receipt');
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Transaction_Receipt);
|
||||||
|
|
||||||
export const isValidCurrentBlock = (response: JsonRpcResponse) =>
|
export const isValidCurrentBlock = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Current Block');
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Current_Block);
|
||||||
|
|
||||||
export const isValidRawTxApi = (response: JsonRpcResponse) =>
|
export const isValidRawTxApi = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Raw Tx');
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Raw_Tx);
|
||||||
|
|
||||||
export const isValidSendTransaction = (response: JsonRpcResponse) =>
|
export const isValidSendTransaction = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Send Transaction');
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Send_Transaction);
|
||||||
|
|
||||||
export const isValidSignMessage = (response: JsonRpcResponse) =>
|
export const isValidSignMessage = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Sign Message');
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Sign_Message);
|
||||||
|
|
||||||
export const isValidGetAccounts = (response: JsonRpcResponse) =>
|
export const isValidGetAccounts = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Get Accounts');
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Get_Accounts);
|
||||||
|
|
||||||
export const isValidGetNetVersion = (response: JsonRpcResponse) =>
|
export const isValidGetNetVersion = (response: JsonRpcResponse) =>
|
||||||
isValidEthCall(response, schema.RpcNode)('Net Version');
|
isValidEthCall(response, schema.RpcNode)(API_NAME.Net_Version);
|
||||||
|
|
||||||
export const isValidTxHash = (hash: string) =>
|
export const isValidTxHash = (hash: string) =>
|
||||||
hash.substring(0, 2) === '0x' && hash.length === 66 && isValidHex(hash);
|
hash.substring(0, 2) === '0x' && hash.length === 66 && isValidHex(hash);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Wei, toTokenBase } from 'libs/units';
|
import { Wei, toTokenBase } from 'libs/units';
|
||||||
import { addHexPrefix } from 'ethereumjs-util';
|
import { addHexPrefix } from 'ethereumjs-util';
|
||||||
import BN from 'bn.js';
|
import { AppState } from 'reducers';
|
||||||
|
|
||||||
export function stripHexPrefix(value: string) {
|
export function stripHexPrefix(value: string) {
|
||||||
return value.replace('0x', '');
|
return value.replace('0x', '');
|
||||||
|
@ -26,16 +26,16 @@ export function sanitizeHex(hex: string) {
|
||||||
export const buildEIP681EtherRequest = (
|
export const buildEIP681EtherRequest = (
|
||||||
recipientAddr: string,
|
recipientAddr: string,
|
||||||
chainId: number,
|
chainId: number,
|
||||||
etherValue: { raw: string; value: Wei | '' }
|
etherValue: AppState['transaction']['fields']['value']
|
||||||
) => `ethereum:${recipientAddr}${chainId !== 1 ? `@${chainId}` : ''}?value=${etherValue.raw}e18`;
|
) => `ethereum:${recipientAddr}${chainId !== 1 ? `@${chainId}` : ''}?value=${etherValue.raw}e18`;
|
||||||
|
|
||||||
export const buildEIP681TokenRequest = (
|
export const buildEIP681TokenRequest = (
|
||||||
recipientAddr: string,
|
recipientAddr: string,
|
||||||
contractAddr: string,
|
contractAddr: string,
|
||||||
chainId: number,
|
chainId: number,
|
||||||
tokenValue: { raw: string; value: Wei | '' },
|
tokenValue: AppState['transaction']['meta']['tokenTo'],
|
||||||
decimal: number,
|
decimal: number,
|
||||||
gasLimit: { raw: string; value: BN | null }
|
gasLimit: AppState['transaction']['fields']['gasLimit']
|
||||||
) =>
|
) =>
|
||||||
`ethereum:${contractAddr}${
|
`ethereum:${contractAddr}${
|
||||||
chainId !== 1 ? `@${chainId}` : ''
|
chainId !== 1 ? `@${chainId}` : ''
|
||||||
|
|
|
@ -7,11 +7,11 @@ import { IFullWallet } from '../IWallet';
|
||||||
import { translateRaw } from 'translations';
|
import { translateRaw } from 'translations';
|
||||||
|
|
||||||
export class LedgerWallet extends DeterministicWallet implements IFullWallet {
|
export class LedgerWallet extends DeterministicWallet implements IFullWallet {
|
||||||
private ethApp: any;
|
private ethApp: ledger.eth;
|
||||||
|
|
||||||
constructor(address: string, dPath: string, index: number) {
|
constructor(address: string, dPath: string, index: number) {
|
||||||
super(address, dPath, index);
|
super(address, dPath, index);
|
||||||
ledger.comm_u2f.create_async().then(comm => {
|
ledger.comm_u2f.create_async().then((comm: any) => {
|
||||||
this.ethApp = new ledger.eth(comm);
|
this.ethApp = new ledger.eth(comm);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -50,9 +50,12 @@ export class LedgerWallet extends DeterministicWallet implements IFullWallet {
|
||||||
const msgHex = Buffer.from(msg).toString('hex');
|
const msgHex = Buffer.from(msg).toString('hex');
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.ethApp.signPersonalMessage_async(this.getPath(), msgHex, async (signed, error) => {
|
this.ethApp.signPersonalMessage_async(
|
||||||
|
this.getPath(),
|
||||||
|
msgHex,
|
||||||
|
async (signed: any, error: any) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
return reject(this.ethApp.getError(error));
|
return reject((this.ethApp as any).getError(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -61,7 +64,8 @@ export class LedgerWallet extends DeterministicWallet implements IFullWallet {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ export class TrezorWallet extends DeterministicWallet implements IFullWallet {
|
||||||
cleanedTx.data,
|
cleanedTx.data,
|
||||||
chainId,
|
chainId,
|
||||||
// Callback
|
// Callback
|
||||||
result => {
|
(result: any) => {
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
return reject(Error(result.error));
|
return reject(Error(result.error));
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ export class TrezorWallet extends DeterministicWallet implements IFullWallet {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
(TrezorConnect as any).ethereumGetAddress(
|
(TrezorConnect as any).ethereumGetAddress(
|
||||||
dPath + '/' + index,
|
dPath + '/' + index,
|
||||||
res => {
|
(res: any) => {
|
||||||
if (res.error) {
|
if (res.error) {
|
||||||
reject(res.error);
|
reject(res.error);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,9 +15,9 @@ const INITIAL_STATE: State = {
|
||||||
gasPriceStatus: null
|
gasPriceStatus: null
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPostFix = (str: string) => {
|
const getPostFix = (str: string): keyof typeof RequestStatus => {
|
||||||
const arr = str.split('_');
|
const arr = str.split('_');
|
||||||
return arr[arr.length - 1];
|
return arr[arr.length - 1] as any;
|
||||||
};
|
};
|
||||||
|
|
||||||
const nextState = (field: keyof State) => (state: State, action: Action): State => ({
|
const nextState = (field: keyof State) => (state: State, action: Action): State => ({
|
||||||
|
|
|
@ -22,14 +22,14 @@ export const resetHOF = (
|
||||||
|
|
||||||
if (includeFields) {
|
if (includeFields) {
|
||||||
(includeFields as any[]).forEach(fieldName => {
|
(includeFields as any[]).forEach(fieldName => {
|
||||||
stateCopy[fieldName] = returnState[fieldName];
|
(stateCopy as any)[fieldName] = (returnState as any)[fieldName];
|
||||||
});
|
});
|
||||||
return returnCb ? returnCb(state, returnState) : { ...stateCopy };
|
return returnCb ? returnCb(state, returnState) : { ...stateCopy };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (excludeFields) {
|
if (excludeFields) {
|
||||||
(excludeFields as any[]).forEach(fieldName => {
|
(excludeFields as any[]).forEach(fieldName => {
|
||||||
returnState[fieldName] = state[fieldName];
|
(returnState as any)[fieldName] = (state as any)[fieldName];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ export function* pruneCustomNetworks(): SagaIterator {
|
||||||
|
|
||||||
//construct lookup table of networks
|
//construct lookup table of networks
|
||||||
|
|
||||||
const linkedNetworks = Object.values(customNodes).reduce(
|
const linkedNetworks: { [key: string]: boolean } = Object.values(customNodes).reduce(
|
||||||
(networkMap, currentNode) => ({ ...networkMap, [currentNode.network]: true }),
|
(networkMap, currentNode) => ({ ...networkMap, [currentNode.network]: true }),
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { changeNodeForce, TypeKeys, web3SetNode } from 'actions/config';
|
||||||
import { getNodeId, getStaticAltNodeIdToWeb3, getNetworkNameByChainId } from 'selectors/config';
|
import { getNodeId, getStaticAltNodeIdToWeb3, getNetworkNameByChainId } from 'selectors/config';
|
||||||
import { setupWeb3Node, Web3Service } from 'libs/nodes/web3';
|
import { setupWeb3Node, Web3Service } from 'libs/nodes/web3';
|
||||||
import { Web3NodeConfig } from 'types/node';
|
import { Web3NodeConfig } from 'types/node';
|
||||||
|
import { SetWalletAction } from 'actions/wallet';
|
||||||
|
|
||||||
export function* initWeb3Node(): SagaIterator {
|
export function* initWeb3Node(): SagaIterator {
|
||||||
const { networkId, lib } = yield call(setupWeb3Node);
|
const { networkId, lib } = yield call(setupWeb3Node);
|
||||||
|
@ -24,7 +25,7 @@ export function* initWeb3Node(): SagaIterator {
|
||||||
}
|
}
|
||||||
|
|
||||||
// unset web3 as the selected node if a non-web3 wallet has been selected
|
// unset web3 as the selected node if a non-web3 wallet has been selected
|
||||||
export function* unsetWeb3NodeOnWalletEvent(action): SagaIterator {
|
export function* unsetWeb3NodeOnWalletEvent(action: SetWalletAction): SagaIterator {
|
||||||
const node = yield select(getNodeId);
|
const node = yield select(getNodeId);
|
||||||
const newWallet = action.payload;
|
const newWallet = action.payload;
|
||||||
const isWeb3Wallet = newWallet instanceof Web3Wallet;
|
const isWeb3Wallet = newWallet instanceof Web3Wallet;
|
||||||
|
@ -52,6 +53,5 @@ export function* unsetWeb3Node(): SagaIterator {
|
||||||
|
|
||||||
export const web3 = [
|
export const web3 = [
|
||||||
takeEvery(TypeKeys.CONFIG_NODE_WEB3_UNSET, unsetWeb3Node),
|
takeEvery(TypeKeys.CONFIG_NODE_WEB3_UNSET, unsetWeb3Node),
|
||||||
takeEvery(WalletTypeKeys.WALLET_SET, unsetWeb3NodeOnWalletEvent),
|
takeEvery(WalletTypeKeys.WALLET_SET, unsetWeb3NodeOnWalletEvent)
|
||||||
takeEvery(WalletTypeKeys.WALLET_RESET, unsetWeb3NodeOnWalletEvent)
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -96,7 +96,7 @@ export function* updateWalletTokenValues(): SagaIterator {
|
||||||
const calls = wallets.map(w => {
|
const calls = wallets.map(w => {
|
||||||
return apply(node, node.getTokenBalance, [w.address, token]);
|
return apply(node, node.getTokenBalance, [w.address, token]);
|
||||||
});
|
});
|
||||||
const tokenBalances: { balance: TokenValue; error: string | null } = yield all(calls);
|
const tokenBalances: { balance: TokenValue; error: string | null }[] = yield all(calls);
|
||||||
|
|
||||||
for (let i = 0; i < wallets.length; i++) {
|
for (let i = 0; i < wallets.length; i++) {
|
||||||
if (!tokenBalances[i].error) {
|
if (!tokenBalances[i].error) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ function* resolveDomain(): SagaIterator {
|
||||||
|
|
||||||
const node: INode = yield select(getNodeLib);
|
const node: INode = yield select(getNodeLib);
|
||||||
|
|
||||||
const result: { domainData: IBaseDomainRequest; error } = yield race({
|
const result: { domainData: IBaseDomainRequest; error: any } = yield race({
|
||||||
domainData: call(resolveDomainRequest, domain, node),
|
domainData: call(resolveDomainRequest, domain, node),
|
||||||
err: call(delay, 10000)
|
err: call(delay, 10000)
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,13 @@ import { INode } from 'libs/nodes/INode';
|
||||||
import { getNodeLib } from 'selectors/config';
|
import { getNodeLib } from 'selectors/config';
|
||||||
import { SagaIterator } from 'redux-saga';
|
import { SagaIterator } from 'redux-saga';
|
||||||
|
|
||||||
export function* makeEthCallAndDecode({ to, data, decoder }): SagaIterator {
|
interface Params {
|
||||||
|
to: any;
|
||||||
|
data: any;
|
||||||
|
decoder: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* makeEthCallAndDecode({ to, data, decoder }: Params): SagaIterator {
|
||||||
const node: INode = yield select(getNodeLib);
|
const node: INode = yield select(getNodeLib);
|
||||||
const result: string = yield apply(node, node.sendCallRequest, [{ data, to }]);
|
const result: string = yield apply(node, node.sendCallRequest, [{ data, to }]);
|
||||||
const decodedResult = yield call(decoder, result);
|
const decodedResult = yield call(decoder, result);
|
||||||
|
|
|
@ -8,7 +8,12 @@ import {
|
||||||
import { select, call, put, takeEvery } from 'redux-saga/effects';
|
import { select, call, put, takeEvery } from 'redux-saga/effects';
|
||||||
import { SagaIterator } from 'redux-saga';
|
import { SagaIterator } from 'redux-saga';
|
||||||
import { setTokenValue, setValueField } from 'actions/transaction/actionCreators';
|
import { setTokenValue, setValueField } from 'actions/transaction/actionCreators';
|
||||||
import { SetCurrentValueAction, TypeKeys } from 'actions/transaction';
|
import {
|
||||||
|
SetCurrentValueAction,
|
||||||
|
TypeKeys,
|
||||||
|
TSetValueField,
|
||||||
|
TSetTokenValue
|
||||||
|
} from 'actions/transaction';
|
||||||
import { toTokenBase } from 'libs/units';
|
import { toTokenBase } from 'libs/units';
|
||||||
import { validateInput, IInput } from 'sagas/transaction/validationHelpers';
|
import { validateInput, IInput } from 'sagas/transaction/validationHelpers';
|
||||||
import { validNumber, validDecimal } from 'libs/validators';
|
import { validNumber, validDecimal } from 'libs/validators';
|
||||||
|
@ -19,7 +24,10 @@ export function* setCurrentValue(action: SetCurrentValueAction): SagaIterator {
|
||||||
return yield call(valueHandler, action, setter);
|
return yield call(valueHandler, action, setter);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* valueHandler({ payload }: SetCurrentValueAction, setter) {
|
export function* valueHandler(
|
||||||
|
{ payload }: SetCurrentValueAction,
|
||||||
|
setter: TSetValueField | TSetTokenValue
|
||||||
|
) {
|
||||||
const decimal: number = yield select(getDecimal);
|
const decimal: number = yield select(getDecimal);
|
||||||
const unit: string = yield select(getUnit);
|
const unit: string = yield select(getUnit);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ export function* getTokenBalances(wallet: IWallet, tokens: Token[]) {
|
||||||
const node: INode = yield select(getNodeLib);
|
const node: INode = yield select(getNodeLib);
|
||||||
const address: string = yield apply(wallet, wallet.getAddressString);
|
const address: string = yield apply(wallet, wallet.getAddressString);
|
||||||
const tokenBalances: TokenBalance[] = yield apply(node, node.getTokenBalances, [address, tokens]);
|
const tokenBalances: TokenBalance[] = yield apply(node, node.getTokenBalances, [address, tokens]);
|
||||||
return tokens.reduce((acc, t, i) => {
|
return tokens.reduce<{ [TokenSymbol: string]: TokenBalance }>((acc, t, i) => {
|
||||||
acc[t.symbol] = tokenBalances[i];
|
acc[t.symbol] = tokenBalances[i];
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
|
@ -263,7 +263,7 @@ export function* unlockWeb3(): SagaIterator {
|
||||||
yield call(initWeb3Node);
|
yield call(initWeb3Node);
|
||||||
yield put(changeNodeIntent('web3'));
|
yield put(changeNodeIntent('web3'));
|
||||||
yield take(
|
yield take(
|
||||||
action =>
|
(action: any) =>
|
||||||
action.type === ConfigTypeKeys.CONFIG_NODE_CHANGE && action.payload.nodeId === 'web3'
|
action.type === ConfigTypeKeys.CONFIG_NODE_CHANGE && action.payload.nodeId === 'web3'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ export function getSelectedNode(state: AppState) {
|
||||||
return getNodes(state).selectedNode;
|
return getNodes(state).selectedNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isNodeChanging(state): boolean {
|
export function isNodeChanging(state: AppState): boolean {
|
||||||
return getSelectedNode(state).pending;
|
return getSelectedNode(state).pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ export function isWalletFormatSupportedOnNetwork(state: AppState, format: Wallet
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unSupportedWalletFormatsOnNetwork(state: AppState): WalletName[] {
|
export function unSupportedWalletFormatsOnNetwork(state: AppState): WalletName[] {
|
||||||
const supportedFormats = walletNames.filter(walletName =>
|
const supportedFormats = walletNames.filter((walletName: WalletName) =>
|
||||||
isWalletFormatSupportedOnNetwork(state, walletName)
|
isWalletFormatSupportedOnNetwork(state, walletName)
|
||||||
);
|
);
|
||||||
return difference(walletNames, supportedFormats);
|
return difference(walletNames, supportedFormats);
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
import { ICurrentTo, ICurrentValue } from 'selectors/transaction';
|
import { ICurrentTo, ICurrentValue } from 'selectors/transaction';
|
||||||
import { isNetworkUnit } from 'selectors/config';
|
import { isNetworkUnit } from 'selectors/config';
|
||||||
|
|
||||||
|
type TransactionFields = AppState['transaction']['fields'];
|
||||||
|
|
||||||
|
export type TransactionFieldValues = {
|
||||||
|
[field in keyof TransactionFields]: TransactionFields[field]['value']
|
||||||
|
};
|
||||||
|
|
||||||
export const reduceToValues = (transactionFields: AppState['transaction']['fields']) =>
|
export const reduceToValues = (transactionFields: AppState['transaction']['fields']) =>
|
||||||
Object.keys(transactionFields).reduce(
|
Object.keys(transactionFields).reduce<TransactionFieldValues>(
|
||||||
(obj, currFieldName) => {
|
(obj, currFieldName: keyof TransactionFields) => {
|
||||||
const currField = transactionFields[currFieldName];
|
const currField = transactionFields[currFieldName];
|
||||||
return { ...obj, [currFieldName]: currField.value };
|
return { ...obj, [currFieldName]: currField.value };
|
||||||
},
|
},
|
||||||
{} as any //TODO: Fix types
|
{} as TransactionFieldValues
|
||||||
);
|
);
|
||||||
|
|
||||||
export const isFullTx = (
|
export const isFullTx = (
|
||||||
|
|
|
@ -81,7 +81,10 @@ const serializedAndTransactionFieldsMatch = (state: AppState, isLocallySigned: b
|
||||||
|
|
||||||
const t2 = getTransactionFields(makeTransaction(serialzedTransaction));
|
const t2 = getTransactionFields(makeTransaction(serialzedTransaction));
|
||||||
const checkValidity = (tx: IHexStrTransaction) =>
|
const checkValidity = (tx: IHexStrTransaction) =>
|
||||||
Object.keys(tx).reduce((match, currField) => match && t1[currField] === t2[currField], true);
|
Object.keys(tx).reduce(
|
||||||
|
(match, currField: keyof IHexStrTransaction) => match && t1[currField] === t2[currField],
|
||||||
|
true
|
||||||
|
);
|
||||||
//reduce both ways to make sure both are exact same
|
//reduce both ways to make sure both are exact same
|
||||||
const transactionsMatch = checkValidity(t1) && checkValidity(t2);
|
const transactionsMatch = checkValidity(t1) && checkValidity(t2);
|
||||||
// if its signed then verify the signature too
|
// if its signed then verify the signature too
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
State as TransactionState
|
State as TransactionState
|
||||||
} from 'reducers/transaction';
|
} from 'reducers/transaction';
|
||||||
import { State as SwapState, INITIAL_STATE as swapInitialState } from 'reducers/swap';
|
import { State as SwapState, INITIAL_STATE as swapInitialState } from 'reducers/swap';
|
||||||
import { applyMiddleware, createStore } from 'redux';
|
import { applyMiddleware, createStore, Store } from 'redux';
|
||||||
import { composeWithDevTools } from 'redux-devtools-extension';
|
import { composeWithDevTools } from 'redux-devtools-extension';
|
||||||
import { createLogger } from 'redux-logger';
|
import { createLogger } from 'redux-logger';
|
||||||
import createSagaMiddleware from 'redux-saga';
|
import createSagaMiddleware from 'redux-saga';
|
||||||
|
@ -24,7 +24,7 @@ const configureStore = () => {
|
||||||
});
|
});
|
||||||
const sagaMiddleware = createSagaMiddleware();
|
const sagaMiddleware = createSagaMiddleware();
|
||||||
let middleware;
|
let middleware;
|
||||||
let store;
|
let store: Store<AppState>;
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
middleware = composeWithDevTools(
|
middleware = composeWithDevTools(
|
||||||
|
@ -45,7 +45,7 @@ const configureStore = () => {
|
||||||
|
|
||||||
const savedTransactionState = loadStatePropertyOrEmptyObject<TransactionState>('transaction');
|
const savedTransactionState = loadStatePropertyOrEmptyObject<TransactionState>('transaction');
|
||||||
|
|
||||||
const persistedInitialState = {
|
const persistedInitialState: Partial<AppState> = {
|
||||||
transaction: {
|
transaction: {
|
||||||
...transactionInitialState,
|
...transactionInitialState,
|
||||||
fields: {
|
fields: {
|
||||||
|
@ -65,10 +65,10 @@ const configureStore = () => {
|
||||||
...rehydrateConfigAndCustomTokenState()
|
...rehydrateConfigAndCustomTokenState()
|
||||||
};
|
};
|
||||||
|
|
||||||
store = createStore(RootReducer, persistedInitialState, middleware);
|
store = createStore<AppState>(RootReducer, persistedInitialState as any, middleware);
|
||||||
|
|
||||||
// Add all of the sagas to the middleware
|
// Add all of the sagas to the middleware
|
||||||
Object.keys(sagas).forEach(saga => {
|
Object.keys(sagas).forEach((saga: keyof typeof sagas) => {
|
||||||
sagaMiddleware.run(sagas[saga]);
|
sagaMiddleware.run(sagas[saga]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,20 @@ import React from 'react';
|
||||||
import { getLanguageSelection } from 'selectors/config';
|
import { getLanguageSelection } from 'selectors/config';
|
||||||
import { configuredStore } from '../store';
|
import { configuredStore } from '../store';
|
||||||
const fallbackLanguage = 'en';
|
const fallbackLanguage = 'en';
|
||||||
const repository = {};
|
const repository: {
|
||||||
|
[language: string]: {
|
||||||
|
[translationName: string]: string;
|
||||||
|
};
|
||||||
|
} = {};
|
||||||
|
|
||||||
const languages = [
|
interface ILanguage {
|
||||||
|
code: string;
|
||||||
|
data: {
|
||||||
|
[translationName: string]: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const languages: ILanguage[] = [
|
||||||
require('./lang/de.json'),
|
require('./lang/de.json'),
|
||||||
require('./lang/el.json'),
|
require('./lang/el.json'),
|
||||||
require('./lang/en.json'),
|
require('./lang/en.json'),
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
declare module 'ethereum-blockies' {
|
||||||
|
export function toDataUrl(address: string): string;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
declare module 'ethereumjs-abi' {
|
||||||
|
import BN from 'bn.js';
|
||||||
|
type Values = (string | number | BN)[];
|
||||||
|
type Types = string[];
|
||||||
|
export function eventID(name: string, types: Types): Buffer;
|
||||||
|
export function methodID(name: string, types: Types): Buffer;
|
||||||
|
export function rawEncode(types: Types, values: Values): Buffer;
|
||||||
|
export function rawDecode(
|
||||||
|
types: Types,
|
||||||
|
data: string | Buffer
|
||||||
|
): (Buffer | boolean | number | BN | string)[];
|
||||||
|
export function simpleEncode(method: string, values: Values): Buffer;
|
||||||
|
export function simpleDecode(
|
||||||
|
method: string,
|
||||||
|
data: string | Buffer
|
||||||
|
): (Buffer | boolean | number | BN | string)[];
|
||||||
|
export function stringify(types: Types, values: Values): string;
|
||||||
|
export function solidityPack(types: Types, values: Values): Buffer;
|
||||||
|
export function soliditySHA3(types: Types, values: Values): Buffer;
|
||||||
|
export function soliditySHA256(types: Types, values: Values): Buffer;
|
||||||
|
export function solidityRIPEMD160(types: Types, values: Values): Buffer;
|
||||||
|
export function fromSerpent(sig: string): Types;
|
||||||
|
export function toSerpent(types: Types): string;
|
||||||
|
}
|
|
@ -92,7 +92,7 @@ declare module 'ethereumjs-tx' {
|
||||||
* sign a transaction with a given a private key
|
* sign a transaction with a given a private key
|
||||||
* @param {Buffer} privateKey
|
* @param {Buffer} privateKey
|
||||||
*/
|
*/
|
||||||
public sign(privateKey: Buffer);
|
public sign(privateKey: Buffer): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The amount of gas paid for the data in this tx
|
* The amount of gas paid for the data in this tx
|
||||||
|
|
|
@ -65,7 +65,7 @@ declare module 'ethereumjs-wallet/hdkey' {
|
||||||
/**
|
/**
|
||||||
* @description derive a node based on a child index
|
* @description derive a node based on a child index
|
||||||
*/
|
*/
|
||||||
deriveChild(index): IHDNodePublic;
|
deriveChild(index: any): IHDNodePublic;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description return a Wallet instance
|
* @description return a Wallet instance
|
||||||
|
@ -97,7 +97,7 @@ declare module 'ethereumjs-wallet/hdkey' {
|
||||||
/**
|
/**
|
||||||
* @description derive a node based on a child index
|
* @description derive a node based on a child index
|
||||||
*/
|
*/
|
||||||
deriveChild(index): IHDNodePrivate | IHDNodePublic;
|
deriveChild(index: any): IHDNodePrivate | IHDNodePublic;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description return a Wallet instance
|
* @description return a Wallet instance
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
declare module 'ethjs-util' {
|
||||||
|
export function arrayContainsArray(arrayA: any[], arrayB: any[]): Boolean;
|
||||||
|
export function getBinarySize(num: string): number;
|
||||||
|
export function intToBuffer(integer: number): Buffer;
|
||||||
|
export function isHexPrefixed(hex: string): boolean;
|
||||||
|
export function stripHexPrefix(hexWithPrefix: string): string;
|
||||||
|
export function padToEven(unpaddedNumber: string): string;
|
||||||
|
export function intToHex(integer: number): string;
|
||||||
|
export function fromAscii(ascii: string): string;
|
||||||
|
export function fromUtf8(utf8: string): string;
|
||||||
|
export function toAscii(nonAscii: string): string;
|
||||||
|
export function toUtf8(nonUtf8: string): string;
|
||||||
|
export function getKeys(keys: any[], query: string): any[];
|
||||||
|
export function isHexString(inputString: string): boolean;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
declare module 'hdkey' {
|
||||||
|
export default class HDKey {
|
||||||
|
privateKey: Buffer;
|
||||||
|
publicKey: Buffer;
|
||||||
|
chainCode: Buffer | string;
|
||||||
|
static fromMasterSeed(seedBuffer: Buffer, versions?: any[]): HDKey;
|
||||||
|
static fromExtendedKey(base58key: any, versions?: any[]): HDKey;
|
||||||
|
static fromJSON(obj: any): HDKey;
|
||||||
|
derive(path: string): HDKey;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
declare module 'idna-uts46' {
|
||||||
|
export interface Options {
|
||||||
|
transitional?: boolean;
|
||||||
|
useStd3ASCII?: boolean;
|
||||||
|
verifyDnsLength?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toAscii(domain: string, options: Options): string;
|
||||||
|
export function toUnicode(domain: string, args: Options): string;
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
declare module 'ledgerco' {
|
||||||
|
// TODO: fill the library typings out
|
||||||
|
export const comm_u2f: any;
|
||||||
|
export class eth {
|
||||||
|
constructor(transport: any);
|
||||||
|
getAddress_async(
|
||||||
|
path: string,
|
||||||
|
boolDisplay?: boolean,
|
||||||
|
boolChaincode?: boolean
|
||||||
|
): Promise<{
|
||||||
|
publicKey: string;
|
||||||
|
address: string;
|
||||||
|
chainCode: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
signTransaction_async(
|
||||||
|
path: string,
|
||||||
|
rawTxHex: string
|
||||||
|
): Promise<{
|
||||||
|
s: string;
|
||||||
|
v: string;
|
||||||
|
r: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
getAppConfiguration_async(): Promise<{
|
||||||
|
arbitraryDataEnabled: number;
|
||||||
|
version: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
signPersonalMessage_async(
|
||||||
|
path: string,
|
||||||
|
messageHex: string
|
||||||
|
): Promise<{
|
||||||
|
v: number;
|
||||||
|
s: string;
|
||||||
|
r: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
signPersonalMessage_async(
|
||||||
|
path: string,
|
||||||
|
messageHex: string,
|
||||||
|
cb: (signed: any, error: any) => any
|
||||||
|
): void;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
declare module 'react-copy-to-clipboard' {
|
||||||
|
interface Options {
|
||||||
|
debug: boolean;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
text: string;
|
||||||
|
onCopy?(a: string, b: boolean): void;
|
||||||
|
options?: Options;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CopyToClipboard extends React.Component<Props> {}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
interface PropTypes {
|
||||||
|
activeStep: number;
|
||||||
|
steps: any[];
|
||||||
|
activeColor?: string;
|
||||||
|
completeColor?: string;
|
||||||
|
defaultColor?: string;
|
||||||
|
activeTitleColor?: string;
|
||||||
|
completeTitleColor?: string;
|
||||||
|
defaultTitleColor?: string;
|
||||||
|
circleFontColor?: string;
|
||||||
|
size?: number;
|
||||||
|
circleFontSize?: number;
|
||||||
|
titleFontSize?: number;
|
||||||
|
circleTop?: number;
|
||||||
|
titleTop?: number;
|
||||||
|
defaultOpacity?: string;
|
||||||
|
completeOpacity?: string;
|
||||||
|
activeOpacity?: string;
|
||||||
|
defaultTitleOpacity?: string;
|
||||||
|
completeTitleOpacity?: string;
|
||||||
|
activeTitleOpacity?: string;
|
||||||
|
barStyle?: string;
|
||||||
|
defaultBarColor?: string;
|
||||||
|
completeBarColor?: string;
|
||||||
|
defaultBorderColor?: string;
|
||||||
|
completeBorderColor?: string;
|
||||||
|
activeBorderColor?: string;
|
||||||
|
defaultBorderStyle?: string;
|
||||||
|
completeBorderStyle?: string;
|
||||||
|
activeBorderStyle?: string;
|
||||||
|
}
|
||||||
|
declare module 'react-stepper-horizontal' {
|
||||||
|
import React from 'react';
|
||||||
|
class Stepper extends React.Component<PropTypes> {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
|
export = Stepper;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
declare module 'redux-test-utils' {
|
||||||
|
import { Store } from 'react-redux';
|
||||||
|
|
||||||
|
export function createMockStore(testState: any): Store<any>;
|
||||||
|
export function createMockDispatch(testAction: any): any;
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
declare module 'wallet-address-validator' {
|
||||||
|
export function validate(
|
||||||
|
address: string,
|
||||||
|
currency?: CurrencyNames | CurrencySymbols,
|
||||||
|
networkType?: 'prod' | 'testnet' | 'both'
|
||||||
|
): boolean;
|
||||||
|
export function getAddressType(address: string): string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type CurrencyNames =
|
||||||
|
| 'bitcoin'
|
||||||
|
| 'litecoin'
|
||||||
|
| 'peercoin'
|
||||||
|
| 'dogecoin'
|
||||||
|
| 'beavercoin'
|
||||||
|
| 'freicoin'
|
||||||
|
| 'protoshares'
|
||||||
|
| 'megacoin'
|
||||||
|
| 'primecoin'
|
||||||
|
| 'auroracoin'
|
||||||
|
| 'namecoin'
|
||||||
|
| 'biocoin';
|
||||||
|
|
||||||
|
type CurrencySymbols =
|
||||||
|
| 'BTC'
|
||||||
|
| 'LTC'
|
||||||
|
| 'PPC'
|
||||||
|
| 'DOGE'
|
||||||
|
| 'BVC'
|
||||||
|
| 'FRC'
|
||||||
|
| 'PTS'
|
||||||
|
| 'MEC'
|
||||||
|
| 'XPM'
|
||||||
|
| 'AUR'
|
||||||
|
| 'NMC'
|
||||||
|
| 'BIO';
|
|
@ -1,13 +1,20 @@
|
||||||
import qs from 'query-string';
|
import qs from 'query-string';
|
||||||
import has from 'lodash/has';
|
import has from 'lodash/has';
|
||||||
|
|
||||||
export function objectContainsObjectKeys(checkingObject, containingObject) {
|
interface IObjectValue {
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function objectContainsObjectKeys(
|
||||||
|
checkingObject: IObjectValue,
|
||||||
|
containingObject: IObjectValue
|
||||||
|
) {
|
||||||
const checkingObjectKeys = Object.keys(checkingObject);
|
const checkingObjectKeys = Object.keys(checkingObject);
|
||||||
const containsAll = checkingObjectKeys.map(key => has(containingObject, key));
|
const containsAll = checkingObjectKeys.map(key => has(containingObject, key));
|
||||||
return containsAll.every(isTrue => isTrue);
|
return containsAll.every(isTrue => isTrue);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getKeyByValue(object, value) {
|
export function getKeyByValue(object: IObjectValue, value: any) {
|
||||||
return Object.keys(object).find(key => object[key] === value);
|
return Object.keys(object).find(key => object[key] === value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,5 +35,5 @@ export function isPositiveInteger(n: number) {
|
||||||
return Number.isInteger(n) && n > 0;
|
return Number.isInteger(n) && n > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getValues = (...args) =>
|
export const getValues = (...args: any[]) =>
|
||||||
args.reduce((acc, currArg) => [...acc, ...Object.values(currArg)], []);
|
args.reduce((acc, currArg) => [...acc, ...Object.values(currArg)], []);
|
||||||
|
|
|
@ -2,6 +2,7 @@ export const REDUX_STATE = 'REDUX_STATE';
|
||||||
import { State as SwapState } from 'reducers/swap';
|
import { State as SwapState } from 'reducers/swap';
|
||||||
import { IWallet, WalletConfig } from 'libs/wallet';
|
import { IWallet, WalletConfig } from 'libs/wallet';
|
||||||
import { sha256 } from 'ethereumjs-util';
|
import { sha256 } from 'ethereumjs-util';
|
||||||
|
import { AppState } from 'reducers';
|
||||||
|
|
||||||
export function loadState<T>(): T | undefined {
|
export function loadState<T>(): T | undefined {
|
||||||
try {
|
try {
|
||||||
|
@ -26,8 +27,8 @@ export const saveState = (state: any) => {
|
||||||
|
|
||||||
export type SwapLocalStorage = SwapState;
|
export type SwapLocalStorage = SwapState;
|
||||||
|
|
||||||
export function loadStatePropertyOrEmptyObject<T>(key: string): T | undefined {
|
export function loadStatePropertyOrEmptyObject<T>(key: keyof AppState): T | undefined {
|
||||||
const localStorageState = loadState();
|
const localStorageState: Partial<AppState> | undefined = loadState();
|
||||||
if (localStorageState) {
|
if (localStorageState) {
|
||||||
if (localStorageState.hasOwnProperty(key)) {
|
if (localStorageState.hasOwnProperty(key)) {
|
||||||
return localStorageState[key] as T;
|
return localStorageState[key] as T;
|
||||||
|
|
|
@ -18,8 +18,8 @@ export default function(element: React.ReactElement<any>, opts: PrintOptions = {
|
||||||
// Convert popupFeatures into a key=value,key=value string. See
|
// Convert popupFeatures into a key=value,key=value string. See
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Window/open#Window_features
|
// https://developer.mozilla.org/en-US/docs/Web/API/Window/open#Window_features
|
||||||
// for more information.
|
// for more information.
|
||||||
const featuresStr = Object.keys(options.popupFeatures)
|
const featuresStr = Object.entries(options.popupFeatures)
|
||||||
.map(key => `${key}=${options.popupFeatures[key]}`)
|
.map(([key, value]) => `${key}=${value}`)
|
||||||
.join(',');
|
.join(',');
|
||||||
|
|
||||||
const popup = window.open('about:blank', 'printWindow', featuresStr);
|
const popup = window.open('about:blank', 'printWindow', featuresStr);
|
||||||
|
|
|
@ -6,7 +6,7 @@ export function dedupeCustomTokens(networkTokens: Token[], customTokens: Token[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any tokens have the same symbol or contract address, remove them
|
// If any tokens have the same symbol or contract address, remove them
|
||||||
const tokenCollisionMap = networkTokens.reduce((prev, token) => {
|
const tokenCollisionMap = networkTokens.reduce<{ [tokenKey: string]: boolean }>((prev, token) => {
|
||||||
prev[token.symbol] = true;
|
prev[token.symbol] = true;
|
||||||
prev[token.address] = true;
|
prev[token.address] = true;
|
||||||
return prev;
|
return prev;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { APP_TITLE } from '../constants';
|
||||||
const isDevelopment = process.env.NODE_ENV !== 'production';
|
const isDevelopment = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
// Cached reference, preventing recreations
|
// Cached reference, preventing recreations
|
||||||
let window;
|
let window: BrowserWindow | null;
|
||||||
|
|
||||||
// Construct new BrowserWindow
|
// Construct new BrowserWindow
|
||||||
export default function getWindow() {
|
export default function getWindow() {
|
||||||
|
@ -39,7 +39,7 @@ export default function getWindow() {
|
||||||
window = null;
|
window = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
window.webContents.on('new-window', (ev, urlStr) => {
|
window.webContents.on('new-window', (ev: any, urlStr: string) => {
|
||||||
// Kill all new window requests by default
|
// Kill all new window requests by default
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
|
@ -53,13 +53,13 @@ export default function getWindow() {
|
||||||
});
|
});
|
||||||
|
|
||||||
window.webContents.on('did-finish-load', () => {
|
window.webContents.on('did-finish-load', () => {
|
||||||
updater(window);
|
updater(window!);
|
||||||
});
|
});
|
||||||
|
|
||||||
window.webContents.on('devtools-opened', () => {
|
window.webContents.on('devtools-opened', () => {
|
||||||
window.focus();
|
window!.focus();
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
window.focus();
|
window!.focus();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
33
package.json
33
package.json
|
@ -54,19 +54,24 @@
|
||||||
"zxcvbn": "4.4.2"
|
"zxcvbn": "4.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/bip39": "2.4.0",
|
||||||
"@types/classnames": "2.2.3",
|
"@types/classnames": "2.2.3",
|
||||||
|
"@types/enzyme": "3.1.8",
|
||||||
|
"@types/enzyme-adapter-react-16": "1.0.1",
|
||||||
"@types/history": "4.6.2",
|
"@types/history": "4.6.2",
|
||||||
"@types/jest": "22.2.0",
|
"@types/jest": "22.2.0",
|
||||||
"@types/lodash": "4.14.104",
|
"@types/lodash": "4.14.104",
|
||||||
"@types/qrcode": "0.8.0",
|
"@types/qrcode": "0.8.0",
|
||||||
"@types/qrcode.react": "0.6.3",
|
"@types/qrcode.react": "0.6.3",
|
||||||
"@types/query-string": "5.1.0",
|
"@types/query-string": "5.1.0",
|
||||||
|
"@types/rc-slider": "8.2.3",
|
||||||
"@types/react": "16.0.40",
|
"@types/react": "16.0.40",
|
||||||
"@types/react-dom": "16.0.4",
|
"@types/react-dom": "16.0.4",
|
||||||
"@types/react-redux": "5.0.15",
|
"@types/react-redux": "5.0.15",
|
||||||
"@types/react-router-dom": "4.2.4",
|
"@types/react-router-dom": "4.2.4",
|
||||||
"@types/react-router-redux": "5.0.12",
|
"@types/react-router-redux": "5.0.12",
|
||||||
"@types/react-select": "1.2.3",
|
"@types/react-select": "1.2.3",
|
||||||
|
"@types/react-transition-group": "2.0.7",
|
||||||
"@types/redux-logger": "3.0.5",
|
"@types/redux-logger": "3.0.5",
|
||||||
"@types/uuid": "3.4.3",
|
"@types/uuid": "3.4.3",
|
||||||
"@types/webpack-env": "1.13.4",
|
"@types/webpack-env": "1.13.4",
|
||||||
|
@ -131,8 +136,8 @@
|
||||||
"webpack-hot-middleware": "2.21.0",
|
"webpack-hot-middleware": "2.21.0",
|
||||||
"webpack-sources": "1.0.1",
|
"webpack-sources": "1.0.1",
|
||||||
"webpack-subresource-integrity": "1.0.4",
|
"webpack-subresource-integrity": "1.0.4",
|
||||||
"worker-loader": "1.1.1",
|
"what-input": "5.0.5",
|
||||||
"what-input": "5.0.5"
|
"worker-loader": "1.1.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"freezer": "webpack --config=./webpack_config/webpack.freezer.js && node ./dist/freezer.js",
|
"freezer": "webpack --config=./webpack_config/webpack.freezer.js && node ./dist/freezer.js",
|
||||||
|
@ -142,10 +147,14 @@
|
||||||
"prebuild": "check-node-version --package",
|
"prebuild": "check-node-version --package",
|
||||||
"build:downloadable": "webpack --config webpack_config/webpack.html.js",
|
"build:downloadable": "webpack --config webpack_config/webpack.html.js",
|
||||||
"prebuild:downloadable": "check-node-version --package",
|
"prebuild:downloadable": "check-node-version --package",
|
||||||
"build:electron": "webpack --config webpack_config/webpack.electron-prod.js && node webpack_config/buildElectron.js",
|
"build:electron":
|
||||||
"build:electron:osx": "webpack --config webpack_config/webpack.electron-prod.js && ELECTRON_OS=osx node webpack_config/buildElectron.js",
|
"webpack --config webpack_config/webpack.electron-prod.js && node webpack_config/buildElectron.js",
|
||||||
"build:electron:windows": "webpack --config webpack_config/webpack.electron-prod.js && ELECTRON_OS=windows node webpack_config/buildElectron.js",
|
"build:electron:osx":
|
||||||
"build:electron:linux": "webpack --config webpack_config/webpack.electron-prod.js && ELECTRON_OS=linux node webpack_config/buildElectron.js",
|
"webpack --config webpack_config/webpack.electron-prod.js && ELECTRON_OS=osx node webpack_config/buildElectron.js",
|
||||||
|
"build:electron:windows":
|
||||||
|
"webpack --config webpack_config/webpack.electron-prod.js && ELECTRON_OS=windows node webpack_config/buildElectron.js",
|
||||||
|
"build:electron:linux":
|
||||||
|
"webpack --config webpack_config/webpack.electron-prod.js && ELECTRON_OS=linux node webpack_config/buildElectron.js",
|
||||||
"prebuild:electron": "check-node-version --package",
|
"prebuild:electron": "check-node-version --package",
|
||||||
"test:coverage": "jest --config=jest_config/jest.config.json --coverage",
|
"test:coverage": "jest --config=jest_config/jest.config.json --coverage",
|
||||||
"test": "jest --config=jest_config/jest.config.json",
|
"test": "jest --config=jest_config/jest.config.json",
|
||||||
|
@ -157,14 +166,18 @@
|
||||||
"predev": "check-node-version --package",
|
"predev": "check-node-version --package",
|
||||||
"dev:https": "HTTPS=true node webpack_config/devServer.js",
|
"dev:https": "HTTPS=true node webpack_config/devServer.js",
|
||||||
"predev:https": "check-node-version --package",
|
"predev:https": "check-node-version --package",
|
||||||
"dev:electron": "concurrently --kill-others --names 'webpack,electron' 'BUILD_ELECTRON=true node webpack_config/devServer.js' 'webpack --config webpack_config/webpack.electron-dev.js && electron dist/electron-js/main.js'",
|
"dev:electron":
|
||||||
"dev:electron:https": "concurrently --kill-others --names 'webpack,electron' 'BUILD_ELECTRON=true HTTPS=true node webpack_config/devServer.js' 'HTTPS=true webpack --config webpack_config/webpack.electron-dev.js && electron dist/electron-js/main.js'",
|
"concurrently --kill-others --names 'webpack,electron' 'BUILD_ELECTRON=true node webpack_config/devServer.js' 'webpack --config webpack_config/webpack.electron-dev.js && electron dist/electron-js/main.js'",
|
||||||
|
"dev:electron:https":
|
||||||
|
"concurrently --kill-others --names 'webpack,electron' 'BUILD_ELECTRON=true HTTPS=true node webpack_config/devServer.js' 'HTTPS=true webpack --config webpack_config/webpack.electron-dev.js && electron dist/electron-js/main.js'",
|
||||||
"tslint": "tslint --project . --exclude common/vendor/**/*",
|
"tslint": "tslint --project . --exclude common/vendor/**/*",
|
||||||
"tscheck": "tsc --noEmit",
|
"tscheck": "tsc --noEmit",
|
||||||
"start": "npm run dev",
|
"start": "npm run dev",
|
||||||
"precommit": "lint-staged",
|
"precommit": "lint-staged",
|
||||||
"formatAll": "find ./common/ -name '*.ts*' | xargs prettier --write --config ./.prettierrc --config-precedence file-override",
|
"formatAll":
|
||||||
"prettier:diff": "prettier --write --config ./.prettierrc --list-different \"common/**/*.ts\" \"common/**/*.tsx\"",
|
"find ./common/ -name '*.ts*' | xargs prettier --write --config ./.prettierrc --config-precedence file-override",
|
||||||
|
"prettier:diff":
|
||||||
|
"prettier --write --config ./.prettierrc --list-different \"common/**/*.ts\" \"common/**/*.tsx\"",
|
||||||
"prepush": "npm run tslint && npm run tscheck"
|
"prepush": "npm run tslint && npm run tscheck"
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
|
|
|
@ -6,10 +6,10 @@ configuredStore.getState();
|
||||||
describe('Contracts JSON', () => {
|
describe('Contracts JSON', () => {
|
||||||
Object.keys(CONTRACTS).forEach(network => {
|
Object.keys(CONTRACTS).forEach(network => {
|
||||||
it(`${network} contracts array properly formatted`, () => {
|
it(`${network} contracts array properly formatted`, () => {
|
||||||
const contracts = CONTRACTS[network];
|
const contracts: any = (CONTRACTS as any)[network];
|
||||||
const addressCollisionMap = {};
|
const addressCollisionMap: any = {};
|
||||||
|
|
||||||
contracts.forEach(contract => {
|
contracts.forEach((contract: any) => {
|
||||||
if (contract.address && !isValidETHAddress(contract.address)) {
|
if (contract.address && !isValidETHAddress(contract.address)) {
|
||||||
throw Error(`Contract '${contract.name}' has invalid address '${contract.address}'`);
|
throw Error(`Contract '${contract.name}' has invalid address '${contract.address}'`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,11 @@ configuredStore.getState();
|
||||||
describe('Tokens JSON', () => {
|
describe('Tokens JSON', () => {
|
||||||
Object.keys(TOKENS).forEach(network => {
|
Object.keys(TOKENS).forEach(network => {
|
||||||
it(`${network} tokens array properly formatted`, () => {
|
it(`${network} tokens array properly formatted`, () => {
|
||||||
const tokens = TOKENS[network];
|
const tokens = (TOKENS as any)[network];
|
||||||
const addressCollisionMap = {};
|
const addressCollisionMap: any = {};
|
||||||
const symbolCollisionMap = {};
|
const symbolCollisionMap: any = {};
|
||||||
|
|
||||||
tokens.forEach(token => {
|
tokens.forEach((token: any) => {
|
||||||
if (!isValidETHAddress(token.address)) {
|
if (!isValidETHAddress(token.address)) {
|
||||||
throw Error(`Token ${token.symbol} has invalid contract address '${token.address}'`);
|
throw Error(`Token ${token.symbol} has invalid contract address '${token.address}'`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { RPCNode } from '../../common/libs/nodes';
|
import { RPCNode } from '../../common/libs/nodes';
|
||||||
import { Validator } from 'jsonschema';
|
import { Validator, ValidatorResult } from 'jsonschema';
|
||||||
import { schema } from '../../common/libs/validators';
|
import { schema } from '../../common/libs/validators';
|
||||||
import 'url-search-params-polyfill';
|
import 'url-search-params-polyfill';
|
||||||
import EtherscanNode from 'libs/nodes/etherscan';
|
import EtherscanNode from 'libs/nodes/etherscan';
|
||||||
|
@ -25,6 +25,10 @@ const validRequests = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface RPCTestList {
|
||||||
|
[key: string]: ((n: RPCNode) => Promise<ValidatorResult>);
|
||||||
|
}
|
||||||
|
|
||||||
const testGetBalance = (n: RPCNode) => {
|
const testGetBalance = (n: RPCNode) => {
|
||||||
return n.client
|
return n.client
|
||||||
.call(n.requests.getBalance(validRequests.address))
|
.call(n.requests.getBalance(validRequests.address))
|
||||||
|
@ -44,7 +48,7 @@ const testGetTokenBalance = (n: RPCNode) => {
|
||||||
.then(data => v.validate(data, schema.RpcNode));
|
.then(data => v.validate(data, schema.RpcNode));
|
||||||
};
|
};
|
||||||
|
|
||||||
const RPCTests = {
|
const RPCTests: RPCTestList = {
|
||||||
getBalance: testGetBalance,
|
getBalance: testGetBalance,
|
||||||
estimateGas: testEstimateGas,
|
estimateGas: testEstimateGas,
|
||||||
getTokenBalance: testGetTokenBalance
|
getTokenBalance: testGetTokenBalance
|
||||||
|
|
|
@ -9,7 +9,7 @@ const dockerTag = 'latest';
|
||||||
|
|
||||||
function promiseFromChildProcess(command: string): Promise<any> {
|
function promiseFromChildProcess(command: string): Promise<any> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
return exec(command, (err, stdout) => {
|
return exec(command, (err: string, stdout: string) => {
|
||||||
err ? reject(err) : resolve(stdout);
|
err ? reject(err) : resolve(stdout);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { configuredStore } from 'store';
|
import { configuredStore } from 'store';
|
||||||
import { delay } from 'redux-saga';
|
import { delay, SagaIterator } from 'redux-saga';
|
||||||
import { call, cancel, fork, put, take, select } from 'redux-saga/effects';
|
import { call, cancel, fork, put, take, select } from 'redux-saga/effects';
|
||||||
import { cloneableGenerator, createMockTask } from 'redux-saga/utils';
|
import { cloneableGenerator, createMockTask } from 'redux-saga/utils';
|
||||||
import {
|
import {
|
||||||
|
@ -58,9 +58,9 @@ describe('pollOfflineStatus*', () => {
|
||||||
timeout: true
|
timeout: true
|
||||||
};
|
};
|
||||||
|
|
||||||
let originalHidden;
|
let originalHidden: any;
|
||||||
let originalOnLine;
|
let originalOnLine: any;
|
||||||
let originalRandom;
|
let originalRandom: any;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
// backup global config
|
// backup global config
|
||||||
|
@ -143,16 +143,18 @@ describe('handlePollOfflineStatus*', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('handleNodeChangeIntent*', () => {
|
describe('handleNodeChangeIntent*', () => {
|
||||||
let originalRandom;
|
let originalRandom: any;
|
||||||
|
|
||||||
// normal operation variables
|
// normal operation variables
|
||||||
const defaultNodeId = selectedNodeExpectedState.initialState.nodeId;
|
const defaultNodeId: any = selectedNodeExpectedState.initialState.nodeId;
|
||||||
const defaultNodeConfig: StaticNodeConfig = staticNodesExpectedState.initialState[defaultNodeId];
|
const defaultNodeConfig: any = (staticNodesExpectedState as any).initialState[defaultNodeId];
|
||||||
const newNodeId = Object.keys(staticNodesExpectedState.initialState).reduce(
|
const newNodeId = Object.keys(staticNodesExpectedState.initialState).reduce(
|
||||||
(acc, cur) =>
|
(acc, cur) =>
|
||||||
staticNodesExpectedState.initialState[cur].network !== defaultNodeConfig.network ? cur : acc
|
(staticNodesExpectedState as any).initialState[cur].network !== defaultNodeConfig.network
|
||||||
|
? cur
|
||||||
|
: acc
|
||||||
);
|
);
|
||||||
const newNodeConfig: StaticNodeConfig = staticNodesExpectedState.initialState[newNodeId];
|
const newNodeConfig: StaticNodeConfig = (staticNodesExpectedState as any).initialState[newNodeId];
|
||||||
|
|
||||||
const changeNodeIntentAction = changeNodeIntent(newNodeId);
|
const changeNodeIntentAction = changeNodeIntent(newNodeId);
|
||||||
const latestBlock = '0xa';
|
const latestBlock = '0xa';
|
||||||
|
@ -166,7 +168,7 @@ describe('handleNodeChangeIntent*', () => {
|
||||||
const data = {} as any;
|
const data = {} as any;
|
||||||
data.gen = cloneableGenerator(handleNodeChangeIntent)(changeNodeIntentAction);
|
data.gen = cloneableGenerator(handleNodeChangeIntent)(changeNodeIntentAction);
|
||||||
|
|
||||||
function shouldBailOut(gen, nextVal, errMsg) {
|
function shouldBailOut(gen: SagaIterator, nextVal: any, errMsg: string) {
|
||||||
expect(gen.next(nextVal).value).toEqual(select(getNodeId));
|
expect(gen.next(nextVal).value).toEqual(select(getNodeId));
|
||||||
expect(gen.next(defaultNodeId).value).toEqual(put(showNotification('danger', errMsg, 5000)));
|
expect(gen.next(defaultNodeId).value).toEqual(put(showNotification('danger', errMsg, 5000)));
|
||||||
expect(gen.next().value).toEqual(
|
expect(gen.next().value).toEqual(
|
||||||
|
@ -297,7 +299,7 @@ describe('unsetWeb3Node*', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('unsetWeb3NodeOnWalletEvent*', () => {
|
describe('unsetWeb3NodeOnWalletEvent*', () => {
|
||||||
const fakeAction = {};
|
const fakeAction: any = {};
|
||||||
const mockNodeId = 'web3';
|
const mockNodeId = 'web3';
|
||||||
const alternativeNodeId = 'eth_mycrypto';
|
const alternativeNodeId = 'eth_mycrypto';
|
||||||
const gen = unsetWeb3NodeOnWalletEvent(fakeAction);
|
const gen = unsetWeb3NodeOnWalletEvent(fakeAction);
|
||||||
|
@ -319,7 +321,7 @@ describe('unsetWeb3NodeOnWalletEvent*', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return early if node type is not web3', () => {
|
it('should return early if node type is not web3', () => {
|
||||||
const gen1 = unsetWeb3NodeOnWalletEvent({ payload: false });
|
const gen1 = unsetWeb3NodeOnWalletEvent({ payload: false } as any);
|
||||||
gen1.next(); //getNode
|
gen1.next(); //getNode
|
||||||
gen1.next('notWeb3'); //getNodeConfig
|
gen1.next('notWeb3'); //getNodeConfig
|
||||||
expect(gen1.next().done).toEqual(true);
|
expect(gen1.next().done).toEqual(true);
|
||||||
|
@ -329,7 +331,7 @@ describe('unsetWeb3NodeOnWalletEvent*', () => {
|
||||||
const mockAddress = '0x0';
|
const mockAddress = '0x0';
|
||||||
const mockNetwork = 'ETH';
|
const mockNetwork = 'ETH';
|
||||||
const mockWeb3Wallet = new Web3Wallet(mockAddress, mockNetwork);
|
const mockWeb3Wallet = new Web3Wallet(mockAddress, mockNetwork);
|
||||||
const gen2 = unsetWeb3NodeOnWalletEvent({ payload: mockWeb3Wallet });
|
const gen2 = unsetWeb3NodeOnWalletEvent({ payload: mockWeb3Wallet } as any);
|
||||||
gen2.next(); //getNode
|
gen2.next(); //getNode
|
||||||
gen2.next('web3'); //getNodeConfig
|
gen2.next('web3'); //getNodeConfig
|
||||||
expect(gen2.next().done).toEqual(true);
|
expect(gen2.next().done).toEqual(true);
|
||||||
|
|
|
@ -12,7 +12,7 @@ import tokens from 'config/tokens/eth.json';
|
||||||
import { SHAPESHIFT_TOKEN_WHITELIST } from 'api/shapeshift';
|
import { SHAPESHIFT_TOKEN_WHITELIST } from 'api/shapeshift';
|
||||||
|
|
||||||
describe('ensure whitelist', () => {
|
describe('ensure whitelist', () => {
|
||||||
const findToken = (tkn: string) => tokens.find(t => t.symbol === tkn);
|
const findToken = (tkn: string) => tokens.find((t: any) => t.symbol === tkn);
|
||||||
SHAPESHIFT_TOKEN_WHITELIST.forEach(t => {
|
SHAPESHIFT_TOKEN_WHITELIST.forEach(t => {
|
||||||
it(`Should find Token ${t}`, () => {
|
it(`Should find Token ${t}`, () => {
|
||||||
expect(findToken(t)).toBeTruthy();
|
expect(findToken(t)).toBeTruthy();
|
||||||
|
@ -87,7 +87,7 @@ describe('swap reducer', () => {
|
||||||
|
|
||||||
it('should handle SWAP_LOAD_SHAPESHIFT_RATES_SUCCEEDED', () => {
|
it('should handle SWAP_LOAD_SHAPESHIFT_RATES_SUCCEEDED', () => {
|
||||||
expect(
|
expect(
|
||||||
swap(undefined, swapActions.loadShapeshiftRatesSucceededSwap(shapeshiftApiResponse))
|
swap(undefined, swapActions.loadShapeshiftRatesSucceededSwap(shapeshiftApiResponse as any))
|
||||||
).toEqual({
|
).toEqual({
|
||||||
...INITIAL_STATE,
|
...INITIAL_STATE,
|
||||||
isFetchingRates: false,
|
isFetchingRates: false,
|
||||||
|
|
|
@ -85,7 +85,7 @@ describe('pollBityOrderStatus*', () => {
|
||||||
error: true,
|
error: true,
|
||||||
msg: 'error message'
|
msg: 'error message'
|
||||||
};
|
};
|
||||||
let random;
|
let random: () => number;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
random = Math.random;
|
random = Math.random;
|
||||||
|
@ -156,7 +156,7 @@ describe('pollShapeshiftOrderStatus*', () => {
|
||||||
error: 'Shapeshift error',
|
error: 'Shapeshift error',
|
||||||
status: 'failed'
|
status: 'failed'
|
||||||
};
|
};
|
||||||
let random;
|
let random: () => number;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
random = Math.random;
|
random = Math.random;
|
||||||
|
@ -293,7 +293,7 @@ describe('postBityOrderCreate*', () => {
|
||||||
const data = {} as any;
|
const data = {} as any;
|
||||||
data.gen = cloneableGenerator(postBityOrderCreate)(action);
|
data.gen = cloneableGenerator(postBityOrderCreate)(action);
|
||||||
|
|
||||||
let random;
|
let random: () => number;
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
random = Math.random;
|
random = Math.random;
|
||||||
Math.random = () => 0.001;
|
Math.random = () => 0.001;
|
||||||
|
@ -381,7 +381,7 @@ describe('postShapeshiftOrderCreate*', () => {
|
||||||
const data = {} as any;
|
const data = {} as any;
|
||||||
data.gen = cloneableGenerator(postShapeshiftOrderCreate)(action);
|
data.gen = cloneableGenerator(postShapeshiftOrderCreate)(action);
|
||||||
|
|
||||||
let random;
|
let random: () => number;
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
random = Math.random;
|
random = Math.random;
|
||||||
Math.random = () => 0.001;
|
Math.random = () => 0.001;
|
||||||
|
@ -457,7 +457,7 @@ describe('bityOrderTimeRemaining*', () => {
|
||||||
orderTimestampCreatedISOString: new Date(orderTimeExpired).toISOString(),
|
orderTimestampCreatedISOString: new Date(orderTimeExpired).toISOString(),
|
||||||
validFor: swapValidFor
|
validFor: swapValidFor
|
||||||
};
|
};
|
||||||
let random;
|
let random: () => number;
|
||||||
|
|
||||||
const data = {} as any;
|
const data = {} as any;
|
||||||
data.gen = cloneableGenerator(bityOrderTimeRemaining)();
|
data.gen = cloneableGenerator(bityOrderTimeRemaining)();
|
||||||
|
@ -538,7 +538,7 @@ describe('shapeshiftOrderTimeRemaining*', () => {
|
||||||
orderTimestampCreatedISOString: new Date(orderTimeExpired).toISOString(),
|
orderTimestampCreatedISOString: new Date(orderTimeExpired).toISOString(),
|
||||||
validFor: swapValidFor
|
validFor: swapValidFor
|
||||||
};
|
};
|
||||||
let random;
|
let random: () => number;
|
||||||
|
|
||||||
const data = {} as any;
|
const data = {} as any;
|
||||||
data.gen = cloneableGenerator(shapeshiftOrderTimeRemaining)();
|
data.gen = cloneableGenerator(shapeshiftOrderTimeRemaining)();
|
||||||
|
|
|
@ -36,7 +36,7 @@ describe('loadBityRates*', () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const err = { message: 'error' };
|
const err = { message: 'error' };
|
||||||
let random;
|
let random: () => number;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
random = Math.random;
|
random = Math.random;
|
||||||
|
@ -103,7 +103,7 @@ describe('loadShapeshiftRates*', () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const err = 'error';
|
const err = 'error';
|
||||||
let random;
|
let random: () => number;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
random = Math.random;
|
random = Math.random;
|
||||||
|
@ -125,7 +125,7 @@ describe('loadShapeshiftRates*', () => {
|
||||||
|
|
||||||
it('should put loadShapeshiftRatesSucceededSwap', () => {
|
it('should put loadShapeshiftRatesSucceededSwap', () => {
|
||||||
expect(gen1.next({ tokens: apiResponse }).value).toEqual(
|
expect(gen1.next({ tokens: apiResponse }).value).toEqual(
|
||||||
put(loadShapeshiftRatesSucceededSwap(apiResponse))
|
put(loadShapeshiftRatesSucceededSwap(apiResponse as any))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ describe('broadcastTransactionWrapper*', () => {
|
||||||
blockExplorer: 'blockExplorer'
|
blockExplorer: 'blockExplorer'
|
||||||
};
|
};
|
||||||
|
|
||||||
let random;
|
let random: () => number;
|
||||||
const func: any = () => undefined;
|
const func: any = () => undefined;
|
||||||
const action: any = {};
|
const action: any = {};
|
||||||
const gens: any = {};
|
const gens: any = {};
|
||||||
|
|
|
@ -10,8 +10,9 @@ import {
|
||||||
valueHandler
|
valueHandler
|
||||||
} from 'sagas/transaction/current/currentValue';
|
} from 'sagas/transaction/current/currentValue';
|
||||||
import { cloneableGenerator, SagaIteratorClone } from 'redux-saga/utils';
|
import { cloneableGenerator, SagaIteratorClone } from 'redux-saga/utils';
|
||||||
|
import { SagaIterator } from 'redux-saga';
|
||||||
|
|
||||||
const itShouldBeDone = gen => {
|
const itShouldBeDone = (gen: SagaIterator) => {
|
||||||
it('should be done', () => {
|
it('should be done', () => {
|
||||||
expect(gen.next().done).toEqual(true);
|
expect(gen.next().done).toEqual(true);
|
||||||
});
|
});
|
||||||
|
@ -83,7 +84,12 @@ describe('setCurrentValue*', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('revalidateCurrentValue*', () => {
|
describe('revalidateCurrentValue*', () => {
|
||||||
const sharedLogic = (gen, etherTransaction, currVal, reparsedValue) => {
|
const sharedLogic = (
|
||||||
|
gen: SagaIterator,
|
||||||
|
etherTransaction: boolean,
|
||||||
|
currVal: any,
|
||||||
|
reparsedValue: boolean
|
||||||
|
) => {
|
||||||
it('should select isEtherTransaction', () => {
|
it('should select isEtherTransaction', () => {
|
||||||
expect(gen.next().value).toEqual(select(isEtherTransaction));
|
expect(gen.next().value).toEqual(select(isEtherTransaction));
|
||||||
});
|
});
|
||||||
|
@ -159,7 +165,7 @@ describe('revalidateCurrentValue*', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('reparseCurrentValue*', () => {
|
describe('reparseCurrentValue*', () => {
|
||||||
const sharedLogic = gen => {
|
const sharedLogic = (gen: SagaIterator) => {
|
||||||
it('should select getDecimal', () => {
|
it('should select getDecimal', () => {
|
||||||
expect(gen.next().value).toEqual(select(getDecimal));
|
expect(gen.next().value).toEqual(select(getDecimal));
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,9 +12,10 @@ import {
|
||||||
} from 'sagas/transaction/fields/fields';
|
} from 'sagas/transaction/fields/fields';
|
||||||
import { cloneableGenerator } from 'redux-saga/utils';
|
import { cloneableGenerator } from 'redux-saga/utils';
|
||||||
import { setGasPriceField } from 'actions/transaction';
|
import { setGasPriceField } from 'actions/transaction';
|
||||||
|
import { SagaIterator } from 'redux-saga';
|
||||||
configuredStore.getState();
|
configuredStore.getState();
|
||||||
|
|
||||||
const itShouldBeDone = gen => {
|
const itShouldBeDone = (gen: SagaIterator) => {
|
||||||
it('should be done', () => {
|
it('should be done', () => {
|
||||||
expect(gen.next().done).toEqual(true);
|
expect(gen.next().done).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,9 +7,10 @@ import { bufferToHex, toBuffer } from 'ethereumjs-util';
|
||||||
import { getTokenTo, getData } from 'selectors/transaction';
|
import { getTokenTo, getData } from 'selectors/transaction';
|
||||||
import { handleTokenTo, handleTokenValue } from 'sagas/transaction/meta/token';
|
import { handleTokenTo, handleTokenValue } from 'sagas/transaction/meta/token';
|
||||||
import { cloneableGenerator } from 'redux-saga/utils';
|
import { cloneableGenerator } from 'redux-saga/utils';
|
||||||
|
import { SagaIterator } from 'redux-saga';
|
||||||
configuredStore.getState();
|
configuredStore.getState();
|
||||||
|
|
||||||
const itShouldBeDone = gen => {
|
const itShouldBeDone = (gen: SagaIterator) => {
|
||||||
it('should be done', () => {
|
it('should be done', () => {
|
||||||
expect(gen.next().done).toEqual(true);
|
expect(gen.next().done).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,11 +17,13 @@ import {
|
||||||
import { encodeTransfer } from 'libs/transaction';
|
import { encodeTransfer } from 'libs/transaction';
|
||||||
import { bufferToHex } from 'ethereumjs-util';
|
import { bufferToHex } from 'ethereumjs-util';
|
||||||
import { rebaseUserInput, validateInput } from 'sagas/transaction/validationHelpers';
|
import { rebaseUserInput, validateInput } from 'sagas/transaction/validationHelpers';
|
||||||
import { cloneableGenerator } from 'redux-saga/utils';
|
import { cloneableGenerator, SagaIteratorClone } from 'redux-saga/utils';
|
||||||
import { handleSetUnitMeta } from 'sagas/transaction/meta/unitSwap';
|
import { handleSetUnitMeta } from 'sagas/transaction/meta/unitSwap';
|
||||||
import { isNetworkUnit } from 'selectors/config';
|
import { isNetworkUnit } from 'selectors/config';
|
||||||
|
import { SagaIterator } from 'redux-saga';
|
||||||
|
import BN from 'bn.js';
|
||||||
|
|
||||||
const itShouldBeDone = gen => {
|
const itShouldBeDone = (gen: SagaIterator) => {
|
||||||
it('should be done', () => {
|
it('should be done', () => {
|
||||||
expect(gen.next().done).toEqual(true);
|
expect(gen.next().done).toEqual(true);
|
||||||
});
|
});
|
||||||
|
@ -29,11 +31,11 @@ const itShouldBeDone = gen => {
|
||||||
|
|
||||||
describe('handleSetUnitMeta*', () => {
|
describe('handleSetUnitMeta*', () => {
|
||||||
const expectedStart = (
|
const expectedStart = (
|
||||||
gen,
|
gen: SagaIterator,
|
||||||
previousUnit,
|
previousUnit: string,
|
||||||
currentUnit,
|
currentUnit: string,
|
||||||
prevUnitIsNetworkUnit,
|
prevUnitIsNetworkUnit: boolean,
|
||||||
currUnitIsNetworkUnit
|
currUnitIsNetworkUnit: boolean
|
||||||
) => {
|
) => {
|
||||||
it('should select getPreviousUnit', () => {
|
it('should select getPreviousUnit', () => {
|
||||||
expect(gen.next().value).toEqual(select(getPreviousUnit));
|
expect(gen.next().value).toEqual(select(getPreviousUnit));
|
||||||
|
@ -121,7 +123,7 @@ describe('handleSetUnitMeta*', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('etherToToken || tokenToToken', () => {
|
describe('etherToToken || tokenToToken', () => {
|
||||||
const sharedLogicA = (gen, decimal, currentUnit) => {
|
const sharedLogicA = (gen: SagaIteratorClone, decimal: number, currentUnit: string) => {
|
||||||
it('should select getToken with currentUnit', () => {
|
it('should select getToken with currentUnit', () => {
|
||||||
expect(gen.next(decimal).value).toEqual(select(getToken, currentUnit));
|
expect(gen.next(decimal).value).toEqual(select(getToken, currentUnit));
|
||||||
});
|
});
|
||||||
|
@ -132,9 +134,16 @@ describe('handleSetUnitMeta*', () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const sharedLogicB = (gen, input, raw, value, currentUnit, isValid) => {
|
const sharedLogicB = (
|
||||||
|
gen: SagaIterator,
|
||||||
|
input: string,
|
||||||
|
raw: string,
|
||||||
|
value: BN,
|
||||||
|
currentUnit: string,
|
||||||
|
isValid: boolean
|
||||||
|
) => {
|
||||||
it('should call rebaseUserInput with input', () => {
|
it('should call rebaseUserInput with input', () => {
|
||||||
expect(gen.next(input).value).toEqual(call(rebaseUserInput, input));
|
expect(gen.next(input).value).toEqual(call(rebaseUserInput, input as any));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call validateInput with value and currentUnit', () => {
|
it('should call validateInput with value and currentUnit', () => {
|
||||||
|
@ -146,7 +155,14 @@ describe('handleSetUnitMeta*', () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const constructExpectedPayload = (data, toAddress, raw, value, decimal, tokenTo?) => {
|
const constructExpectedPayload = (
|
||||||
|
data: Buffer,
|
||||||
|
toAddress: string,
|
||||||
|
raw: string,
|
||||||
|
value: BN,
|
||||||
|
decimal: number,
|
||||||
|
tokenTo?: any
|
||||||
|
) => {
|
||||||
const base = {
|
const base = {
|
||||||
data: { raw: bufferToHex(data), value: data },
|
data: { raw: bufferToHex(data), value: data },
|
||||||
to: { raw: '', value: Address(toAddress) },
|
to: { raw: '', value: Address(toAddress) },
|
||||||
|
|
|
@ -14,7 +14,7 @@ describe('handleFromRequest*', () => {
|
||||||
const fromAddress = '0xa';
|
const fromAddress = '0xa';
|
||||||
const gens: any = {};
|
const gens: any = {};
|
||||||
gens.gen = cloneableGenerator(handleFromRequest)();
|
gens.gen = cloneableGenerator(handleFromRequest)();
|
||||||
let random;
|
let random: () => number;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
random = Math.random;
|
random = Math.random;
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
localGasEstimation,
|
localGasEstimation,
|
||||||
setAddressMessageGasLimit
|
setAddressMessageGasLimit
|
||||||
} from 'sagas/transaction/network/gas';
|
} from 'sagas/transaction/network/gas';
|
||||||
import { cloneableGenerator } from 'redux-saga/utils';
|
import { cloneableGenerator, SagaIteratorClone } from 'redux-saga/utils';
|
||||||
import { Wei } from 'libs/units';
|
import { Wei } from 'libs/units';
|
||||||
import { TypeKeys as ConfigTypeKeys } from 'actions/config';
|
import { TypeKeys as ConfigTypeKeys } from 'actions/config';
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ describe('estimateGas*', () => {
|
||||||
const gens: { [name: string]: any } = {};
|
const gens: { [name: string]: any } = {};
|
||||||
gens.successCase = cloneableGenerator(estimateGas)();
|
gens.successCase = cloneableGenerator(estimateGas)();
|
||||||
|
|
||||||
let random;
|
let random: () => number;
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
random = Math.random;
|
random = Math.random;
|
||||||
Math.random = () => 0.001;
|
Math.random = () => 0.001;
|
||||||
|
@ -251,8 +251,8 @@ describe('localGasEstimation', () => {
|
||||||
describe('setAddressMessageGasLimit*', () => {
|
describe('setAddressMessageGasLimit*', () => {
|
||||||
const gens = cloneableGenerator(setAddressMessageGasLimit)();
|
const gens = cloneableGenerator(setAddressMessageGasLimit)();
|
||||||
const gen = gens.clone();
|
const gen = gens.clone();
|
||||||
let noAutoGen;
|
let noAutoGen: SagaIteratorClone;
|
||||||
let noMessageGen;
|
let noMessageGen: SagaIteratorClone;
|
||||||
const addressMessage = {
|
const addressMessage = {
|
||||||
gasLimit: 123456,
|
gasLimit: 123456,
|
||||||
msg: 'Thanks for donating, er, investing in SCAM'
|
msg: 'Thanks for donating, er, investing in SCAM'
|
||||||
|
|
|
@ -21,7 +21,7 @@ describe('handleNonceRequest*', () => {
|
||||||
|
|
||||||
const gens: any = {};
|
const gens: any = {};
|
||||||
gens.gen = cloneableGenerator(handleNonceRequest)();
|
gens.gen = cloneableGenerator(handleNonceRequest)();
|
||||||
let random;
|
let random: () => number;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
random = Math.random;
|
random = Math.random;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue