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:
HenryNguyen5 2018-03-07 18:36:05 -05:00 committed by Daniel Ternyak
parent 0e26f7af4c
commit c340246ca0
107 changed files with 737 additions and 291 deletions

View File

@ -29,7 +29,7 @@ export function loadBityRatesSucceededSwap(
export type TLoadShapeshiftRatesSucceededSwap = typeof loadShapeshiftRatesSucceededSwap;
export function loadShapeshiftRatesSucceededSwap(
payload
payload: interfaces.LoadShapeshiftRatesSucceededSwapAction['payload']
): interfaces.LoadShapeshiftRatesSucceededSwapAction {
return {
type: TypeKeys.SWAP_LOAD_SHAPESHIFT_RATES_SUCCEEDED,

View File

@ -29,10 +29,14 @@ const repOptions = {
name: 'Augur'
};
export interface MappedRates {
[key: string]: any;
}
export function getAllRates() {
const mappedRates = {};
const mappedRates: MappedRates = {};
return _getAllRates().then(bityRates => {
bityRates.objects.forEach(each => {
bityRates.objects.forEach((each: any) => {
const pairName = each.pair;
const from = { id: pairName.substring(0, 3) };
const to = { id: pairName.substring(3, 6) };

View File

@ -1,4 +1,5 @@
import { checkHttpStatus, parseJSON } from './utils';
import { Omit } from 'react-redux';
const MAX_GAS_FAST = 250;
@ -21,15 +22,29 @@ export interface GasEstimates {
isDefault: boolean;
}
interface GasExpressResponse {
block_time: number;
blockNum: number;
fast: number;
fastest: number;
safeLow: number;
standard: number;
}
export function fetchGasEstimates(): Promise<GasEstimates> {
return fetch('https://dev.blockscale.net/api/gasexpress.json', {
mode: 'cors'
})
.then(checkHttpStatus)
.then(parseJSON)
.then((res: object) => {
.then((res: GasExpressResponse) => {
// 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 => {
if (typeof res[key] !== 'number') {
throw new Error(

View File

@ -28,6 +28,44 @@ export const SHAPESHIFT_TOKEN_WHITELIST = [
];
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 {
public whitelist = SHAPESHIFT_WHITELIST;
private url = SHAPESHIFT_BASE_URL;
@ -36,13 +74,18 @@ class ShapeshiftService {
'Content-Type': 'application/json'
};
public checkStatus(address) {
public checkStatus(address: string) {
return fetch(`${this.url}/txStat/${address}`)
.then(checkHttpStatus)
.then(parseJSON);
}
public sendAmount(withdrawal, originKind, destinationKind, destinationAmount) {
public sendAmount(
withdrawal: string,
originKind: string,
destinationKind: string,
destinationAmount: number
) {
const pair = `${originKind.toLowerCase()}_${destinationKind.toLowerCase()}`;
return fetch(`${this.url}/sendamount`, {
@ -81,7 +124,7 @@ class ShapeshiftService {
return mappedRates;
};
private getPairRates(marketInfo) {
private getPairRates(marketInfo: ShapeshiftMarketInfo[]) {
const filteredMarketInfo = marketInfo.filter(obj => {
const { pair } = obj;
const pairArr = pair.split('_');
@ -97,7 +140,7 @@ class ShapeshiftService {
return pairRates;
}
private async checkAvl(pairRates) {
private async checkAvl(pairRates: IPairData[]) {
const avlCoins = await this.getAvlCoins();
const mapAvl = pairRates.map(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() {
@ -130,7 +174,7 @@ class ShapeshiftService {
.then(parseJSON);
}
private getSinglePairRate(pair) {
private getSinglePairRate(pair: string) {
return fetch(`${this.url}/rate/${pair}`)
.then(checkHttpStatus)
.then(parseJSON);
@ -142,12 +186,12 @@ class ShapeshiftService {
.then(parseJSON);
}
private isWhitelisted(coin) {
private isWhitelisted(coin: string) {
return this.whitelist.includes(coin);
}
private mapMarketInfo(marketInfo) {
const tokenMap = {};
private mapMarketInfo(marketInfo: (IPairData & IAvailablePairData)[]) {
const tokenMap: TokenMap = {};
marketInfo.forEach(m => {
const originKind = m.pair.substring(0, 3);
const destinationKind = m.pair.substring(4, 7);

View File

@ -37,5 +37,8 @@ export const AmountField: React.SFC<Props> = ({
/>
);
const isAmountValid = (raw, customValidator, isValid) =>
customValidator ? customValidator(raw) : isValid;
const isAmountValid = (
raw: string,
customValidator: ((rawAmount: string) => boolean) | undefined,
isValid: boolean
) => (customValidator ? customValidator(raw) : isValid);

View File

@ -8,7 +8,6 @@ import { chain, flatMap } from 'lodash';
import { TokenBalance, getShownTokenBalances } from 'selectors/wallet';
import { Balance } from 'libs/wallet';
import './EquivalentValues.scss';
import { Wei } from 'libs/units';
import { AppState } from 'reducers';
import { getNetworkConfig, getOffline } from 'selectors/config';
import { connect } from 'react-redux';
@ -16,6 +15,7 @@ import btcIco from 'assets/images/bitcoin.png';
import ethIco from 'assets/images/ether.png';
import repIco from 'assets/images/augur.png';
import { NetworkConfig } from 'types/network';
import BN from 'bn.js';
interface AllValue {
symbol: string;
@ -51,6 +51,14 @@ interface DispatchProps {
fetchCCRates: TFetchCCRatesRequested;
}
interface FiatSymbols {
[key: string]: string;
}
interface Rates {
[rate: string]: number;
}
type Props = StateProps & DispatchProps;
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 });
};
@ -120,28 +128,38 @@ class EquivalentValues extends React.Component<Props, State> {
const isFetching =
!balance || balance.isPending || !tokenBalances || Object.keys(rates).length === 0;
const pairRates = this.generateValues(equivalentValues.label, equivalentValues.value);
const fiatSymbols = {
const fiatSymbols: FiatSymbols = {
USD: '$',
EUR: '€',
GBP: '£',
CHF: ' '
};
const coinAndTokenSymbols = {
const coinAndTokenSymbols: any = {
BTC: btcIco,
ETH: ethIco,
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 = '' }) => (
<div className={`EquivalentValues-values-currency ${className}`}>
<img src={icon} />
{!!symbol && <span className="EquivalentValues-values-currency-fiat-symbol">{symbol}</span>}
<span className="EquivalentValues-values-currency-label">{rate}</span>{' '}
const Value = (props: ValueProps) => (
<div className={`EquivalentValues-values-currency ${props.className}`}>
<img src={props.icon} />
{!!props.symbol && (
<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">
<UnitDisplay
unit={'ether'}
value={value}
displayShortBalance={rateSymbols.isFiat(rate) ? 2 : 3}
value={props.value}
displayShortBalance={rateSymbols.isFiat(props.rate) ? 2 : 3}
checkOffline={true}
/>
</span>
@ -157,7 +175,7 @@ class EquivalentValues extends React.Component<Props, State> {
// TODO: Update type
value={equivalentValues as any}
options={options as any}
onChange={this.selectOption}
onChange={this.selectOption as any}
clearable={false}
searchable={false}
/>
@ -224,7 +242,7 @@ class EquivalentValues extends React.Component<Props, State> {
const allRates = Object.values(balance).map(
value => !!rates[value.symbol] && rates[value.symbol]
);
const allEquivalentValues = allRates.map((rateType, i) => {
const allEquivalentValues = allRates.map((rateType: any, i) => {
return {
symbol: Object.keys(rates)[i],
equivalentValues: [
@ -260,9 +278,9 @@ class EquivalentValues extends React.Component<Props, State> {
// return equivalent value (unit * rate * balance)
private handleValues(unit: string, balance: Balance['wei']) {
const { rates } = this.props;
const ratesObj = { ...rates[unit] };
const ratesObj: Rates = { ...rates[unit] };
return Object.keys(ratesObj).map(key => {
const value = (balance as Wei).muln(ratesObj[key]);
const value = balance!.muln(ratesObj[key]);
return { rate: key, value };
});
}

View File

@ -5,7 +5,7 @@ import './Promos.scss';
import { connect } from 'react-redux';
import { AppState } from '../../reducers';
const CarouselAnimation = ({ children, ...props }) => (
const CarouselAnimation = ({ children, ...props }: any) => (
<CSSTransition {...props} timeout={300} classNames="carousel">
{children}
</CSSTransition>

View File

@ -15,19 +15,23 @@ interface Props {
onRemoveCustomToken(symbol: string): any;
}
interface TrackedTokens {
[symbol: string]: boolean;
}
interface State {
trackedTokens: { [symbol: string]: boolean };
showCustomTokenForm: boolean;
}
export default class TokenBalances extends React.PureComponent<Props, State> {
public state = {
public state: State = {
trackedTokens: {},
showCustomTokenForm: false
};
public componentWillReceiveProps(nextProps: Props) {
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();
return prev;
}, {});

View File

@ -13,7 +13,7 @@ interface StateProps {
}
interface OwnProps {
withProps(props: CallBackProps);
withProps(props: CallBackProps): null | React.ReactElement<any>;
onChange(value: React.FormEvent<HTMLInputElement>): void;
}

View File

@ -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) {
this.setState({ privateKey: nextProps.privateKey });
this.setState({ privateKey: nextProps.privateKey || '' });
}
}

View File

@ -17,7 +17,7 @@ import { Input } from 'components/ui';
const CUSTOM = 'custom';
interface InputProps {
name: string;
name: keyof Omit<State, 'hasAuth'>;
placeholder?: string;
type?: string;
autoComplete?: 'off';

View File

@ -18,7 +18,7 @@ interface State {
}
class LogOutPromptClass extends React.Component<Props, State> {
constructor(props) {
constructor(props: Props) {
super(props);
this.state = {
nextLocation: null,

View File

@ -1,5 +1,5 @@
import React from 'react';
import Slider from 'rc-slider';
import Slider, { createSliderWithTooltip } from 'rc-slider';
import translate, { translateRaw } from 'translations';
import FeeSummary from './FeeSummary';
import './SimpleGas.scss';
@ -16,12 +16,13 @@ import { getEstimates, getIsEstimating } from 'selectors/gas';
import { Wei, fromWei } from 'libs/units';
import { gasPriceDefaults } from 'config';
import { InlineSpinner } from 'components/ui/InlineSpinner';
const SliderWithTooltip = Slider.createSliderWithTooltip(Slider);
import { TInputGasPrice } from 'actions/transaction';
const SliderWithTooltip = createSliderWithTooltip(Slider);
interface OwnProps {
gasPrice: AppState['transaction']['fields']['gasPrice'];
inputGasPrice(rawGas: string);
setGasPrice(rawGas: string);
setGasPrice: TInputGasPrice;
inputGasPrice(rawGas: string): void;
}
interface StateProps {

View File

@ -7,6 +7,7 @@ import { connect } from 'react-redux';
import { AppState } from 'reducers';
import { getUnit } from 'selectors/transaction';
import { getNetworkUnit } from 'selectors/config';
import { Option } from 'react-select';
interface DispatchProps {
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);
};
}

View File

@ -126,7 +126,7 @@ type InsecureWallets = { [key in InsecureWalletName]: InsecureWalletInfo };
type MiscWallet = { [key in MiscWalletName]: MiscWalletInfo };
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;
const SECURE_WALLETS = Object.values(SecureWalletName);

View File

@ -73,7 +73,7 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
this.getAddresses();
}
public componentWillReceiveProps(nextProps) {
public componentWillReceiveProps(nextProps: Props) {
const { publicKey, chainCode, seed, dPath } = this.props;
if (
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 });
}

View File

@ -129,7 +129,7 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
showTip: false
});
ledger.comm_u2f.create_async().then(comm => {
ledger.comm_u2f.create_async().then((comm: any) => {
new ledger.eth(comm)
.getAddress_async(dPath, false, true)
.then(res => {
@ -139,7 +139,7 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
isLoading: false
});
})
.catch(err => {
.catch((err: any) => {
if (err && err.metaData && err.metaData.code === 5) {
this.showTip();
}

View File

@ -59,7 +59,7 @@ class MnemonicDecryptClass extends PureComponent<Props, State> {
isValid={isValidMnemonic}
isTextareaWhenVisible={true}
onChange={this.onMnemonicChange}
onEnter={isValidMnemonic && this.onDWModalOpen}
onEnter={isValidMnemonic ? this.onDWModalOpen : undefined}
/>
</div>
<div className="form-group">
@ -134,7 +134,7 @@ class MnemonicDecryptClass extends PureComponent<Props, State> {
this.setState({ dPath });
};
private handleUnlock = (address, index) => {
private handleUnlock = (address: string, index: number) => {
const { formattedPhrase, pass, dPath } = this.state;
this.props.onUnlock({

View File

@ -108,7 +108,7 @@ class TrezorDecryptClass extends PureComponent<Props, State> {
(TrezorConnect as any).getXPubKey(
dPath,
res => {
(res: any) => {
if (res.success) {
this.setState({
dPath,

View File

@ -1,5 +1,5 @@
import React from 'react';
import Select, { ReactSelectProps } from 'react-select';
import Select, { ReactSelectProps, Option } from 'react-select';
interface Props extends ReactSelectProps {
className?: string;
@ -13,11 +13,11 @@ export default class Dropdown extends React.Component<Props> {
hasBlurred: false
};
public handleChange = selectedOption => {
public handleChange = (selectedOption: Option) => {
this.setState({ selectedOption });
};
public formatOptions = options => {
public formatOptions = (options: Option[]) => {
if (typeof options[0] === 'object') {
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
ref={el => {
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();
});
}
@ -46,7 +46,7 @@ export default class Dropdown extends React.Component<Props> {
className={`${this.props.className} ${this.state.hasBlurred ? 'has-blurred' : ''}`}
value={value}
onChange={obj => {
this.handleChange(obj);
this.handleChange(obj as any);
onChange();
}}
{...this.props}
@ -56,7 +56,7 @@ export default class Dropdown extends React.Component<Props> {
this.props.onBlur(e);
}
}}
options={options}
options={options as any}
/>
);
}

View File

@ -23,7 +23,7 @@ interface ModalStyle {
maxWidth?: string;
}
const Fade = ({ children, ...props }) => (
const Fade = ({ children, ...props }: any) => (
<CSSTransition {...props} timeout={300} classNames="animate-modal">
{children}
</CSSTransition>

View File

@ -64,8 +64,8 @@ export default class DropdownComponent<T> extends PureComponent<Props<T>, State>
overflowY: 'auto'
};
const searchRegex = new RegExp(search, 'gi');
const onSearchChange = e => {
this.setState({ search: e.target.value });
const onSearchChange = (e: React.FormEvent<HTMLInputElement>) => {
this.setState({ search: e.currentTarget.value });
};
return (

View File

@ -25,15 +25,15 @@ const ValueComp: React.SFC = (props: any) => {
};
const OptionComp: React.SFC = (props: any) => {
const handleMouseDown = event => {
const handleMouseDown = (event: React.MouseEvent<any>) => {
event.preventDefault();
event.stopPropagation();
props.onSelect(props.option, event);
};
const handleMouseEnter = event => {
const handleMouseEnter = (event: React.MouseEvent<any>) => {
props.onFocus(props.option, event);
};
const handleMouseMove = event => {
const handleMouseMove = (event: React.MouseEvent<any>) => {
if (props.isFocused) {
return;
}

View File

@ -6,7 +6,11 @@ import { HELP_ARTICLE } from 'config';
import OnboardSlide from './OnboardSlide';
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 subheader = translate('ONBOARD_final_subtitle');

View File

@ -49,7 +49,7 @@ interface Props {
class OnboardModal extends React.Component<Props, State> {
private modal: Modal | null = null;
constructor(props) {
constructor(props: Props) {
super(props);
this.state = {
isOpen: false

View File

@ -36,7 +36,7 @@ interface State {
inputs: {
[key: string]: { rawData: string; parsedData: string[] | string };
};
outputs;
outputs: any;
selectedFunction: null | ContractOption;
}
@ -124,7 +124,7 @@ class InteractExplorerClass extends Component<Props, State> {
</div>
);
})}
{selectedFunction.contract.outputs.map((output, index) => {
{selectedFunction.contract.outputs.map((output: any, index: number) => {
const { type, name } = output;
const parsedName = name === '' ? index : name;

View File

@ -20,7 +20,7 @@ interface StateProps {
}
interface OwnProps {
accessContract(contractAbi: string, address: string): (ev) => void;
accessContract(contractAbi: string, address: string): (ev: any) => void;
resetState(): void;
}
@ -45,7 +45,7 @@ const abiJsonPlaceholder = [
class InteractForm extends Component<Props, State> {
private abiJsonPlaceholder = JSON.stringify(abiJsonPlaceholder, null, 0);
constructor(props) {
constructor(props: Props) {
super(props);
this.state = {
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.setState({ [name]: ev.currentTarget.value });
};

View File

@ -1,7 +1,7 @@
import React from 'react';
import { IOwnedDomainRequest } from 'libs/ens';
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;

View File

@ -22,7 +22,7 @@ class CountDown extends Component<Props, State> {
private startCountDown = () => {
const time = moment(this.props.initialTime);
let intervalId;
let intervalId: number;
const setTimeDisplay = () => {
const diff = moment.duration(time.diff(moment()));
@ -44,7 +44,7 @@ class CountDown extends Component<Props, State> {
this.setState({ timeDisplay });
};
intervalId = setInterval(setTimeDisplay, 1000);
intervalId = window.setInterval(setTimeDisplay, 1000);
setTimeDisplay();
};
}

View File

@ -46,7 +46,7 @@ const WalletTypes: React.SFC<{}> = () => {
<div className="WalletTypes-types row">
<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">
<h2 className="WalletType-title">{translate(typeInfo[type].name)}</h2>
<ul className="WalletType-features">

View File

@ -44,7 +44,8 @@ interface 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, {}> {
public state = {
@ -145,7 +146,7 @@ class RequestPayment extends React.Component<Props, {}> {
private generateEIP681String(
currentTo: string,
tokenContractAddress: string,
currentValue,
currentValue: { raw: string; value: BN | null },
gasLimit: { raw: string; value: BN | null },
unit: string,
decimal: number,
@ -162,7 +163,11 @@ class RequestPayment extends React.Component<Props, {}> {
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);
} else {
return buildEIP681TokenRequest(

View File

@ -30,8 +30,8 @@ export interface ActionProps {
interface State {
disabled: boolean;
origin: SwapInput;
destination: SwapInput;
origin: SwapOpt;
destination: SwapOpt;
originKindOptions: any[];
destinationKindOptions: any[];
originErr: string;
@ -49,7 +49,7 @@ interface SwapOpt extends SwapInput {
}
export default class CurrencySwap extends PureComponent<Props, State> {
public state = {
public state: State = {
disabled: true,
origin: {
label: 'BTC',
@ -57,14 +57,14 @@ export default class CurrencySwap extends PureComponent<Props, State> {
status: 'available',
image: 'https://shapeshift.io/images/coins/bitcoin.png',
amount: NaN
} as SwapOpt,
},
destination: {
label: 'ETH',
value: 'Ether',
status: 'available',
image: 'https://shapeshift.io/images/coins/ether.png',
amount: NaN
} as SwapOpt,
},
originKindOptions: [],
destinationKindOptions: [],
originErr: '',
@ -151,7 +151,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
return merge(shapeshiftRates, bityRates);
};
public getMinMax = (originKind: WhitelistedCoins, destinationKind) => {
public getMinMax = (originKind: WhitelistedCoins, destinationKind: string) => {
let min;
let max;
@ -176,7 +176,11 @@ export default class CurrencySwap extends PureComponent<Props, State> {
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 higherThanMin = originAmount >= rate.min;
const lowerThanMax = originAmount <= rate.max;
@ -201,7 +205,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
this.debouncedCreateErrString(origin, destination, showError);
}
public setErrorMessages = (originErr, destinationErr) => {
public setErrorMessages = (originErr: string, destinationErr: string) => {
this.setState({
originErr,
destinationErr
@ -269,15 +273,17 @@ export default class CurrencySwap extends PureComponent<Props, State> {
: this.updateDestinationAmount(origin, destination, amount);
};
public onChangeOriginKind = newOption => {
public onChangeOriginKind = (newOption: any) => {
const { origin, destination, destinationKindOptions } = this.state;
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 = {
label: newOption.label === destination.label ? origin.label : destination.label,
value: newOption.value === destination.value ? origin.value : destination.value,
amount: ''
amount: 0,
status: '',
image: ''
};
this.setState({
@ -292,16 +298,16 @@ export default class CurrencySwap extends PureComponent<Props, State> {
initSwap({ origin: newOrigin, destination: newDest });
};
public onChangeDestinationKind = newOption => {
public onChangeDestinationKind = (newOption: any) => {
const { initSwap } = this.props;
const { origin, destination } = this.state;
const newOrigin = {
...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({
origin: newOrigin,
destination: newDest
@ -339,7 +345,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
<Input
id="origin-swap-input"
className={`input-group-input ${
String(origin.amount) !== '' &&
!origin.amount &&
this.isMinMaxValid(origin.amount, origin.label, destination.label)
? ''
: 'invalid'
@ -364,7 +370,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
<Input
id="destination-swap-input"
className={`${
String(destination.amount) !== '' &&
!destination.amount &&
this.isMinMaxValid(origin.amount, origin.label, destination.label)
? ''
: 'invalid'

View File

@ -24,6 +24,7 @@ import { getOffline } from 'selectors/config';
import Rates from './Rates';
import { AppState } from 'reducers';
import './CurrentRates.scss';
import { Optional } from 'utils/types';
interface StateProps {
isOffline: boolean;
@ -40,7 +41,7 @@ interface ActionProps {
type Props = StateProps & ActionProps;
class CurrentRates extends PureComponent<Props> {
private shapeShiftRateCache = null;
private shapeShiftRateCache: any = null;
public componentDidMount() {
if (!this.props.isOffline) {
@ -79,7 +80,7 @@ class CurrentRates extends PureComponent<Props> {
public buildSSPairs = (shapeshiftRates: NormalizedShapeshiftRates, n: number = 4) => {
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;
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;
};
@ -118,7 +119,7 @@ class CurrentRates extends PureComponent<Props> {
return fixedRates;
};
public swapEl = (providerURL, providerLogo, children) => {
public swapEl = (providerURL: string, providerLogo: string, children: any) => {
return (
<article className="SwapRates">
<h3 className="SwapRates-title">{translate('SWAP_rates')}</h3>

View File

@ -47,7 +47,7 @@ interface State {
}
export default class Rates extends Component<Props, State> {
public state = {
public state: State = {
pairs: {}
};
@ -72,7 +72,7 @@ export default class Rates extends Component<Props, State> {
public getPairs = () => {
const { rates } = this.props;
const { allIds } = rates;
return allIds.reduce((acc, cur) => {
return allIds.reduce<{ [id: string]: 1 }>((acc, cur) => {
acc[cur] = 1;
return acc;
}, {});

View File

@ -1,7 +1,14 @@
import abi from 'ethereumjs-abi';
import { toChecksumAddress, addHexPrefix } from 'ethereumjs-util';
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 {
public constant: boolean;
@ -53,7 +60,6 @@ export default class AbiFunction {
// Convert argdata to a hex buffer for ethereumjs-abi
const argBuffer = new Buffer(argString, 'hex');
// Decode!
const argArr = abi.rawDecode(this.outputTypes, argBuffer);
@ -80,13 +86,13 @@ export default class AbiFunction {
}
private parsePostDecodedValue = (type: string, value: any) => {
const valueMapping = {
address: val => toChecksumAddress(val.toString(16))
const valueMapping: ITypeMapping = {
address: (val: any) => toChecksumAddress(val.toString(16))
};
return valueMapping[type]
? valueMapping[type](value)
: BN.isBN(value) ? value.toString() : value;
const mapppedType = valueMapping[type];
return mapppedType ? mapppedType(value) : BN.isBN(value) ? value.toString() : value;
};
private parsePreEncodedValue = (_: string, value: any) =>
@ -95,7 +101,7 @@ export default class AbiFunction {
private makeFuncParams = () =>
this.inputs.reduce((accumulator, currInput) => {
const { name, type } = currInput;
const inputHandler = inputToParse =>
const inputHandler = (inputToParse: any) =>
//TODO: introduce typechecking and typecasting mapping for inputs
({ name, type, value: this.parsePreEncodedValue(type, inputToParse) });
@ -110,7 +116,7 @@ export default class AbiFunction {
return addHexPrefix(`${this.methodSelector}${encodedArgs}`);
};
private processSuppliedArgs = (suppliedArgs: object) =>
private processSuppliedArgs = (suppliedArgs: ISuppliedArgs) =>
this.inputNames.map(name => {
const type = this.funcParams[name].type;
//TODO: parse args based on type

View File

@ -6,6 +6,11 @@ const ABIFUNC_METHOD_NAMES = ['encodeInput', 'decodeInput', 'decodeOutput'];
enum ABIMethodTypes {
FUNC = 'function'
}
export default interface Contract {
[key: string]: any;
};
export type TContract = typeof Contract;
export default class Contract {
@ -22,14 +27,14 @@ export default class Contract {
return isFunc ? { ...accu, [currContractMethodName]: currContractMethod } : accu;
}, {});
public abi;
public abi: any;
constructor(abi, outputMappings: ContractOutputMappings = {}) {
constructor(abi: any, outputMappings: ContractOutputMappings = {}) {
this.assignABIFuncs(abi, outputMappings);
}
private assignABIFuncs = (abi, outputMappings: ContractOutputMappings) => {
abi.forEach(currentABIMethod => {
private assignABIFuncs = (abi: any, outputMappings: ContractOutputMappings) => {
abi.forEach((currentABIMethod: any) => {
const { name, type } = currentABIMethod;
if (type === ABIMethodTypes.FUNC) {
//only grab the functions we need

View File

@ -36,3 +36,11 @@ export interface FuncParams {
processInput(value: any): any;
};
}
export interface ITypeMapping {
[type: string]: (value: any) => any;
}
export interface ISuppliedArgs {
[argumentName: string]: any;
}

View File

@ -1,7 +1,7 @@
import { mnemonicToSeed, validateMnemonic } from 'bip39';
import { createDecipheriv, createHash } from 'crypto';
import { privateToAddress } from 'ethereumjs-util';
import { fromMasterSeed } from 'hdkey';
import HDkey from 'hdkey';
import { stripHexPrefixAndLower } from 'libs/values';
// 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) {
// 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');
hash.update(block);
hash.update(data);
@ -83,7 +83,7 @@ export function decryptMnemonicToPrivKey(
}
const seed = mnemonicToSeed(phrase, pass);
const derived = fromMasterSeed(seed).derive(path);
const derived = HDkey.fromMasterSeed(seed).derive(path);
const dPrivKey = derived.privateKey;
const dAddress = privateToAddress(dPrivKey).toString('hex');

View File

@ -1,7 +1,7 @@
import uts46 from 'idna-uts46';
import ethUtil from 'ethereumjs-util';
export function normalise(name: string) {
export function normalise(name: string): string {
try {
return uts46.toUnicode(name, { useStd3ASCII: true, transitional: false });
} catch (e) {
@ -65,7 +65,7 @@ export enum NameState {
NotYetAvailable = '5'
}
export const modeStrMap = name => [
export const modeStrMap = (name: string) => [
`${name} is available and the auction hasnt started`,
`${name} is available and the auction has been started`,
`${name} is taken and currently owned by someone`,

View File

@ -11,6 +11,7 @@ import {
GetCurrentBlockRequest
} from './types';
import { Token } from 'types/network';
import { IHexStrWeb3Transaction, IHexStrTransaction } from 'libs/transaction';
export default class EtherscanRequests extends RPCRequests {
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 {
module: 'proxy',
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 {
module: 'proxy',
action: 'eth_call',

View File

@ -41,10 +41,10 @@ export default class RPCClient {
}).then(r => r.json());
};
private createHeaders = headerObject => {
private createHeaders = (headerObject: HeadersInit) => {
const headers = new Headers();
Object.keys(headerObject).forEach(name => {
headers.append(name, headerObject[name]);
Object.entries(headerObject).forEach(([name, value]) => {
headers.append(name, value);
});
return headers;
};

View File

@ -2,7 +2,6 @@ import BN from 'bn.js';
import { IHexStrTransaction } from 'libs/transaction';
import { Wei, TokenValue } from 'libs/units';
import { stripHexPrefix } from 'libs/values';
import { hexToNumber } from 'utils/formatters';
import { INode, TxObj, TransactionData, TransactionReceipt } from '../INode';
import RPCClient from './client';
import RPCRequests from './requests';
@ -18,6 +17,7 @@ import {
isValidRawTxApi
} from 'libs/validators';
import { Token } from 'types/network';
import { hexToNumber } from 'utils/formatters';
export default class RpcNode implements INode {
public client: RPCClient;

View File

@ -13,14 +13,13 @@ import {
import { hexEncodeData } from './utils';
import { TxObj } from '../INode';
import { Token } from 'types/network';
import { IHexStrTransaction } from 'libs/transaction';
export default class RPCRequests {
public getNetVersion() {
return { method: 'net_version' };
}
/* TODO: Fix `| any` on all of these */
public sendRawTx(signedTx: string): SendRawTxRequest | any {
return {
method: 'eth_sendRawTransaction',
@ -28,7 +27,7 @@ export default class RPCRequests {
};
}
public estimateGas(transaction): EstimateGasRequest | any {
public estimateGas(transaction: Partial<IHexStrTransaction>): EstimateGasRequest | any {
return {
method: 'eth_estimateGas',
params: [transaction]

View File

@ -27,7 +27,7 @@ export interface GetAccountsRequest extends RPCRequestBase {
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;
export interface IWeb3Provider {

View File

@ -10,9 +10,9 @@ export interface ITransaction {
gasPrice: Wei;
nonce: BN;
chainId: number;
v;
r;
s;
v: Buffer;
r: Buffer;
s: Buffer;
}
export interface IHexStrTransaction {

View File

@ -6,6 +6,7 @@ import { IFullWallet } from 'libs/wallet';
import { translateRaw } from 'translations';
import { ITransaction, IHexStrTransaction } from '../typings';
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
const computeIndexingHash = (tx: Buffer) => bufferToHex(makeTransaction(tx).hash(false));
@ -75,7 +76,13 @@ const validAddress = (t: ITransaction) => {
};
const makeTransaction = (
t: Partial<Tx> | Partial<ITransaction> | Partial<IHexStrTransaction> | Buffer | string
t:
| Partial<Tx>
| Partial<ITransaction>
| Partial<IHexStrTransaction>
| Buffer
| string
| TransactionFieldValues
) => new Tx(t);
//TODO: check that addresses are always checksummed

View File

@ -184,7 +184,7 @@ export const isValidNonce = (value: string): boolean => {
return valid;
};
function isValidResult(response: JsonRpcResponse, schemaFormat): boolean {
function isValidResult(response: JsonRpcResponse, schemaFormat: typeof schema.RpcNode): boolean {
return v.validate(response, schemaFormat).valid;
}
@ -204,9 +204,25 @@ function formatErrors(response: JsonRpcResponse, apiType: string) {
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) => (
apiName,
cb?
apiName: API_NAME,
cb?: (res: JsonRpcResponse) => any
) => {
if (!isValidResult(response, schemaType)) {
if (cb) {
@ -218,45 +234,44 @@ const isValidEthCall = (response: JsonRpcResponse, schemaType: typeof schema.Rpc
};
export const isValidGetBalance = (response: JsonRpcResponse) =>
isValidEthCall(response, schema.RpcNode)('Get Balance');
isValidEthCall(response, schema.RpcNode)(API_NAME.Get_Balance);
export const isValidEstimateGas = (response: JsonRpcResponse) =>
isValidEthCall(response, schema.RpcNode)('Estimate Gas');
isValidEthCall(response, schema.RpcNode)(API_NAME.Estimate_Gas);
export const isValidCallRequest = (response: JsonRpcResponse) =>
isValidEthCall(response, schema.RpcNode)('Call Request');
isValidEthCall(response, schema.RpcNode)(API_NAME.Call_Request);
export const isValidTokenBalance = (response: JsonRpcResponse) =>
isValidEthCall(response, schema.RpcNode)('Token Balance', () => ({
isValidEthCall(response, schema.RpcNode)(API_NAME.Token_Balance, () => ({
result: 'Failed'
}));
export const isValidTransactionCount = (response: JsonRpcResponse) =>
isValidEthCall(response, schema.RpcNode)('Transaction Count');
isValidEthCall(response, schema.RpcNode)(API_NAME.Transaction_Count);
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) =>
isValidEthCall(response, schema.RpcNode)('Transaction Receipt');
isValidEthCall(response, schema.RpcNode)(API_NAME.Transaction_Receipt);
export const isValidCurrentBlock = (response: JsonRpcResponse) =>
isValidEthCall(response, schema.RpcNode)('Current Block');
isValidEthCall(response, schema.RpcNode)(API_NAME.Current_Block);
export const isValidRawTxApi = (response: JsonRpcResponse) =>
isValidEthCall(response, schema.RpcNode)('Raw Tx');
isValidEthCall(response, schema.RpcNode)(API_NAME.Raw_Tx);
export const isValidSendTransaction = (response: JsonRpcResponse) =>
isValidEthCall(response, schema.RpcNode)('Send Transaction');
isValidEthCall(response, schema.RpcNode)(API_NAME.Send_Transaction);
export const isValidSignMessage = (response: JsonRpcResponse) =>
isValidEthCall(response, schema.RpcNode)('Sign Message');
isValidEthCall(response, schema.RpcNode)(API_NAME.Sign_Message);
export const isValidGetAccounts = (response: JsonRpcResponse) =>
isValidEthCall(response, schema.RpcNode)('Get Accounts');
isValidEthCall(response, schema.RpcNode)(API_NAME.Get_Accounts);
export const isValidGetNetVersion = (response: JsonRpcResponse) =>
isValidEthCall(response, schema.RpcNode)('Net Version');
isValidEthCall(response, schema.RpcNode)(API_NAME.Net_Version);
export const isValidTxHash = (hash: string) =>
hash.substring(0, 2) === '0x' && hash.length === 66 && isValidHex(hash);

View File

@ -1,6 +1,6 @@
import { Wei, toTokenBase } from 'libs/units';
import { addHexPrefix } from 'ethereumjs-util';
import BN from 'bn.js';
import { AppState } from 'reducers';
export function stripHexPrefix(value: string) {
return value.replace('0x', '');
@ -26,16 +26,16 @@ export function sanitizeHex(hex: string) {
export const buildEIP681EtherRequest = (
recipientAddr: string,
chainId: number,
etherValue: { raw: string; value: Wei | '' }
etherValue: AppState['transaction']['fields']['value']
) => `ethereum:${recipientAddr}${chainId !== 1 ? `@${chainId}` : ''}?value=${etherValue.raw}e18`;
export const buildEIP681TokenRequest = (
recipientAddr: string,
contractAddr: string,
chainId: number,
tokenValue: { raw: string; value: Wei | '' },
tokenValue: AppState['transaction']['meta']['tokenTo'],
decimal: number,
gasLimit: { raw: string; value: BN | null }
gasLimit: AppState['transaction']['fields']['gasLimit']
) =>
`ethereum:${contractAddr}${
chainId !== 1 ? `@${chainId}` : ''

View File

@ -7,11 +7,11 @@ import { IFullWallet } from '../IWallet';
import { translateRaw } from 'translations';
export class LedgerWallet extends DeterministicWallet implements IFullWallet {
private ethApp: any;
private ethApp: ledger.eth;
constructor(address: string, dPath: string, index: number) {
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);
});
}
@ -50,18 +50,22 @@ export class LedgerWallet extends DeterministicWallet implements IFullWallet {
const msgHex = Buffer.from(msg).toString('hex');
return new Promise((resolve, reject) => {
this.ethApp.signPersonalMessage_async(this.getPath(), msgHex, async (signed, error) => {
if (error) {
return reject(this.ethApp.getError(error));
}
this.ethApp.signPersonalMessage_async(
this.getPath(),
msgHex,
async (signed: any, error: any) => {
if (error) {
return reject((this.ethApp as any).getError(error));
}
try {
const combined = signed.r + signed.s + signed.v;
resolve(bufferToHex(combined));
} catch (err) {
reject(err);
try {
const combined = signed.r + signed.s + signed.v;
resolve(bufferToHex(combined));
} catch (err) {
reject(err);
}
}
});
);
});
}

View File

@ -30,7 +30,7 @@ export class TrezorWallet extends DeterministicWallet implements IFullWallet {
cleanedTx.data,
chainId,
// Callback
result => {
(result: any) => {
if (!result.success) {
return reject(Error(result.error));
}
@ -64,7 +64,7 @@ export class TrezorWallet extends DeterministicWallet implements IFullWallet {
return new Promise((resolve, reject) => {
(TrezorConnect as any).ethereumGetAddress(
dPath + '/' + index,
res => {
(res: any) => {
if (res.error) {
reject(res.error);
} else {

View File

@ -15,9 +15,9 @@ const INITIAL_STATE: State = {
gasPriceStatus: null
};
const getPostFix = (str: string) => {
const getPostFix = (str: string): keyof typeof RequestStatus => {
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 => ({

View File

@ -22,14 +22,14 @@ export const resetHOF = (
if (includeFields) {
(includeFields as any[]).forEach(fieldName => {
stateCopy[fieldName] = returnState[fieldName];
(stateCopy as any)[fieldName] = (returnState as any)[fieldName];
});
return returnCb ? returnCb(state, returnState) : { ...stateCopy };
}
if (excludeFields) {
(excludeFields as any[]).forEach(fieldName => {
returnState[fieldName] = state[fieldName];
(returnState as any)[fieldName] = (state as any)[fieldName];
});
}

View File

@ -15,7 +15,7 @@ export function* pruneCustomNetworks(): SagaIterator {
//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 }),
{}
);

View File

@ -6,6 +6,7 @@ import { changeNodeForce, TypeKeys, web3SetNode } from 'actions/config';
import { getNodeId, getStaticAltNodeIdToWeb3, getNetworkNameByChainId } from 'selectors/config';
import { setupWeb3Node, Web3Service } from 'libs/nodes/web3';
import { Web3NodeConfig } from 'types/node';
import { SetWalletAction } from 'actions/wallet';
export function* initWeb3Node(): SagaIterator {
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
export function* unsetWeb3NodeOnWalletEvent(action): SagaIterator {
export function* unsetWeb3NodeOnWalletEvent(action: SetWalletAction): SagaIterator {
const node = yield select(getNodeId);
const newWallet = action.payload;
const isWeb3Wallet = newWallet instanceof Web3Wallet;
@ -52,6 +53,5 @@ export function* unsetWeb3Node(): SagaIterator {
export const web3 = [
takeEvery(TypeKeys.CONFIG_NODE_WEB3_UNSET, unsetWeb3Node),
takeEvery(WalletTypeKeys.WALLET_SET, unsetWeb3NodeOnWalletEvent),
takeEvery(WalletTypeKeys.WALLET_RESET, unsetWeb3NodeOnWalletEvent)
takeEvery(WalletTypeKeys.WALLET_SET, unsetWeb3NodeOnWalletEvent)
];

View File

@ -96,7 +96,7 @@ export function* updateWalletTokenValues(): SagaIterator {
const calls = wallets.map(w => {
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++) {
if (!tokenBalances[i].error) {

View File

@ -45,7 +45,7 @@ function* resolveDomain(): SagaIterator {
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),
err: call(delay, 10000)
});

View File

@ -3,7 +3,13 @@ import { INode } from 'libs/nodes/INode';
import { getNodeLib } from 'selectors/config';
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 result: string = yield apply(node, node.sendCallRequest, [{ data, to }]);
const decodedResult = yield call(decoder, result);

View File

@ -8,7 +8,12 @@ import {
import { select, call, put, takeEvery } from 'redux-saga/effects';
import { SagaIterator } from 'redux-saga';
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 { validateInput, IInput } from 'sagas/transaction/validationHelpers';
import { validNumber, validDecimal } from 'libs/validators';
@ -19,7 +24,10 @@ export function* setCurrentValue(action: SetCurrentValueAction): SagaIterator {
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 unit: string = yield select(getUnit);

View File

@ -13,7 +13,7 @@ export function* getTokenBalances(wallet: IWallet, tokens: Token[]) {
const node: INode = yield select(getNodeLib);
const address: string = yield apply(wallet, wallet.getAddressString);
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];
return acc;
}, {});

View File

@ -263,7 +263,7 @@ export function* unlockWeb3(): SagaIterator {
yield call(initWeb3Node);
yield put(changeNodeIntent('web3'));
yield take(
action =>
(action: any) =>
action.type === ConfigTypeKeys.CONFIG_NODE_CHANGE && action.payload.nodeId === 'web3'
);

View File

@ -86,7 +86,7 @@ export function getSelectedNode(state: AppState) {
return getNodes(state).selectedNode;
}
export function isNodeChanging(state): boolean {
export function isNodeChanging(state: AppState): boolean {
return getSelectedNode(state).pending;
}

View File

@ -75,7 +75,7 @@ export function isWalletFormatSupportedOnNetwork(state: AppState, format: Wallet
}
export function unSupportedWalletFormatsOnNetwork(state: AppState): WalletName[] {
const supportedFormats = walletNames.filter(walletName =>
const supportedFormats = walletNames.filter((walletName: WalletName) =>
isWalletFormatSupportedOnNetwork(state, walletName)
);
return difference(walletNames, supportedFormats);

View File

@ -1,13 +1,20 @@
import { AppState } from 'reducers';
import { ICurrentTo, ICurrentValue } from 'selectors/transaction';
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']) =>
Object.keys(transactionFields).reduce(
(obj, currFieldName) => {
Object.keys(transactionFields).reduce<TransactionFieldValues>(
(obj, currFieldName: keyof TransactionFields) => {
const currField = transactionFields[currFieldName];
return { ...obj, [currFieldName]: currField.value };
},
{} as any //TODO: Fix types
{} as TransactionFieldValues
);
export const isFullTx = (

View File

@ -81,7 +81,10 @@ const serializedAndTransactionFieldsMatch = (state: AppState, isLocallySigned: b
const t2 = getTransactionFields(makeTransaction(serialzedTransaction));
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
const transactionsMatch = checkValidity(t1) && checkValidity(t2);
// if its signed then verify the signature too

View File

@ -5,7 +5,7 @@ import {
State as TransactionState
} from 'reducers/transaction';
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 { createLogger } from 'redux-logger';
import createSagaMiddleware from 'redux-saga';
@ -24,7 +24,7 @@ const configureStore = () => {
});
const sagaMiddleware = createSagaMiddleware();
let middleware;
let store;
let store: Store<AppState>;
if (process.env.NODE_ENV !== 'production') {
middleware = composeWithDevTools(
@ -45,7 +45,7 @@ const configureStore = () => {
const savedTransactionState = loadStatePropertyOrEmptyObject<TransactionState>('transaction');
const persistedInitialState = {
const persistedInitialState: Partial<AppState> = {
transaction: {
...transactionInitialState,
fields: {
@ -65,10 +65,10 @@ const configureStore = () => {
...rehydrateConfigAndCustomTokenState()
};
store = createStore(RootReducer, persistedInitialState, middleware);
store = createStore<AppState>(RootReducer, persistedInitialState as any, 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]);
});

View File

@ -3,9 +3,20 @@ import React from 'react';
import { getLanguageSelection } from 'selectors/config';
import { configuredStore } from '../store';
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/el.json'),
require('./lang/en.json'),

View File

@ -0,0 +1,3 @@
declare module 'ethereum-blockies' {
export function toDataUrl(address: string): string;
}

24
common/typescript/ethereumjs-abi.d.ts vendored Normal file
View File

@ -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;
}

View File

@ -92,7 +92,7 @@ declare module 'ethereumjs-tx' {
* sign a transaction with a given a private key
* @param {Buffer} privateKey
*/
public sign(privateKey: Buffer);
public sign(privateKey: Buffer): void;
/**
* The amount of gas paid for the data in this tx

View File

@ -65,7 +65,7 @@ declare module 'ethereumjs-wallet/hdkey' {
/**
* @description derive a node based on a child index
*/
deriveChild(index): IHDNodePublic;
deriveChild(index: any): IHDNodePublic;
/**
* @description return a Wallet instance
@ -97,7 +97,7 @@ declare module 'ethereumjs-wallet/hdkey' {
/**
* @description derive a node based on a child index
*/
deriveChild(index): IHDNodePrivate | IHDNodePublic;
deriveChild(index: any): IHDNodePrivate | IHDNodePublic;
/**
* @description return a Wallet instance

15
common/typescript/ethjs-util.d.ts vendored Normal file
View File

@ -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;
}

11
common/typescript/hdkey.d.ts vendored Normal file
View File

@ -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;
}
}

10
common/typescript/idna-uts46.d.ts vendored Normal file
View File

@ -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;
}

45
common/typescript/ledgerco.d.ts vendored Normal file
View File

@ -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;
}
}

View File

@ -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> {}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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';

View File

@ -1,13 +1,20 @@
import qs from 'query-string';
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 containsAll = checkingObjectKeys.map(key => has(containingObject, key));
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);
}
@ -28,5 +35,5 @@ export function isPositiveInteger(n: number) {
return Number.isInteger(n) && n > 0;
}
export const getValues = (...args) =>
export const getValues = (...args: any[]) =>
args.reduce((acc, currArg) => [...acc, ...Object.values(currArg)], []);

View File

@ -2,6 +2,7 @@ export const REDUX_STATE = 'REDUX_STATE';
import { State as SwapState } from 'reducers/swap';
import { IWallet, WalletConfig } from 'libs/wallet';
import { sha256 } from 'ethereumjs-util';
import { AppState } from 'reducers';
export function loadState<T>(): T | undefined {
try {
@ -26,8 +27,8 @@ export const saveState = (state: any) => {
export type SwapLocalStorage = SwapState;
export function loadStatePropertyOrEmptyObject<T>(key: string): T | undefined {
const localStorageState = loadState();
export function loadStatePropertyOrEmptyObject<T>(key: keyof AppState): T | undefined {
const localStorageState: Partial<AppState> | undefined = loadState();
if (localStorageState) {
if (localStorageState.hasOwnProperty(key)) {
return localStorageState[key] as T;

View File

@ -18,8 +18,8 @@ export default function(element: React.ReactElement<any>, opts: PrintOptions = {
// Convert popupFeatures into a key=value,key=value string. See
// https://developer.mozilla.org/en-US/docs/Web/API/Window/open#Window_features
// for more information.
const featuresStr = Object.keys(options.popupFeatures)
.map(key => `${key}=${options.popupFeatures[key]}`)
const featuresStr = Object.entries(options.popupFeatures)
.map(([key, value]) => `${key}=${value}`)
.join(',');
const popup = window.open('about:blank', 'printWindow', featuresStr);

View File

@ -6,7 +6,7 @@ export function dedupeCustomTokens(networkTokens: Token[], customTokens: Token[]
}
// 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.address] = true;
return prev;

View File

@ -6,7 +6,7 @@ import { APP_TITLE } from '../constants';
const isDevelopment = process.env.NODE_ENV !== 'production';
// Cached reference, preventing recreations
let window;
let window: BrowserWindow | null;
// Construct new BrowserWindow
export default function getWindow() {
@ -39,7 +39,7 @@ export default function getWindow() {
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
ev.preventDefault();
@ -53,13 +53,13 @@ export default function getWindow() {
});
window.webContents.on('did-finish-load', () => {
updater(window);
updater(window!);
});
window.webContents.on('devtools-opened', () => {
window.focus();
window!.focus();
setImmediate(() => {
window.focus();
window!.focus();
});
});

View File

@ -54,19 +54,24 @@
"zxcvbn": "4.4.2"
},
"devDependencies": {
"@types/bip39": "2.4.0",
"@types/classnames": "2.2.3",
"@types/enzyme": "3.1.8",
"@types/enzyme-adapter-react-16": "1.0.1",
"@types/history": "4.6.2",
"@types/jest": "22.2.0",
"@types/lodash": "4.14.104",
"@types/qrcode": "0.8.0",
"@types/qrcode.react": "0.6.3",
"@types/query-string": "5.1.0",
"@types/rc-slider": "8.2.3",
"@types/react": "16.0.40",
"@types/react-dom": "16.0.4",
"@types/react-redux": "5.0.15",
"@types/react-router-dom": "4.2.4",
"@types/react-router-redux": "5.0.12",
"@types/react-select": "1.2.3",
"@types/react-transition-group": "2.0.7",
"@types/redux-logger": "3.0.5",
"@types/uuid": "3.4.3",
"@types/webpack-env": "1.13.4",
@ -131,8 +136,8 @@
"webpack-hot-middleware": "2.21.0",
"webpack-sources": "1.0.1",
"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": {
"freezer": "webpack --config=./webpack_config/webpack.freezer.js && node ./dist/freezer.js",
@ -142,10 +147,14 @@
"prebuild": "check-node-version --package",
"build:downloadable": "webpack --config webpack_config/webpack.html.js",
"prebuild:downloadable": "check-node-version --package",
"build:electron": "webpack --config webpack_config/webpack.electron-prod.js && node webpack_config/buildElectron.js",
"build:electron:osx": "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",
"build:electron":
"webpack --config webpack_config/webpack.electron-prod.js && node webpack_config/buildElectron.js",
"build:electron:osx":
"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",
"test:coverage": "jest --config=jest_config/jest.config.json --coverage",
"test": "jest --config=jest_config/jest.config.json",
@ -157,14 +166,18 @@
"predev": "check-node-version --package",
"dev:https": "HTTPS=true node webpack_config/devServer.js",
"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: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'",
"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: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/**/*",
"tscheck": "tsc --noEmit",
"start": "npm run dev",
"precommit": "lint-staged",
"formatAll": "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\"",
"formatAll":
"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"
},
"lint-staged": {

View File

@ -6,10 +6,10 @@ configuredStore.getState();
describe('Contracts JSON', () => {
Object.keys(CONTRACTS).forEach(network => {
it(`${network} contracts array properly formatted`, () => {
const contracts = CONTRACTS[network];
const addressCollisionMap = {};
const contracts: any = (CONTRACTS as any)[network];
const addressCollisionMap: any = {};
contracts.forEach(contract => {
contracts.forEach((contract: any) => {
if (contract.address && !isValidETHAddress(contract.address)) {
throw Error(`Contract '${contract.name}' has invalid address '${contract.address}'`);
}

View File

@ -6,11 +6,11 @@ configuredStore.getState();
describe('Tokens JSON', () => {
Object.keys(TOKENS).forEach(network => {
it(`${network} tokens array properly formatted`, () => {
const tokens = TOKENS[network];
const addressCollisionMap = {};
const symbolCollisionMap = {};
const tokens = (TOKENS as any)[network];
const addressCollisionMap: any = {};
const symbolCollisionMap: any = {};
tokens.forEach(token => {
tokens.forEach((token: any) => {
if (!isValidETHAddress(token.address)) {
throw Error(`Token ${token.symbol} has invalid contract address '${token.address}'`);
}

View File

@ -1,5 +1,5 @@
import { RPCNode } from '../../common/libs/nodes';
import { Validator } from 'jsonschema';
import { Validator, ValidatorResult } from 'jsonschema';
import { schema } from '../../common/libs/validators';
import 'url-search-params-polyfill';
import EtherscanNode from 'libs/nodes/etherscan';
@ -25,6 +25,10 @@ const validRequests = {
}
};
interface RPCTestList {
[key: string]: ((n: RPCNode) => Promise<ValidatorResult>);
}
const testGetBalance = (n: RPCNode) => {
return n.client
.call(n.requests.getBalance(validRequests.address))
@ -44,7 +48,7 @@ const testGetTokenBalance = (n: RPCNode) => {
.then(data => v.validate(data, schema.RpcNode));
};
const RPCTests = {
const RPCTests: RPCTestList = {
getBalance: testGetBalance,
estimateGas: testEstimateGas,
getTokenBalance: testGetTokenBalance

View File

@ -9,7 +9,7 @@ const dockerTag = 'latest';
function promiseFromChildProcess(command: string): Promise<any> {
return new Promise((resolve, reject) => {
return exec(command, (err, stdout) => {
return exec(command, (err: string, stdout: string) => {
err ? reject(err) : resolve(stdout);
});
});

View File

@ -1,5 +1,5 @@
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 { cloneableGenerator, createMockTask } from 'redux-saga/utils';
import {
@ -58,9 +58,9 @@ describe('pollOfflineStatus*', () => {
timeout: true
};
let originalHidden;
let originalOnLine;
let originalRandom;
let originalHidden: any;
let originalOnLine: any;
let originalRandom: any;
beforeAll(() => {
// backup global config
@ -143,16 +143,18 @@ describe('handlePollOfflineStatus*', () => {
});
describe('handleNodeChangeIntent*', () => {
let originalRandom;
let originalRandom: any;
// normal operation variables
const defaultNodeId = selectedNodeExpectedState.initialState.nodeId;
const defaultNodeConfig: StaticNodeConfig = staticNodesExpectedState.initialState[defaultNodeId];
const defaultNodeId: any = selectedNodeExpectedState.initialState.nodeId;
const defaultNodeConfig: any = (staticNodesExpectedState as any).initialState[defaultNodeId];
const newNodeId = Object.keys(staticNodesExpectedState.initialState).reduce(
(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 latestBlock = '0xa';
@ -166,7 +168,7 @@ describe('handleNodeChangeIntent*', () => {
const data = {} as any;
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(defaultNodeId).value).toEqual(put(showNotification('danger', errMsg, 5000)));
expect(gen.next().value).toEqual(
@ -297,7 +299,7 @@ describe('unsetWeb3Node*', () => {
});
describe('unsetWeb3NodeOnWalletEvent*', () => {
const fakeAction = {};
const fakeAction: any = {};
const mockNodeId = 'web3';
const alternativeNodeId = 'eth_mycrypto';
const gen = unsetWeb3NodeOnWalletEvent(fakeAction);
@ -319,7 +321,7 @@ describe('unsetWeb3NodeOnWalletEvent*', () => {
});
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('notWeb3'); //getNodeConfig
expect(gen1.next().done).toEqual(true);
@ -329,7 +331,7 @@ describe('unsetWeb3NodeOnWalletEvent*', () => {
const mockAddress = '0x0';
const mockNetwork = 'ETH';
const mockWeb3Wallet = new Web3Wallet(mockAddress, mockNetwork);
const gen2 = unsetWeb3NodeOnWalletEvent({ payload: mockWeb3Wallet });
const gen2 = unsetWeb3NodeOnWalletEvent({ payload: mockWeb3Wallet } as any);
gen2.next(); //getNode
gen2.next('web3'); //getNodeConfig
expect(gen2.next().done).toEqual(true);

View File

@ -12,7 +12,7 @@ import tokens from 'config/tokens/eth.json';
import { SHAPESHIFT_TOKEN_WHITELIST } from 'api/shapeshift';
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 => {
it(`Should find Token ${t}`, () => {
expect(findToken(t)).toBeTruthy();
@ -87,7 +87,7 @@ describe('swap reducer', () => {
it('should handle SWAP_LOAD_SHAPESHIFT_RATES_SUCCEEDED', () => {
expect(
swap(undefined, swapActions.loadShapeshiftRatesSucceededSwap(shapeshiftApiResponse))
swap(undefined, swapActions.loadShapeshiftRatesSucceededSwap(shapeshiftApiResponse as any))
).toEqual({
...INITIAL_STATE,
isFetchingRates: false,

View File

@ -85,7 +85,7 @@ describe('pollBityOrderStatus*', () => {
error: true,
msg: 'error message'
};
let random;
let random: () => number;
beforeAll(() => {
random = Math.random;
@ -156,7 +156,7 @@ describe('pollShapeshiftOrderStatus*', () => {
error: 'Shapeshift error',
status: 'failed'
};
let random;
let random: () => number;
beforeAll(() => {
random = Math.random;
@ -293,7 +293,7 @@ describe('postBityOrderCreate*', () => {
const data = {} as any;
data.gen = cloneableGenerator(postBityOrderCreate)(action);
let random;
let random: () => number;
beforeAll(() => {
random = Math.random;
Math.random = () => 0.001;
@ -381,7 +381,7 @@ describe('postShapeshiftOrderCreate*', () => {
const data = {} as any;
data.gen = cloneableGenerator(postShapeshiftOrderCreate)(action);
let random;
let random: () => number;
beforeAll(() => {
random = Math.random;
Math.random = () => 0.001;
@ -457,7 +457,7 @@ describe('bityOrderTimeRemaining*', () => {
orderTimestampCreatedISOString: new Date(orderTimeExpired).toISOString(),
validFor: swapValidFor
};
let random;
let random: () => number;
const data = {} as any;
data.gen = cloneableGenerator(bityOrderTimeRemaining)();
@ -538,7 +538,7 @@ describe('shapeshiftOrderTimeRemaining*', () => {
orderTimestampCreatedISOString: new Date(orderTimeExpired).toISOString(),
validFor: swapValidFor
};
let random;
let random: () => number;
const data = {} as any;
data.gen = cloneableGenerator(shapeshiftOrderTimeRemaining)();

View File

@ -36,7 +36,7 @@ describe('loadBityRates*', () => {
}
};
const err = { message: 'error' };
let random;
let random: () => number;
beforeAll(() => {
random = Math.random;
@ -103,7 +103,7 @@ describe('loadShapeshiftRates*', () => {
}
};
const err = 'error';
let random;
let random: () => number;
beforeAll(() => {
random = Math.random;
@ -125,7 +125,7 @@ describe('loadShapeshiftRates*', () => {
it('should put loadShapeshiftRatesSucceededSwap', () => {
expect(gen1.next({ tokens: apiResponse }).value).toEqual(
put(loadShapeshiftRatesSucceededSwap(apiResponse))
put(loadShapeshiftRatesSucceededSwap(apiResponse as any))
);
});

View File

@ -36,7 +36,7 @@ describe('broadcastTransactionWrapper*', () => {
blockExplorer: 'blockExplorer'
};
let random;
let random: () => number;
const func: any = () => undefined;
const action: any = {};
const gens: any = {};

View File

@ -10,8 +10,9 @@ import {
valueHandler
} from 'sagas/transaction/current/currentValue';
import { cloneableGenerator, SagaIteratorClone } from 'redux-saga/utils';
import { SagaIterator } from 'redux-saga';
const itShouldBeDone = gen => {
const itShouldBeDone = (gen: SagaIterator) => {
it('should be done', () => {
expect(gen.next().done).toEqual(true);
});
@ -83,7 +84,12 @@ describe('setCurrentValue*', () => {
});
describe('revalidateCurrentValue*', () => {
const sharedLogic = (gen, etherTransaction, currVal, reparsedValue) => {
const sharedLogic = (
gen: SagaIterator,
etherTransaction: boolean,
currVal: any,
reparsedValue: boolean
) => {
it('should select isEtherTransaction', () => {
expect(gen.next().value).toEqual(select(isEtherTransaction));
});
@ -159,7 +165,7 @@ describe('revalidateCurrentValue*', () => {
});
describe('reparseCurrentValue*', () => {
const sharedLogic = gen => {
const sharedLogic = (gen: SagaIterator) => {
it('should select getDecimal', () => {
expect(gen.next().value).toEqual(select(getDecimal));
});

View File

@ -12,9 +12,10 @@ import {
} from 'sagas/transaction/fields/fields';
import { cloneableGenerator } from 'redux-saga/utils';
import { setGasPriceField } from 'actions/transaction';
import { SagaIterator } from 'redux-saga';
configuredStore.getState();
const itShouldBeDone = gen => {
const itShouldBeDone = (gen: SagaIterator) => {
it('should be done', () => {
expect(gen.next().done).toEqual(true);
});

View File

@ -7,9 +7,10 @@ import { bufferToHex, toBuffer } from 'ethereumjs-util';
import { getTokenTo, getData } from 'selectors/transaction';
import { handleTokenTo, handleTokenValue } from 'sagas/transaction/meta/token';
import { cloneableGenerator } from 'redux-saga/utils';
import { SagaIterator } from 'redux-saga';
configuredStore.getState();
const itShouldBeDone = gen => {
const itShouldBeDone = (gen: SagaIterator) => {
it('should be done', () => {
expect(gen.next().done).toEqual(true);
});

View File

@ -17,11 +17,13 @@ import {
import { encodeTransfer } from 'libs/transaction';
import { bufferToHex } from 'ethereumjs-util';
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 { 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', () => {
expect(gen.next().done).toEqual(true);
});
@ -29,11 +31,11 @@ const itShouldBeDone = gen => {
describe('handleSetUnitMeta*', () => {
const expectedStart = (
gen,
previousUnit,
currentUnit,
prevUnitIsNetworkUnit,
currUnitIsNetworkUnit
gen: SagaIterator,
previousUnit: string,
currentUnit: string,
prevUnitIsNetworkUnit: boolean,
currUnitIsNetworkUnit: boolean
) => {
it('should select getPreviousUnit', () => {
expect(gen.next().value).toEqual(select(getPreviousUnit));
@ -121,7 +123,7 @@ describe('handleSetUnitMeta*', () => {
});
describe('etherToToken || tokenToToken', () => {
const sharedLogicA = (gen, decimal, currentUnit) => {
const sharedLogicA = (gen: SagaIteratorClone, decimal: number, currentUnit: string) => {
it('should select getToken with 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', () => {
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', () => {
@ -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 = {
data: { raw: bufferToHex(data), value: data },
to: { raw: '', value: Address(toAddress) },

View File

@ -14,7 +14,7 @@ describe('handleFromRequest*', () => {
const fromAddress = '0xa';
const gens: any = {};
gens.gen = cloneableGenerator(handleFromRequest)();
let random;
let random: () => number;
beforeAll(() => {
random = Math.random;

View File

@ -19,7 +19,7 @@ import {
localGasEstimation,
setAddressMessageGasLimit
} from 'sagas/transaction/network/gas';
import { cloneableGenerator } from 'redux-saga/utils';
import { cloneableGenerator, SagaIteratorClone } from 'redux-saga/utils';
import { Wei } from 'libs/units';
import { TypeKeys as ConfigTypeKeys } from 'actions/config';
@ -117,7 +117,7 @@ describe('estimateGas*', () => {
const gens: { [name: string]: any } = {};
gens.successCase = cloneableGenerator(estimateGas)();
let random;
let random: () => number;
beforeAll(() => {
random = Math.random;
Math.random = () => 0.001;
@ -251,8 +251,8 @@ describe('localGasEstimation', () => {
describe('setAddressMessageGasLimit*', () => {
const gens = cloneableGenerator(setAddressMessageGasLimit)();
const gen = gens.clone();
let noAutoGen;
let noMessageGen;
let noAutoGen: SagaIteratorClone;
let noMessageGen: SagaIteratorClone;
const addressMessage = {
gasLimit: 123456,
msg: 'Thanks for donating, er, investing in SCAM'

View File

@ -21,7 +21,7 @@ describe('handleNonceRequest*', () => {
const gens: any = {};
gens.gen = cloneableGenerator(handleNonceRequest)();
let random;
let random: () => number;
beforeAll(() => {
random = Math.random;

Some files were not shown because too many files have changed in this diff Show More