diff --git a/common/actions/swap/actionCreators.ts b/common/actions/swap/actionCreators.ts index e638044f..2958a84f 100644 --- a/common/actions/swap/actionCreators.ts +++ b/common/actions/swap/actionCreators.ts @@ -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, diff --git a/common/api/bity.ts b/common/api/bity.ts index 8ba10d8d..8f74f70d 100644 --- a/common/api/bity.ts +++ b/common/api/bity.ts @@ -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) }; diff --git a/common/api/gas.ts b/common/api/gas.ts index 1f0400c1..3bdd3b70 100644 --- a/common/api/gas.ts +++ b/common/api/gas.ts @@ -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 { 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)[] = [ + 'safeLow', + 'standard', + 'fast', + 'fastest' + ]; keys.forEach(key => { if (typeof res[key] !== 'number') { throw new Error( diff --git a/common/api/shapeshift.ts b/common/api/shapeshift.ts index 01100505..84244709 100644 --- a/common/api/shapeshift.ts +++ b/common/api/shapeshift.ts @@ -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); diff --git a/common/components/AmountField.tsx b/common/components/AmountField.tsx index 9e71fb67..3095835f 100644 --- a/common/components/AmountField.tsx +++ b/common/components/AmountField.tsx @@ -37,5 +37,8 @@ export const AmountField: React.SFC = ({ /> ); -const isAmountValid = (raw, customValidator, isValid) => - customValidator ? customValidator(raw) : isValid; +const isAmountValid = ( + raw: string, + customValidator: ((rawAmount: string) => boolean) | undefined, + isValid: boolean +) => (customValidator ? customValidator(raw) : isValid); diff --git a/common/components/BalanceSidebar/EquivalentValues.tsx b/common/components/BalanceSidebar/EquivalentValues.tsx index 4fe011d6..3cf19b24 100644 --- a/common/components/BalanceSidebar/EquivalentValues.tsx +++ b/common/components/BalanceSidebar/EquivalentValues.tsx @@ -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 { @@ -110,7 +118,7 @@ class EquivalentValues extends React.Component { } } - public selectOption = equivalentValues => { + public selectOption = (equivalentValues: Option) => { this.setState({ equivalentValues }); }; @@ -120,28 +128,38 @@ class EquivalentValues extends React.Component { 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 = '' }) => ( -
- - {!!symbol && {symbol}} - {rate}{' '} + const Value = (props: ValueProps) => ( +
+ + {!!props.symbol && ( + {props.symbol} + )} + {props.rate}{' '} @@ -157,7 +175,7 @@ class EquivalentValues extends React.Component { // 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 { 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 { // 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 }; }); } diff --git a/common/components/BalanceSidebar/Promos.tsx b/common/components/BalanceSidebar/Promos.tsx index fdc5fa94..2c59325a 100644 --- a/common/components/BalanceSidebar/Promos.tsx +++ b/common/components/BalanceSidebar/Promos.tsx @@ -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) => ( {children} diff --git a/common/components/BalanceSidebar/TokenBalances/Balances.tsx b/common/components/BalanceSidebar/TokenBalances/Balances.tsx index 4f3fe566..156db5fe 100644 --- a/common/components/BalanceSidebar/TokenBalances/Balances.tsx +++ b/common/components/BalanceSidebar/TokenBalances/Balances.tsx @@ -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 { - 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((prev, t) => { prev[t.symbol] = !t.balance.isZero(); return prev; }, {}); diff --git a/common/components/GasLimitFieldFactory/GasLimitInputFactory.tsx b/common/components/GasLimitFieldFactory/GasLimitInputFactory.tsx index cc5dc6d3..38a5e7d1 100644 --- a/common/components/GasLimitFieldFactory/GasLimitInputFactory.tsx +++ b/common/components/GasLimitFieldFactory/GasLimitInputFactory.tsx @@ -13,7 +13,7 @@ interface StateProps { } interface OwnProps { - withProps(props: CallBackProps); + withProps(props: CallBackProps): null | React.ReactElement; onChange(value: React.FormEvent): void; } diff --git a/common/components/GenerateKeystoreModal/index.tsx b/common/components/GenerateKeystoreModal/index.tsx index 6e66ffce..c67d3723 100644 --- a/common/components/GenerateKeystoreModal/index.tsx +++ b/common/components/GenerateKeystoreModal/index.tsx @@ -41,9 +41,9 @@ export default class GenerateKeystoreModal extends React.Component } } - public componentWillReceiveProps(nextProps) { + public componentWillReceiveProps(nextProps: Props) { if (nextProps.privateKey !== this.props.privateKey) { - this.setState({ privateKey: nextProps.privateKey }); + this.setState({ privateKey: nextProps.privateKey || '' }); } } diff --git a/common/components/Header/components/CustomNodeModal.tsx b/common/components/Header/components/CustomNodeModal.tsx index 6805a948..cc86790e 100644 --- a/common/components/Header/components/CustomNodeModal.tsx +++ b/common/components/Header/components/CustomNodeModal.tsx @@ -17,7 +17,7 @@ import { Input } from 'components/ui'; const CUSTOM = 'custom'; interface InputProps { - name: string; + name: keyof Omit; placeholder?: string; type?: string; autoComplete?: 'off'; diff --git a/common/components/LogOutPrompt.tsx b/common/components/LogOutPrompt.tsx index dadde8f1..4e3281df 100644 --- a/common/components/LogOutPrompt.tsx +++ b/common/components/LogOutPrompt.tsx @@ -18,7 +18,7 @@ interface State { } class LogOutPromptClass extends React.Component { - constructor(props) { + constructor(props: Props) { super(props); this.state = { nextLocation: null, diff --git a/common/components/TXMetaDataPanel/components/SimpleGas.tsx b/common/components/TXMetaDataPanel/components/SimpleGas.tsx index 8b6fa1e8..5469b29c 100644 --- a/common/components/TXMetaDataPanel/components/SimpleGas.tsx +++ b/common/components/TXMetaDataPanel/components/SimpleGas.tsx @@ -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 { diff --git a/common/components/UnitDropDown/UnitDropDown.tsx b/common/components/UnitDropDown/UnitDropDown.tsx index ab643fd7..ebc56176 100644 --- a/common/components/UnitDropDown/UnitDropDown.tsx +++ b/common/components/UnitDropDown/UnitDropDown.tsx @@ -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 { /> ); } - private handleOnChange = unit => { + private handleOnChange = (unit: Option) => { + if (!unit.value) { + throw Error('No unit value found'); + } this.props.setUnitMeta(unit.value); }; } diff --git a/common/components/WalletDecrypt/WalletDecrypt.tsx b/common/components/WalletDecrypt/WalletDecrypt.tsx index b94a1c67..465c9e8f 100644 --- a/common/components/WalletDecrypt/WalletDecrypt.tsx +++ b/common/components/WalletDecrypt/WalletDecrypt.tsx @@ -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); diff --git a/common/components/WalletDecrypt/components/DeterministicWalletsModal.tsx b/common/components/WalletDecrypt/components/DeterministicWalletsModal.tsx index dbf0c0d8..9fc02f04 100644 --- a/common/components/WalletDecrypt/components/DeterministicWalletsModal.tsx +++ b/common/components/WalletDecrypt/components/DeterministicWalletsModal.tsx @@ -73,7 +73,7 @@ class DeterministicWalletsModalClass extends React.PureComponent { 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 { } }; - private selectAddress(selectedAddress, selectedAddrIndex) { + private selectAddress(selectedAddress: string, selectedAddrIndex: number) { this.setState({ selectedAddress, selectedAddrIndex }); } diff --git a/common/components/WalletDecrypt/components/LedgerNano.tsx b/common/components/WalletDecrypt/components/LedgerNano.tsx index 0aa5b392..79f80374 100644 --- a/common/components/WalletDecrypt/components/LedgerNano.tsx +++ b/common/components/WalletDecrypt/components/LedgerNano.tsx @@ -129,7 +129,7 @@ class LedgerNanoSDecryptClass extends PureComponent { 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 { isLoading: false }); }) - .catch(err => { + .catch((err: any) => { if (err && err.metaData && err.metaData.code === 5) { this.showTip(); } diff --git a/common/components/WalletDecrypt/components/Mnemonic.tsx b/common/components/WalletDecrypt/components/Mnemonic.tsx index 9b8384ce..aef10c66 100644 --- a/common/components/WalletDecrypt/components/Mnemonic.tsx +++ b/common/components/WalletDecrypt/components/Mnemonic.tsx @@ -59,7 +59,7 @@ class MnemonicDecryptClass extends PureComponent { isValid={isValidMnemonic} isTextareaWhenVisible={true} onChange={this.onMnemonicChange} - onEnter={isValidMnemonic && this.onDWModalOpen} + onEnter={isValidMnemonic ? this.onDWModalOpen : undefined} />
@@ -134,7 +134,7 @@ class MnemonicDecryptClass extends PureComponent { this.setState({ dPath }); }; - private handleUnlock = (address, index) => { + private handleUnlock = (address: string, index: number) => { const { formattedPhrase, pass, dPath } = this.state; this.props.onUnlock({ diff --git a/common/components/WalletDecrypt/components/Trezor.tsx b/common/components/WalletDecrypt/components/Trezor.tsx index 97cebbf5..66f0d7b0 100644 --- a/common/components/WalletDecrypt/components/Trezor.tsx +++ b/common/components/WalletDecrypt/components/Trezor.tsx @@ -108,7 +108,7 @@ class TrezorDecryptClass extends PureComponent { (TrezorConnect as any).getXPubKey( dPath, - res => { + (res: any) => { if (res.success) { this.setState({ dPath, diff --git a/common/components/ui/Dropdown.tsx b/common/components/ui/Dropdown.tsx index 2163ddf4..b68774de 100644 --- a/common/components/ui/Dropdown.tsx +++ b/common/components/ui/Dropdown.tsx @@ -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 { 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 { // use ref to prevent
); })} - {selectedFunction.contract.outputs.map((output, index) => { + {selectedFunction.contract.outputs.map((output: any, index: number) => { const { type, name } = output; const parsedName = name === '' ? index : name; diff --git a/common/containers/Tabs/Contracts/components/Interact/components/InteractForm/index.tsx b/common/containers/Tabs/Contracts/components/Interact/components/InteractForm/index.tsx index 2d44567e..ab001183 100644 --- a/common/containers/Tabs/Contracts/components/Interact/components/InteractForm/index.tsx +++ b/common/containers/Tabs/Contracts/components/Interact/components/InteractForm/index.tsx @@ -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 { 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 { ); } - private handleInput = name => (ev: React.FormEvent) => { + private handleInput = (name: any) => ( + ev: React.FormEvent + ) => { this.props.resetState(); this.setState({ [name]: ev.currentTarget.value }); }; diff --git a/common/containers/Tabs/ENS/components/NameResolve/components/NameOwned.tsx b/common/containers/Tabs/ENS/components/NameResolve/components/NameOwned.tsx index 19e698a7..d56ebd1a 100644 --- a/common/containers/Tabs/ENS/components/NameResolve/components/NameOwned.tsx +++ b/common/containers/Tabs/ENS/components/NameResolve/components/NameOwned.tsx @@ -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; diff --git a/common/containers/Tabs/ENS/components/NameResolve/components/components/ENSTime.tsx b/common/containers/Tabs/ENS/components/NameResolve/components/components/ENSTime.tsx index 8bf7db97..21782302 100644 --- a/common/containers/Tabs/ENS/components/NameResolve/components/components/ENSTime.tsx +++ b/common/containers/Tabs/ENS/components/NameResolve/components/components/ENSTime.tsx @@ -22,7 +22,7 @@ class CountDown extends Component { 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 { this.setState({ timeDisplay }); }; - intervalId = setInterval(setTimeDisplay, 1000); + intervalId = window.setInterval(setTimeDisplay, 1000); setTimeDisplay(); }; } diff --git a/common/containers/Tabs/GenerateWallet/components/WalletTypes.tsx b/common/containers/Tabs/GenerateWallet/components/WalletTypes.tsx index 2074440a..1e633867 100644 --- a/common/containers/Tabs/GenerateWallet/components/WalletTypes.tsx +++ b/common/containers/Tabs/GenerateWallet/components/WalletTypes.tsx @@ -46,7 +46,7 @@ const WalletTypes: React.SFC<{}> = () => {
- {Object.keys(typeInfo).map(type => ( + {Object.keys(typeInfo).map((type: keyof typeof typeInfo) => (

{translate(typeInfo[type].name)}

    diff --git a/common/containers/Tabs/SendTransaction/components/RequestPayment.tsx b/common/containers/Tabs/SendTransaction/components/RequestPayment.tsx index 0f6cd29d..2daf124c 100644 --- a/common/containers/Tabs/SendTransaction/components/RequestPayment.tsx +++ b/common/containers/Tabs/SendTransaction/components/RequestPayment.tsx @@ -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 { public state = { @@ -145,7 +146,7 @@ class RequestPayment extends React.Component { 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 { 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( diff --git a/common/containers/Tabs/Swap/components/CurrencySwap.tsx b/common/containers/Tabs/Swap/components/CurrencySwap.tsx index 5db6cb3a..ac6e9d29 100644 --- a/common/containers/Tabs/Swap/components/CurrencySwap.tsx +++ b/common/containers/Tabs/Swap/components/CurrencySwap.tsx @@ -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 { - public state = { + public state: State = { disabled: true, origin: { label: 'BTC', @@ -57,14 +57,14 @@ export default class CurrencySwap extends PureComponent { 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 { 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 { 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 { 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 { : 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 { 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 { { { - private shapeShiftRateCache = null; + private shapeShiftRateCache: any = null; public componentDidMount() { if (!this.props.isOffline) { @@ -79,7 +80,7 @@ class CurrentRates extends PureComponent { 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 { }; }; - public isValidRates = rates => { + public isValidRates = (rates: Optional) => { return rates && rates.allIds && rates.allIds.length > 0; }; @@ -118,7 +119,7 @@ class CurrentRates extends PureComponent { return fixedRates; }; - public swapEl = (providerURL, providerLogo, children) => { + public swapEl = (providerURL: string, providerLogo: string, children: any) => { return (

    {translate('SWAP_rates')}

    diff --git a/common/containers/Tabs/Swap/components/Rates.tsx b/common/containers/Tabs/Swap/components/Rates.tsx index 8a3c0ff0..d57cdc9b 100644 --- a/common/containers/Tabs/Swap/components/Rates.tsx +++ b/common/containers/Tabs/Swap/components/Rates.tsx @@ -47,7 +47,7 @@ interface State { } export default class Rates extends Component { - public state = { + public state: State = { pairs: {} }; @@ -72,7 +72,7 @@ export default class Rates extends Component { 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; }, {}); diff --git a/common/libs/contracts/ABIFunction.ts b/common/libs/contracts/ABIFunction.ts index a2f39436..cb27143c 100644 --- a/common/libs/contracts/ABIFunction.ts +++ b/common/libs/contracts/ABIFunction.ts @@ -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 diff --git a/common/libs/contracts/index.ts b/common/libs/contracts/index.ts index fb84fd7d..96b04f77 100644 --- a/common/libs/contracts/index.ts +++ b/common/libs/contracts/index.ts @@ -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 diff --git a/common/libs/contracts/types.ts b/common/libs/contracts/types.ts index 861ad080..6252320a 100644 --- a/common/libs/contracts/types.ts +++ b/common/libs/contracts/types.ts @@ -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; +} diff --git a/common/libs/decrypt.ts b/common/libs/decrypt.ts index 7cca2c3d..cdc18c64 100644 --- a/common/libs/decrypt.ts +++ b/common/libs/decrypt.ts @@ -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'); diff --git a/common/libs/ens/index.ts b/common/libs/ens/index.ts index 3e1f8aba..bd219cc5 100644 --- a/common/libs/ens/index.ts +++ b/common/libs/ens/index.ts @@ -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 hasn’t started`, `${name} is available and the auction has been started`, `${name} is taken and currently owned by someone`, diff --git a/common/libs/nodes/etherscan/requests.ts b/common/libs/nodes/etherscan/requests.ts index 05e60ebb..aaea211a 100644 --- a/common/libs/nodes/etherscan/requests.ts +++ b/common/libs/nodes/etherscan/requests.ts @@ -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): CallRequest { return { module: 'proxy', action: 'eth_call', diff --git a/common/libs/nodes/rpc/client.ts b/common/libs/nodes/rpc/client.ts index 58f6a2e1..73f773ba 100644 --- a/common/libs/nodes/rpc/client.ts +++ b/common/libs/nodes/rpc/client.ts @@ -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; }; diff --git a/common/libs/nodes/rpc/index.ts b/common/libs/nodes/rpc/index.ts index 51470743..bee475aa 100644 --- a/common/libs/nodes/rpc/index.ts +++ b/common/libs/nodes/rpc/index.ts @@ -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; diff --git a/common/libs/nodes/rpc/requests.ts b/common/libs/nodes/rpc/requests.ts index 6f2aeb01..af44de55 100644 --- a/common/libs/nodes/rpc/requests.ts +++ b/common/libs/nodes/rpc/requests.ts @@ -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): EstimateGasRequest | any { return { method: 'eth_estimateGas', params: [transaction] diff --git a/common/libs/nodes/web3/types.ts b/common/libs/nodes/web3/types.ts index f596c094..56ee5599 100644 --- a/common/libs/nodes/web3/types.ts +++ b/common/libs/nodes/web3/types.ts @@ -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 { diff --git a/common/libs/transaction/typings.ts b/common/libs/transaction/typings.ts index b7fe7497..d942e580 100644 --- a/common/libs/transaction/typings.ts +++ b/common/libs/transaction/typings.ts @@ -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 { diff --git a/common/libs/transaction/utils/ether.ts b/common/libs/transaction/utils/ether.ts index 30dc8490..25de3cf0 100644 --- a/common/libs/transaction/utils/ether.ts +++ b/common/libs/transaction/utils/ether.ts @@ -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 | Partial | Partial | Buffer | string + t: + | Partial + | Partial + | Partial + | Buffer + | string + | TransactionFieldValues ) => new Tx(t); //TODO: check that addresses are always checksummed diff --git a/common/libs/validators.ts b/common/libs/validators.ts index 848fbafa..617036dc 100644 --- a/common/libs/validators.ts +++ b/common/libs/validators.ts @@ -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); diff --git a/common/libs/values.ts b/common/libs/values.ts index 544c631c..9b298a54 100644 --- a/common/libs/values.ts +++ b/common/libs/values.ts @@ -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}` : '' diff --git a/common/libs/wallet/deterministic/ledger.ts b/common/libs/wallet/deterministic/ledger.ts index 97d76280..036a2539 100644 --- a/common/libs/wallet/deterministic/ledger.ts +++ b/common/libs/wallet/deterministic/ledger.ts @@ -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); + } } - }); + ); }); } diff --git a/common/libs/wallet/deterministic/trezor.ts b/common/libs/wallet/deterministic/trezor.ts index dd08c16b..594c4bca 100644 --- a/common/libs/wallet/deterministic/trezor.ts +++ b/common/libs/wallet/deterministic/trezor.ts @@ -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 { diff --git a/common/reducers/transaction/network/network.ts b/common/reducers/transaction/network/network.ts index 2cb44bfe..f08cb822 100644 --- a/common/reducers/transaction/network/network.ts +++ b/common/reducers/transaction/network/network.ts @@ -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 => ({ diff --git a/common/reducers/transaction/shared.ts b/common/reducers/transaction/shared.ts index 077c2a3a..2a21a19e 100644 --- a/common/reducers/transaction/shared.ts +++ b/common/reducers/transaction/shared.ts @@ -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]; }); } diff --git a/common/sagas/config/network.ts b/common/sagas/config/network.ts index 7f75e9c4..3974f0fd 100644 --- a/common/sagas/config/network.ts +++ b/common/sagas/config/network.ts @@ -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 }), {} ); diff --git a/common/sagas/config/web3.ts b/common/sagas/config/web3.ts index 5da68c91..fb0945a4 100644 --- a/common/sagas/config/web3.ts +++ b/common/sagas/config/web3.ts @@ -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) ]; diff --git a/common/sagas/deterministicWallets.ts b/common/sagas/deterministicWallets.ts index d4e7164b..da15d31b 100644 --- a/common/sagas/deterministicWallets.ts +++ b/common/sagas/deterministicWallets.ts @@ -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) { diff --git a/common/sagas/ens/ens.ts b/common/sagas/ens/ens.ts index 0b25d516..2d71a6dc 100644 --- a/common/sagas/ens/ens.ts +++ b/common/sagas/ens/ens.ts @@ -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) }); diff --git a/common/sagas/ens/helpers.ts b/common/sagas/ens/helpers.ts index 8024ee89..a799076d 100644 --- a/common/sagas/ens/helpers.ts +++ b/common/sagas/ens/helpers.ts @@ -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); diff --git a/common/sagas/transaction/current/currentValue.ts b/common/sagas/transaction/current/currentValue.ts index bb20403a..e8ed6696 100644 --- a/common/sagas/transaction/current/currentValue.ts +++ b/common/sagas/transaction/current/currentValue.ts @@ -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); diff --git a/common/sagas/wallet/helpers.ts b/common/sagas/wallet/helpers.ts index 6c2041c6..e463e28d 100644 --- a/common/sagas/wallet/helpers.ts +++ b/common/sagas/wallet/helpers.ts @@ -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; }, {}); diff --git a/common/sagas/wallet/wallet.ts b/common/sagas/wallet/wallet.ts index 02b94d58..c1ed437a 100644 --- a/common/sagas/wallet/wallet.ts +++ b/common/sagas/wallet/wallet.ts @@ -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' ); diff --git a/common/selectors/config/nodes.ts b/common/selectors/config/nodes.ts index 2b196c6c..bba5b5d8 100644 --- a/common/selectors/config/nodes.ts +++ b/common/selectors/config/nodes.ts @@ -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; } diff --git a/common/selectors/config/wallet.ts b/common/selectors/config/wallet.ts index 2afc86bd..766e1bb5 100644 --- a/common/selectors/config/wallet.ts +++ b/common/selectors/config/wallet.ts @@ -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); diff --git a/common/selectors/transaction/helpers.ts b/common/selectors/transaction/helpers.ts index b87dd866..b8e1bf48 100644 --- a/common/selectors/transaction/helpers.ts +++ b/common/selectors/transaction/helpers.ts @@ -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( + (obj, currFieldName: keyof TransactionFields) => { const currField = transactionFields[currFieldName]; return { ...obj, [currFieldName]: currField.value }; }, - {} as any //TODO: Fix types + {} as TransactionFieldValues ); export const isFullTx = ( diff --git a/common/selectors/transaction/transaction.ts b/common/selectors/transaction/transaction.ts index 400665a8..f09d5e0e 100644 --- a/common/selectors/transaction/transaction.ts +++ b/common/selectors/transaction/transaction.ts @@ -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 diff --git a/common/store/store.ts b/common/store/store.ts index 30661a76..a985d40b 100644 --- a/common/store/store.ts +++ b/common/store/store.ts @@ -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; if (process.env.NODE_ENV !== 'production') { middleware = composeWithDevTools( @@ -45,7 +45,7 @@ const configureStore = () => { const savedTransactionState = loadStatePropertyOrEmptyObject('transaction'); - const persistedInitialState = { + const persistedInitialState: Partial = { transaction: { ...transactionInitialState, fields: { @@ -65,10 +65,10 @@ const configureStore = () => { ...rehydrateConfigAndCustomTokenState() }; - store = createStore(RootReducer, persistedInitialState, middleware); + store = createStore(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]); }); diff --git a/common/translations/index.tsx b/common/translations/index.tsx index d108961c..1b39e9db 100644 --- a/common/translations/index.tsx +++ b/common/translations/index.tsx @@ -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'), diff --git a/common/typescript/ethereum-blockies.d.ts b/common/typescript/ethereum-blockies.d.ts new file mode 100644 index 00000000..81eaf813 --- /dev/null +++ b/common/typescript/ethereum-blockies.d.ts @@ -0,0 +1,3 @@ +declare module 'ethereum-blockies' { + export function toDataUrl(address: string): string; +} diff --git a/common/typescript/ethereumjs-abi.d.ts b/common/typescript/ethereumjs-abi.d.ts new file mode 100644 index 00000000..d396c198 --- /dev/null +++ b/common/typescript/ethereumjs-abi.d.ts @@ -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; +} diff --git a/common/typescript/ethereumjs-tx.d.ts b/common/typescript/ethereumjs-tx.d.ts index 185ea1ee..afeb862f 100644 --- a/common/typescript/ethereumjs-tx.d.ts +++ b/common/typescript/ethereumjs-tx.d.ts @@ -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 diff --git a/common/typescript/ethereumjs-wallet.d.ts b/common/typescript/ethereumjs-wallet.d.ts index f3ab8433..86c22380 100644 --- a/common/typescript/ethereumjs-wallet.d.ts +++ b/common/typescript/ethereumjs-wallet.d.ts @@ -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 diff --git a/common/typescript/ethjs-util.d.ts b/common/typescript/ethjs-util.d.ts new file mode 100644 index 00000000..d3cf3039 --- /dev/null +++ b/common/typescript/ethjs-util.d.ts @@ -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; +} diff --git a/common/typescript/hdkey.d.ts b/common/typescript/hdkey.d.ts new file mode 100644 index 00000000..839a5188 --- /dev/null +++ b/common/typescript/hdkey.d.ts @@ -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; + } +} diff --git a/common/typescript/idna-uts46.d.ts b/common/typescript/idna-uts46.d.ts new file mode 100644 index 00000000..9b52c0a6 --- /dev/null +++ b/common/typescript/idna-uts46.d.ts @@ -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; +} diff --git a/common/typescript/ledgerco.d.ts b/common/typescript/ledgerco.d.ts new file mode 100644 index 00000000..41d026ea --- /dev/null +++ b/common/typescript/ledgerco.d.ts @@ -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; + } +} diff --git a/common/typescript/react-copy-to-clipboard.d.ts b/common/typescript/react-copy-to-clipboard.d.ts new file mode 100644 index 00000000..08c2a167 --- /dev/null +++ b/common/typescript/react-copy-to-clipboard.d.ts @@ -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 {} +} diff --git a/common/typescript/react-stepper-horizontal.d.ts b/common/typescript/react-stepper-horizontal.d.ts new file mode 100644 index 00000000..1207f4f4 --- /dev/null +++ b/common/typescript/react-stepper-horizontal.d.ts @@ -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 { + constructor(); + } + export = Stepper; +} diff --git a/common/typescript/redux-test-utils.d.ts b/common/typescript/redux-test-utils.d.ts new file mode 100644 index 00000000..2c898236 --- /dev/null +++ b/common/typescript/redux-test-utils.d.ts @@ -0,0 +1,6 @@ +declare module 'redux-test-utils' { + import { Store } from 'react-redux'; + + export function createMockStore(testState: any): Store; + export function createMockDispatch(testAction: any): any; +} diff --git a/common/typescript/wallet-address-validator.d.ts b/common/typescript/wallet-address-validator.d.ts new file mode 100644 index 00000000..4ce2cbd4 --- /dev/null +++ b/common/typescript/wallet-address-validator.d.ts @@ -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'; diff --git a/common/utils/helpers.ts b/common/utils/helpers.ts index b6d1fe2c..52ca8456 100644 --- a/common/utils/helpers.ts +++ b/common/utils/helpers.ts @@ -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)], []); diff --git a/common/utils/localStorage.ts b/common/utils/localStorage.ts index a252dc02..05e3d613 100644 --- a/common/utils/localStorage.ts +++ b/common/utils/localStorage.ts @@ -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 | undefined { try { @@ -26,8 +27,8 @@ export const saveState = (state: any) => { export type SwapLocalStorage = SwapState; -export function loadStatePropertyOrEmptyObject(key: string): T | undefined { - const localStorageState = loadState(); +export function loadStatePropertyOrEmptyObject(key: keyof AppState): T | undefined { + const localStorageState: Partial | undefined = loadState(); if (localStorageState) { if (localStorageState.hasOwnProperty(key)) { return localStorageState[key] as T; diff --git a/common/utils/printElement.ts b/common/utils/printElement.ts index e4e0b593..bf3db1ab 100644 --- a/common/utils/printElement.ts +++ b/common/utils/printElement.ts @@ -18,8 +18,8 @@ export default function(element: React.ReactElement, 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); diff --git a/common/utils/tokens.ts b/common/utils/tokens.ts index f092624f..09ddf845 100644 --- a/common/utils/tokens.ts +++ b/common/utils/tokens.ts @@ -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; diff --git a/electron-app/main/window.ts b/electron-app/main/window.ts index f1a9003d..3cc48efd 100644 --- a/electron-app/main/window.ts +++ b/electron-app/main/window.ts @@ -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(); }); }); diff --git a/package.json b/package.json index e95bda21..4d725a31 100644 --- a/package.json +++ b/package.json @@ -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": { diff --git a/spec/config/contracts.spec.ts b/spec/config/contracts.spec.ts index 5be61684..f007dc8f 100644 --- a/spec/config/contracts.spec.ts +++ b/spec/config/contracts.spec.ts @@ -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}'`); } diff --git a/spec/config/tokens.spec.ts b/spec/config/tokens.spec.ts index 9ffa36cf..0858f6b9 100644 --- a/spec/config/tokens.spec.ts +++ b/spec/config/tokens.spec.ts @@ -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}'`); } diff --git a/spec/integration/data.int.ts b/spec/integration/data.int.ts index 3a7db3f6..fbfdc457 100644 --- a/spec/integration/data.int.ts +++ b/spec/integration/data.int.ts @@ -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); +} + 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 diff --git a/spec/integration/derivationChecker.int.ts b/spec/integration/derivationChecker.int.ts index 487ffe78..b09890e5 100644 --- a/spec/integration/derivationChecker.int.ts +++ b/spec/integration/derivationChecker.int.ts @@ -9,7 +9,7 @@ const dockerTag = 'latest'; function promiseFromChildProcess(command: string): Promise { return new Promise((resolve, reject) => { - return exec(command, (err, stdout) => { + return exec(command, (err: string, stdout: string) => { err ? reject(err) : resolve(stdout); }); }); diff --git a/spec/reducers/config/config.spec.ts b/spec/reducers/config/config.spec.ts index 1c95dd55..5bef5b56 100644 --- a/spec/reducers/config/config.spec.ts +++ b/spec/reducers/config/config.spec.ts @@ -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); diff --git a/spec/reducers/swap.spec.ts b/spec/reducers/swap.spec.ts index caf4fc57..1e40650f 100644 --- a/spec/reducers/swap.spec.ts +++ b/spec/reducers/swap.spec.ts @@ -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, diff --git a/spec/sagas/swap/orders.spec.ts b/spec/sagas/swap/orders.spec.ts index 0b1bd8c3..34856166 100644 --- a/spec/sagas/swap/orders.spec.ts +++ b/spec/sagas/swap/orders.spec.ts @@ -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)(); diff --git a/spec/sagas/swap/rates.spec.ts b/spec/sagas/swap/rates.spec.ts index 7a29d696..cb65b098 100644 --- a/spec/sagas/swap/rates.spec.ts +++ b/spec/sagas/swap/rates.spec.ts @@ -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)) ); }); diff --git a/spec/sagas/transaction/broadcast/helpers.spec.tsx b/spec/sagas/transaction/broadcast/helpers.spec.tsx index 0a8845f5..5dc1044f 100644 --- a/spec/sagas/transaction/broadcast/helpers.spec.tsx +++ b/spec/sagas/transaction/broadcast/helpers.spec.tsx @@ -36,7 +36,7 @@ describe('broadcastTransactionWrapper*', () => { blockExplorer: 'blockExplorer' }; - let random; + let random: () => number; const func: any = () => undefined; const action: any = {}; const gens: any = {}; diff --git a/spec/sagas/transaction/current/currentValue.spec.ts b/spec/sagas/transaction/current/currentValue.spec.ts index b5591386..11878b37 100644 --- a/spec/sagas/transaction/current/currentValue.spec.ts +++ b/spec/sagas/transaction/current/currentValue.spec.ts @@ -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)); }); diff --git a/spec/sagas/transaction/fields/fields.spec.ts b/spec/sagas/transaction/fields/fields.spec.ts index 9884eeeb..561a85d3 100644 --- a/spec/sagas/transaction/fields/fields.spec.ts +++ b/spec/sagas/transaction/fields/fields.spec.ts @@ -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); }); diff --git a/spec/sagas/transaction/meta/token.spec.ts b/spec/sagas/transaction/meta/token.spec.ts index 9d76a947..191cb54b 100644 --- a/spec/sagas/transaction/meta/token.spec.ts +++ b/spec/sagas/transaction/meta/token.spec.ts @@ -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); }); diff --git a/spec/sagas/transaction/meta/unitSwap.spec.ts b/spec/sagas/transaction/meta/unitSwap.spec.ts index 70b3d625..6e9920bd 100644 --- a/spec/sagas/transaction/meta/unitSwap.spec.ts +++ b/spec/sagas/transaction/meta/unitSwap.spec.ts @@ -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) }, diff --git a/spec/sagas/transaction/network/from.spec.ts b/spec/sagas/transaction/network/from.spec.ts index d5679d65..750d1528 100644 --- a/spec/sagas/transaction/network/from.spec.ts +++ b/spec/sagas/transaction/network/from.spec.ts @@ -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; diff --git a/spec/sagas/transaction/network/gas.spec.ts b/spec/sagas/transaction/network/gas.spec.ts index df4e0a85..2505d68a 100644 --- a/spec/sagas/transaction/network/gas.spec.ts +++ b/spec/sagas/transaction/network/gas.spec.ts @@ -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' diff --git a/spec/sagas/transaction/network/nonce.spec.ts b/spec/sagas/transaction/network/nonce.spec.ts index caad6a5d..52b6cdb2 100644 --- a/spec/sagas/transaction/network/nonce.spec.ts +++ b/spec/sagas/transaction/network/nonce.spec.ts @@ -21,7 +21,7 @@ describe('handleNonceRequest*', () => { const gens: any = {}; gens.gen = cloneableGenerator(handleNonceRequest)(); - let random; + let random: () => number; beforeAll(() => { random = Math.random; diff --git a/spec/sagas/transaction/sendEverything.spec.ts b/spec/sagas/transaction/sendEverything.spec.ts index 4319a57d..6593ca8c 100644 --- a/spec/sagas/transaction/sendEverything.spec.ts +++ b/spec/sagas/transaction/sendEverything.spec.ts @@ -11,9 +11,11 @@ import { getEtherBalance, getCurrentBalance } from 'selectors/wallet'; import { fromTokenBase, fromWei, Wei } from 'libs/units'; import { handleSendEverything } from 'sagas/transaction/sendEverything'; import { cloneableGenerator } from 'redux-saga/utils'; +import { SagaIterator } from 'redux-saga'; +import BN from 'bn.js'; describe('handleSendEverything*', () => { - let random; + let random: () => number; beforeAll(() => { random = Math.random; Math.random = () => 0.001; @@ -23,7 +25,7 @@ describe('handleSendEverything*', () => { Math.random = random; }); - const sharedStart = (gen, transactionObj, currentBalance) => { + const sharedStart = (gen: SagaIterator, transactionObj: any, currentBalance: BN | null) => { it('should select getTransaction', () => { expect(gen.next().value).toEqual(select(getTransaction)); }); diff --git a/spec/sagas/transaction/signing/helpers.spec.ts b/spec/sagas/transaction/signing/helpers.spec.ts index c800ddf9..68a10cd1 100644 --- a/spec/sagas/transaction/signing/helpers.spec.ts +++ b/spec/sagas/transaction/signing/helpers.spec.ts @@ -97,7 +97,7 @@ describe('getWalletAndTransaction*', () => { describe('handleFailedTransaction*', () => { const err = new Error('Message'); const gen = handleFailedTransaction(err); - let random; + let random: () => number; beforeAll(() => { random = Math.random; diff --git a/spec/sagas/transaction/validationHelpers.spec.ts b/spec/sagas/transaction/validationHelpers.spec.ts index dd3548c2..a990fbc4 100644 --- a/spec/sagas/transaction/validationHelpers.spec.ts +++ b/spec/sagas/transaction/validationHelpers.spec.ts @@ -10,8 +10,9 @@ import { } from 'sagas/transaction/validationHelpers'; import { cloneableGenerator } from 'redux-saga/utils'; import { getOffline, isNetworkUnit } from 'selectors/config'; +import { SagaIterator } from 'redux-saga'; -const itShouldBeDone = gen => { +const itShouldBeDone = (gen: SagaIterator) => { it('should be done', () => { expect(gen.next().done).toEqual(true); }); diff --git a/spec/sagas/wallet.spec.tsx b/spec/sagas/wallet.spec.tsx index db8ecd44..1244dc38 100644 --- a/spec/sagas/wallet.spec.tsx +++ b/spec/sagas/wallet.spec.tsx @@ -292,9 +292,9 @@ describe('unlockWeb3*', () => { data.gen = cloneableGenerator(unlockWeb3)(); const accounts = [address]; const { random } = Math; - let nodeLib; + let nodeLib: Web3Node; - function sendAsync(options, cb) { + function sendAsync(options: any, cb: any) { const resp = { id: 'id' }; @@ -333,7 +333,7 @@ describe('unlockWeb3*', () => { it('should yield take on node change', () => { const expected = take( - action => + (action: any) => action.type === ConfigTypeKeys.CONFIG_NODE_CHANGE && action.payload.nodeSelection === 'web3' ); const result = data.gen.next().value; diff --git a/spec/utils/localStorage.spec.ts b/spec/utils/localStorage.spec.ts index 947f2db1..0afb0ddc 100644 --- a/spec/utils/localStorage.spec.ts +++ b/spec/utils/localStorage.spec.ts @@ -11,9 +11,7 @@ describe('saveState', () => { foo: 'bar' }; saveState(persistMe); - expect(JSON.parse(localStorage.getItem(REDUX_STATE) as string)).toEqual( - persistMe - ); + expect(JSON.parse(localStorage.getItem(REDUX_STATE) as string)).toEqual(persistMe); }); }); @@ -32,6 +30,6 @@ describe('loadStatePropertyOrEmptyObject', () => { two: 'bar' }; saveState(serializeThis); - expect(loadStatePropertyOrEmptyObject('one')).toEqual(serializeThis.one); + expect(loadStatePropertyOrEmptyObject('one' as any)).toEqual(serializeThis.one); }); }); diff --git a/spec/utils/shallowWithStore.ts b/spec/utils/shallowWithStore.ts index b0a07f74..232cb394 100644 --- a/spec/utils/shallowWithStore.ts +++ b/spec/utils/shallowWithStore.ts @@ -1,6 +1,6 @@ import { shallow } from 'enzyme'; -const shallowWithStore = (component, store) => { +const shallowWithStore = (component: any, store: any) => { const context = { store }; diff --git a/tsconfig.json b/tsconfig.json index 1af567ef..8e31a85f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,8 @@ "moduleResolution": "node", "noEmitOnError": false, "noUnusedLocals": true, - "noUnusedParameters": true + "noUnusedParameters": true, + "noImplicitAny": true }, "include": [ "./common/",