Enable no-implicit-any (#1263)
* Progress commit * Update more types * Fix more types * Fix abi function types * Fix lib types * Fix rest of types * Address wbobeirne changes * Change origin and destination check
This commit is contained in:
parent
0e26f7af4c
commit
c340246ca0
|
@ -29,7 +29,7 @@ export function loadBityRatesSucceededSwap(
|
|||
|
||||
export type TLoadShapeshiftRatesSucceededSwap = typeof loadShapeshiftRatesSucceededSwap;
|
||||
export function loadShapeshiftRatesSucceededSwap(
|
||||
payload
|
||||
payload: interfaces.LoadShapeshiftRatesSucceededSwapAction['payload']
|
||||
): interfaces.LoadShapeshiftRatesSucceededSwapAction {
|
||||
return {
|
||||
type: TypeKeys.SWAP_LOAD_SHAPESHIFT_RATES_SUCCEEDED,
|
||||
|
|
|
@ -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) };
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { checkHttpStatus, parseJSON } from './utils';
|
||||
import { Omit } from 'react-redux';
|
||||
|
||||
const MAX_GAS_FAST = 250;
|
||||
|
||||
|
@ -21,15 +22,29 @@ export interface GasEstimates {
|
|||
isDefault: boolean;
|
||||
}
|
||||
|
||||
interface GasExpressResponse {
|
||||
block_time: number;
|
||||
blockNum: number;
|
||||
fast: number;
|
||||
fastest: number;
|
||||
safeLow: number;
|
||||
standard: number;
|
||||
}
|
||||
|
||||
export function fetchGasEstimates(): Promise<GasEstimates> {
|
||||
return fetch('https://dev.blockscale.net/api/gasexpress.json', {
|
||||
mode: 'cors'
|
||||
})
|
||||
.then(checkHttpStatus)
|
||||
.then(parseJSON)
|
||||
.then((res: object) => {
|
||||
.then((res: GasExpressResponse) => {
|
||||
// Make sure it looks like a raw gas estimate, and it has valid values
|
||||
const keys = ['safeLow', 'standard', 'fast', 'fastest'];
|
||||
const keys: (keyof Omit<GasExpressResponse, 'block_time' | 'blockNum'>)[] = [
|
||||
'safeLow',
|
||||
'standard',
|
||||
'fast',
|
||||
'fastest'
|
||||
];
|
||||
keys.forEach(key => {
|
||||
if (typeof res[key] !== 'number') {
|
||||
throw new Error(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -37,5 +37,8 @@ export const AmountField: React.SFC<Props> = ({
|
|||
/>
|
||||
);
|
||||
|
||||
const isAmountValid = (raw, customValidator, isValid) =>
|
||||
customValidator ? customValidator(raw) : isValid;
|
||||
const isAmountValid = (
|
||||
raw: string,
|
||||
customValidator: ((rawAmount: string) => boolean) | undefined,
|
||||
isValid: boolean
|
||||
) => (customValidator ? customValidator(raw) : isValid);
|
||||
|
|
|
@ -8,7 +8,6 @@ import { chain, flatMap } from 'lodash';
|
|||
import { TokenBalance, getShownTokenBalances } from 'selectors/wallet';
|
||||
import { Balance } from 'libs/wallet';
|
||||
import './EquivalentValues.scss';
|
||||
import { Wei } from 'libs/units';
|
||||
import { AppState } from 'reducers';
|
||||
import { getNetworkConfig, getOffline } from 'selectors/config';
|
||||
import { connect } from 'react-redux';
|
||||
|
@ -16,6 +15,7 @@ import btcIco from 'assets/images/bitcoin.png';
|
|||
import ethIco from 'assets/images/ether.png';
|
||||
import repIco from 'assets/images/augur.png';
|
||||
import { NetworkConfig } from 'types/network';
|
||||
import BN from 'bn.js';
|
||||
|
||||
interface AllValue {
|
||||
symbol: string;
|
||||
|
@ -51,6 +51,14 @@ interface DispatchProps {
|
|||
fetchCCRates: TFetchCCRatesRequested;
|
||||
}
|
||||
|
||||
interface FiatSymbols {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
interface Rates {
|
||||
[rate: string]: number;
|
||||
}
|
||||
|
||||
type Props = StateProps & DispatchProps;
|
||||
|
||||
class EquivalentValues extends React.Component<Props, State> {
|
||||
|
@ -110,7 +118,7 @@ class EquivalentValues extends React.Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
public selectOption = equivalentValues => {
|
||||
public selectOption = (equivalentValues: Option) => {
|
||||
this.setState({ equivalentValues });
|
||||
};
|
||||
|
||||
|
@ -120,28 +128,38 @@ class EquivalentValues extends React.Component<Props, State> {
|
|||
const isFetching =
|
||||
!balance || balance.isPending || !tokenBalances || Object.keys(rates).length === 0;
|
||||
const pairRates = this.generateValues(equivalentValues.label, equivalentValues.value);
|
||||
const fiatSymbols = {
|
||||
const fiatSymbols: FiatSymbols = {
|
||||
USD: '$',
|
||||
EUR: '€',
|
||||
GBP: '£',
|
||||
CHF: ' '
|
||||
};
|
||||
const coinAndTokenSymbols = {
|
||||
const coinAndTokenSymbols: any = {
|
||||
BTC: btcIco,
|
||||
ETH: ethIco,
|
||||
REP: repIco
|
||||
};
|
||||
interface ValueProps {
|
||||
className: string;
|
||||
rate: string;
|
||||
value: BN | null;
|
||||
symbol?: string;
|
||||
icon?: string;
|
||||
key?: number | string;
|
||||
}
|
||||
|
||||
const Value = ({ className = '', rate, value, symbol = '', icon = '' }) => (
|
||||
<div className={`EquivalentValues-values-currency ${className}`}>
|
||||
<img src={icon} />
|
||||
{!!symbol && <span className="EquivalentValues-values-currency-fiat-symbol">{symbol}</span>}
|
||||
<span className="EquivalentValues-values-currency-label">{rate}</span>{' '}
|
||||
const Value = (props: ValueProps) => (
|
||||
<div className={`EquivalentValues-values-currency ${props.className}`}>
|
||||
<img src={props.icon} />
|
||||
{!!props.symbol && (
|
||||
<span className="EquivalentValues-values-currency-fiat-symbol">{props.symbol}</span>
|
||||
)}
|
||||
<span className="EquivalentValues-values-currency-label">{props.rate}</span>{' '}
|
||||
<span className="EquivalentValues-values-currency-value">
|
||||
<UnitDisplay
|
||||
unit={'ether'}
|
||||
value={value}
|
||||
displayShortBalance={rateSymbols.isFiat(rate) ? 2 : 3}
|
||||
value={props.value}
|
||||
displayShortBalance={rateSymbols.isFiat(props.rate) ? 2 : 3}
|
||||
checkOffline={true}
|
||||
/>
|
||||
</span>
|
||||
|
@ -157,7 +175,7 @@ class EquivalentValues extends React.Component<Props, State> {
|
|||
// TODO: Update type
|
||||
value={equivalentValues as any}
|
||||
options={options as any}
|
||||
onChange={this.selectOption}
|
||||
onChange={this.selectOption as any}
|
||||
clearable={false}
|
||||
searchable={false}
|
||||
/>
|
||||
|
@ -224,7 +242,7 @@ class EquivalentValues extends React.Component<Props, State> {
|
|||
const allRates = Object.values(balance).map(
|
||||
value => !!rates[value.symbol] && rates[value.symbol]
|
||||
);
|
||||
const allEquivalentValues = allRates.map((rateType, i) => {
|
||||
const allEquivalentValues = allRates.map((rateType: any, i) => {
|
||||
return {
|
||||
symbol: Object.keys(rates)[i],
|
||||
equivalentValues: [
|
||||
|
@ -260,9 +278,9 @@ class EquivalentValues extends React.Component<Props, State> {
|
|||
// return equivalent value (unit * rate * balance)
|
||||
private handleValues(unit: string, balance: Balance['wei']) {
|
||||
const { rates } = this.props;
|
||||
const ratesObj = { ...rates[unit] };
|
||||
const ratesObj: Rates = { ...rates[unit] };
|
||||
return Object.keys(ratesObj).map(key => {
|
||||
const value = (balance as Wei).muln(ratesObj[key]);
|
||||
const value = balance!.muln(ratesObj[key]);
|
||||
return { rate: key, value };
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import './Promos.scss';
|
|||
import { connect } from 'react-redux';
|
||||
import { AppState } from '../../reducers';
|
||||
|
||||
const CarouselAnimation = ({ children, ...props }) => (
|
||||
const CarouselAnimation = ({ children, ...props }: any) => (
|
||||
<CSSTransition {...props} timeout={300} classNames="carousel">
|
||||
{children}
|
||||
</CSSTransition>
|
||||
|
|
|
@ -15,19 +15,23 @@ interface Props {
|
|||
onRemoveCustomToken(symbol: string): any;
|
||||
}
|
||||
|
||||
interface TrackedTokens {
|
||||
[symbol: string]: boolean;
|
||||
}
|
||||
|
||||
interface State {
|
||||
trackedTokens: { [symbol: string]: boolean };
|
||||
showCustomTokenForm: boolean;
|
||||
}
|
||||
export default class TokenBalances extends React.PureComponent<Props, State> {
|
||||
public state = {
|
||||
public state: State = {
|
||||
trackedTokens: {},
|
||||
showCustomTokenForm: false
|
||||
};
|
||||
|
||||
public componentWillReceiveProps(nextProps: Props) {
|
||||
if (nextProps.tokenBalances !== this.props.tokenBalances) {
|
||||
const trackedTokens = nextProps.tokenBalances.reduce((prev, t) => {
|
||||
const trackedTokens = nextProps.tokenBalances.reduce<TrackedTokens>((prev, t) => {
|
||||
prev[t.symbol] = !t.balance.isZero();
|
||||
return prev;
|
||||
}, {});
|
||||
|
|
|
@ -13,7 +13,7 @@ interface StateProps {
|
|||
}
|
||||
|
||||
interface OwnProps {
|
||||
withProps(props: CallBackProps);
|
||||
withProps(props: CallBackProps): null | React.ReactElement<any>;
|
||||
onChange(value: React.FormEvent<HTMLInputElement>): void;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,9 +41,9 @@ export default class GenerateKeystoreModal extends React.Component<Props, State>
|
|||
}
|
||||
}
|
||||
|
||||
public componentWillReceiveProps(nextProps) {
|
||||
public componentWillReceiveProps(nextProps: Props) {
|
||||
if (nextProps.privateKey !== this.props.privateKey) {
|
||||
this.setState({ privateKey: nextProps.privateKey });
|
||||
this.setState({ privateKey: nextProps.privateKey || '' });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import { Input } from 'components/ui';
|
|||
const CUSTOM = 'custom';
|
||||
|
||||
interface InputProps {
|
||||
name: string;
|
||||
name: keyof Omit<State, 'hasAuth'>;
|
||||
placeholder?: string;
|
||||
type?: string;
|
||||
autoComplete?: 'off';
|
||||
|
|
|
@ -18,7 +18,7 @@ interface State {
|
|||
}
|
||||
|
||||
class LogOutPromptClass extends React.Component<Props, State> {
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
nextLocation: null,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -7,6 +7,7 @@ import { connect } from 'react-redux';
|
|||
import { AppState } from 'reducers';
|
||||
import { getUnit } from 'selectors/transaction';
|
||||
import { getNetworkUnit } from 'selectors/config';
|
||||
import { Option } from 'react-select';
|
||||
|
||||
interface DispatchProps {
|
||||
setUnitMeta: TSetUnitMeta;
|
||||
|
@ -41,7 +42,10 @@ class UnitDropdownClass extends Component<DispatchProps & StateProps> {
|
|||
/>
|
||||
);
|
||||
}
|
||||
private handleOnChange = unit => {
|
||||
private handleOnChange = (unit: Option<string>) => {
|
||||
if (!unit.value) {
|
||||
throw Error('No unit value found');
|
||||
}
|
||||
this.props.setUnitMeta(unit.value);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -73,7 +73,7 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
|
|||
this.getAddresses();
|
||||
}
|
||||
|
||||
public componentWillReceiveProps(nextProps) {
|
||||
public componentWillReceiveProps(nextProps: Props) {
|
||||
const { publicKey, chainCode, seed, dPath } = this.props;
|
||||
if (
|
||||
nextProps.publicKey !== publicKey ||
|
||||
|
@ -245,7 +245,7 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
|
|||
}
|
||||
};
|
||||
|
||||
private selectAddress(selectedAddress, selectedAddrIndex) {
|
||||
private selectAddress(selectedAddress: string, selectedAddrIndex: number) {
|
||||
this.setState({ selectedAddress, selectedAddrIndex });
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
|
|||
showTip: false
|
||||
});
|
||||
|
||||
ledger.comm_u2f.create_async().then(comm => {
|
||||
ledger.comm_u2f.create_async().then((comm: any) => {
|
||||
new ledger.eth(comm)
|
||||
.getAddress_async(dPath, false, true)
|
||||
.then(res => {
|
||||
|
@ -139,7 +139,7 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
|
|||
isLoading: false
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err: any) => {
|
||||
if (err && err.metaData && err.metaData.code === 5) {
|
||||
this.showTip();
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ class MnemonicDecryptClass extends PureComponent<Props, State> {
|
|||
isValid={isValidMnemonic}
|
||||
isTextareaWhenVisible={true}
|
||||
onChange={this.onMnemonicChange}
|
||||
onEnter={isValidMnemonic && this.onDWModalOpen}
|
||||
onEnter={isValidMnemonic ? this.onDWModalOpen : undefined}
|
||||
/>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
|
@ -134,7 +134,7 @@ class MnemonicDecryptClass extends PureComponent<Props, State> {
|
|||
this.setState({ dPath });
|
||||
};
|
||||
|
||||
private handleUnlock = (address, index) => {
|
||||
private handleUnlock = (address: string, index: number) => {
|
||||
const { formattedPhrase, pass, dPath } = this.state;
|
||||
|
||||
this.props.onUnlock({
|
||||
|
|
|
@ -108,7 +108,7 @@ class TrezorDecryptClass extends PureComponent<Props, State> {
|
|||
|
||||
(TrezorConnect as any).getXPubKey(
|
||||
dPath,
|
||||
res => {
|
||||
(res: any) => {
|
||||
if (res.success) {
|
||||
this.setState({
|
||||
dPath,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import Select, { ReactSelectProps } from 'react-select';
|
||||
import Select, { ReactSelectProps, Option } from 'react-select';
|
||||
|
||||
interface Props extends ReactSelectProps {
|
||||
className?: string;
|
||||
|
@ -13,11 +13,11 @@ export default class Dropdown extends React.Component<Props> {
|
|||
hasBlurred: false
|
||||
};
|
||||
|
||||
public handleChange = selectedOption => {
|
||||
public handleChange = (selectedOption: Option) => {
|
||||
this.setState({ selectedOption });
|
||||
};
|
||||
|
||||
public formatOptions = options => {
|
||||
public formatOptions = (options: Option[]) => {
|
||||
if (typeof options[0] === 'object') {
|
||||
return options;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ export default class Dropdown extends React.Component<Props> {
|
|||
// use ref to prevent <label /> from stealing focus when used inline with an input
|
||||
ref={el => {
|
||||
if (!!el && !!(el as any).control) {
|
||||
(el as any).control.addEventListener('click', e => {
|
||||
(el as any).control.addEventListener('click', (e: React.FormEvent<any>) => {
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ export default class Dropdown extends React.Component<Props> {
|
|||
className={`${this.props.className} ${this.state.hasBlurred ? 'has-blurred' : ''}`}
|
||||
value={value}
|
||||
onChange={obj => {
|
||||
this.handleChange(obj);
|
||||
this.handleChange(obj as any);
|
||||
onChange();
|
||||
}}
|
||||
{...this.props}
|
||||
|
@ -56,7 +56,7 @@ export default class Dropdown extends React.Component<Props> {
|
|||
this.props.onBlur(e);
|
||||
}
|
||||
}}
|
||||
options={options}
|
||||
options={options as any}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ interface ModalStyle {
|
|||
maxWidth?: string;
|
||||
}
|
||||
|
||||
const Fade = ({ children, ...props }) => (
|
||||
const Fade = ({ children, ...props }: any) => (
|
||||
<CSSTransition {...props} timeout={300} classNames="animate-modal">
|
||||
{children}
|
||||
</CSSTransition>
|
||||
|
|
|
@ -64,8 +64,8 @@ export default class DropdownComponent<T> extends PureComponent<Props<T>, State>
|
|||
overflowY: 'auto'
|
||||
};
|
||||
const searchRegex = new RegExp(search, 'gi');
|
||||
const onSearchChange = e => {
|
||||
this.setState({ search: e.target.value });
|
||||
const onSearchChange = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
this.setState({ search: e.currentTarget.value });
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -25,15 +25,15 @@ const ValueComp: React.SFC = (props: any) => {
|
|||
};
|
||||
|
||||
const OptionComp: React.SFC = (props: any) => {
|
||||
const handleMouseDown = event => {
|
||||
const handleMouseDown = (event: React.MouseEvent<any>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
props.onSelect(props.option, event);
|
||||
};
|
||||
const handleMouseEnter = event => {
|
||||
const handleMouseEnter = (event: React.MouseEvent<any>) => {
|
||||
props.onFocus(props.option, event);
|
||||
};
|
||||
const handleMouseMove = event => {
|
||||
const handleMouseMove = (event: React.MouseEvent<any>) => {
|
||||
if (props.isFocused) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,11 @@ import { HELP_ARTICLE } from 'config';
|
|||
import OnboardSlide from './OnboardSlide';
|
||||
import onboardIconTen from 'assets/images/onboarding/slide-10.svg';
|
||||
|
||||
const FinalSlide = ({ closeModal }) => {
|
||||
interface Props {
|
||||
closeModal(): void;
|
||||
}
|
||||
|
||||
const FinalSlide: React.SFC<Props> = ({ closeModal }) => {
|
||||
const header = translate('ONBOARD_final_title');
|
||||
const subheader = translate('ONBOARD_final_subtitle');
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ interface Props {
|
|||
class OnboardModal extends React.Component<Props, State> {
|
||||
private modal: Modal | null = null;
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isOpen: false
|
||||
|
|
|
@ -36,7 +36,7 @@ interface State {
|
|||
inputs: {
|
||||
[key: string]: { rawData: string; parsedData: string[] | string };
|
||||
};
|
||||
outputs;
|
||||
outputs: any;
|
||||
selectedFunction: null | ContractOption;
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ class InteractExplorerClass extends Component<Props, State> {
|
|||
</div>
|
||||
);
|
||||
})}
|
||||
{selectedFunction.contract.outputs.map((output, index) => {
|
||||
{selectedFunction.contract.outputs.map((output: any, index: number) => {
|
||||
const { type, name } = output;
|
||||
const parsedName = name === '' ? index : name;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ interface StateProps {
|
|||
}
|
||||
|
||||
interface OwnProps {
|
||||
accessContract(contractAbi: string, address: string): (ev) => void;
|
||||
accessContract(contractAbi: string, address: string): (ev: any) => void;
|
||||
resetState(): void;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ const abiJsonPlaceholder = [
|
|||
class InteractForm extends Component<Props, State> {
|
||||
private abiJsonPlaceholder = JSON.stringify(abiJsonPlaceholder, null, 0);
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
address: '',
|
||||
|
@ -140,7 +140,9 @@ class InteractForm extends Component<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
private handleInput = name => (ev: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
private handleInput = (name: any) => (
|
||||
ev: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>
|
||||
) => {
|
||||
this.props.resetState();
|
||||
this.setState({ [name]: ev.currentTarget.value });
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class CountDown extends Component<Props, State> {
|
|||
|
||||
private startCountDown = () => {
|
||||
const time = moment(this.props.initialTime);
|
||||
let intervalId;
|
||||
let intervalId: number;
|
||||
|
||||
const setTimeDisplay = () => {
|
||||
const diff = moment.duration(time.diff(moment()));
|
||||
|
@ -44,7 +44,7 @@ class CountDown extends Component<Props, State> {
|
|||
this.setState({ timeDisplay });
|
||||
};
|
||||
|
||||
intervalId = setInterval(setTimeDisplay, 1000);
|
||||
intervalId = window.setInterval(setTimeDisplay, 1000);
|
||||
setTimeDisplay();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ const WalletTypes: React.SFC<{}> = () => {
|
|||
|
||||
<div className="WalletTypes-types row">
|
||||
<div className="col-md-1" />
|
||||
{Object.keys(typeInfo).map(type => (
|
||||
{Object.keys(typeInfo).map((type: keyof typeof typeInfo) => (
|
||||
<div key={type} className="WalletType col-md-5">
|
||||
<h2 className="WalletType-title">{translate(typeInfo[type].name)}</h2>
|
||||
<ul className="WalletType-features">
|
||||
|
|
|
@ -44,7 +44,8 @@ interface ActionProps {
|
|||
|
||||
type Props = OwnProps & StateProps & ActionProps;
|
||||
|
||||
const isValidAmount = decimal => amount => validNumber(+amount) && validDecimal(amount, decimal);
|
||||
const isValidAmount = (decimal: number) => (amount: string) =>
|
||||
validNumber(+amount) && validDecimal(amount, decimal);
|
||||
|
||||
class RequestPayment extends React.Component<Props, {}> {
|
||||
public state = {
|
||||
|
@ -145,7 +146,7 @@ class RequestPayment extends React.Component<Props, {}> {
|
|||
private generateEIP681String(
|
||||
currentTo: string,
|
||||
tokenContractAddress: string,
|
||||
currentValue,
|
||||
currentValue: { raw: string; value: BN | null },
|
||||
gasLimit: { raw: string; value: BN | null },
|
||||
unit: string,
|
||||
decimal: number,
|
||||
|
@ -162,7 +163,11 @@ class RequestPayment extends React.Component<Props, {}> {
|
|||
return '';
|
||||
}
|
||||
|
||||
if (this.props.isNetworkUnit) {
|
||||
const currentValueIsEther = (
|
||||
_: AppState['transaction']['fields']['value'] | AppState['transaction']['meta']['tokenTo']
|
||||
): _ is AppState['transaction']['fields']['value'] => this.props.isNetworkUnit;
|
||||
|
||||
if (currentValueIsEther(currentValue)) {
|
||||
return buildEIP681EtherRequest(currentTo, chainId, currentValue);
|
||||
} else {
|
||||
return buildEIP681TokenRequest(
|
||||
|
|
|
@ -30,8 +30,8 @@ export interface ActionProps {
|
|||
|
||||
interface State {
|
||||
disabled: boolean;
|
||||
origin: SwapInput;
|
||||
destination: SwapInput;
|
||||
origin: SwapOpt;
|
||||
destination: SwapOpt;
|
||||
originKindOptions: any[];
|
||||
destinationKindOptions: any[];
|
||||
originErr: string;
|
||||
|
@ -49,7 +49,7 @@ interface SwapOpt extends SwapInput {
|
|||
}
|
||||
|
||||
export default class CurrencySwap extends PureComponent<Props, State> {
|
||||
public state = {
|
||||
public state: State = {
|
||||
disabled: true,
|
||||
origin: {
|
||||
label: 'BTC',
|
||||
|
@ -57,14 +57,14 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
|||
status: 'available',
|
||||
image: 'https://shapeshift.io/images/coins/bitcoin.png',
|
||||
amount: NaN
|
||||
} as SwapOpt,
|
||||
},
|
||||
destination: {
|
||||
label: 'ETH',
|
||||
value: 'Ether',
|
||||
status: 'available',
|
||||
image: 'https://shapeshift.io/images/coins/ether.png',
|
||||
amount: NaN
|
||||
} as SwapOpt,
|
||||
},
|
||||
originKindOptions: [],
|
||||
destinationKindOptions: [],
|
||||
originErr: '',
|
||||
|
@ -151,7 +151,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
|||
return merge(shapeshiftRates, bityRates);
|
||||
};
|
||||
|
||||
public getMinMax = (originKind: WhitelistedCoins, destinationKind) => {
|
||||
public getMinMax = (originKind: WhitelistedCoins, destinationKind: string) => {
|
||||
let min;
|
||||
let max;
|
||||
|
||||
|
@ -176,7 +176,11 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
|||
return { min, max };
|
||||
};
|
||||
|
||||
public isMinMaxValid = (originAmount: number, originKind: WhitelistedCoins, destinationKind) => {
|
||||
public isMinMaxValid = (
|
||||
originAmount: number,
|
||||
originKind: WhitelistedCoins,
|
||||
destinationKind: string
|
||||
) => {
|
||||
const rate = this.getMinMax(originKind, destinationKind);
|
||||
const higherThanMin = originAmount >= rate.min;
|
||||
const lowerThanMax = originAmount <= rate.max;
|
||||
|
@ -201,7 +205,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
|||
this.debouncedCreateErrString(origin, destination, showError);
|
||||
}
|
||||
|
||||
public setErrorMessages = (originErr, destinationErr) => {
|
||||
public setErrorMessages = (originErr: string, destinationErr: string) => {
|
||||
this.setState({
|
||||
originErr,
|
||||
destinationErr
|
||||
|
@ -269,15 +273,17 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
|||
: this.updateDestinationAmount(origin, destination, amount);
|
||||
};
|
||||
|
||||
public onChangeOriginKind = newOption => {
|
||||
public onChangeOriginKind = (newOption: any) => {
|
||||
const { origin, destination, destinationKindOptions } = this.state;
|
||||
const { options, initSwap } = this.props;
|
||||
|
||||
const newOrigin = { ...origin, label: newOption.label, value: newOption.value, amount: '' };
|
||||
const newOrigin = { ...origin, label: newOption.label, value: newOption.value, amount: 0 };
|
||||
const newDest = {
|
||||
label: newOption.label === destination.label ? origin.label : destination.label,
|
||||
value: newOption.value === destination.value ? origin.value : destination.value,
|
||||
amount: ''
|
||||
amount: 0,
|
||||
status: '',
|
||||
image: ''
|
||||
};
|
||||
|
||||
this.setState({
|
||||
|
@ -292,16 +298,16 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
|||
initSwap({ origin: newOrigin, destination: newDest });
|
||||
};
|
||||
|
||||
public onChangeDestinationKind = newOption => {
|
||||
public onChangeDestinationKind = (newOption: any) => {
|
||||
const { initSwap } = this.props;
|
||||
const { origin, destination } = this.state;
|
||||
|
||||
const newOrigin = {
|
||||
...origin,
|
||||
amount: ''
|
||||
amount: 0
|
||||
};
|
||||
|
||||
const newDest = { ...destination, label: newOption.label, value: newOption.value, amount: '' };
|
||||
const newDest = { ...destination, label: newOption.label, value: newOption.value, amount: 0 };
|
||||
this.setState({
|
||||
origin: newOrigin,
|
||||
destination: newDest
|
||||
|
@ -339,7 +345,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
|||
<Input
|
||||
id="origin-swap-input"
|
||||
className={`input-group-input ${
|
||||
String(origin.amount) !== '' &&
|
||||
!origin.amount &&
|
||||
this.isMinMaxValid(origin.amount, origin.label, destination.label)
|
||||
? ''
|
||||
: 'invalid'
|
||||
|
@ -364,7 +370,7 @@ export default class CurrencySwap extends PureComponent<Props, State> {
|
|||
<Input
|
||||
id="destination-swap-input"
|
||||
className={`${
|
||||
String(destination.amount) !== '' &&
|
||||
!destination.amount &&
|
||||
this.isMinMaxValid(origin.amount, origin.label, destination.label)
|
||||
? ''
|
||||
: 'invalid'
|
||||
|
|
|
@ -24,6 +24,7 @@ import { getOffline } from 'selectors/config';
|
|||
import Rates from './Rates';
|
||||
import { AppState } from 'reducers';
|
||||
import './CurrentRates.scss';
|
||||
import { Optional } from 'utils/types';
|
||||
|
||||
interface StateProps {
|
||||
isOffline: boolean;
|
||||
|
@ -40,7 +41,7 @@ interface ActionProps {
|
|||
type Props = StateProps & ActionProps;
|
||||
|
||||
class CurrentRates extends PureComponent<Props> {
|
||||
private shapeShiftRateCache = null;
|
||||
private shapeShiftRateCache: any = null;
|
||||
|
||||
public componentDidMount() {
|
||||
if (!this.props.isOffline) {
|
||||
|
@ -79,7 +80,7 @@ class CurrentRates extends PureComponent<Props> {
|
|||
|
||||
public buildSSPairs = (shapeshiftRates: NormalizedShapeshiftRates, n: number = 4) => {
|
||||
const pairCollection = times(n, () => this.getRandomSSPairData(shapeshiftRates));
|
||||
const byId = pairCollection.reduce((acc, cur) => {
|
||||
const byId = pairCollection.reduce<{ [id: string]: NormalizedShapeshiftRate }>((acc, cur) => {
|
||||
acc[cur.id] = cur;
|
||||
return acc;
|
||||
}, {});
|
||||
|
@ -90,7 +91,7 @@ class CurrentRates extends PureComponent<Props> {
|
|||
};
|
||||
};
|
||||
|
||||
public isValidRates = rates => {
|
||||
public isValidRates = (rates: Optional<NormalizedShapeshiftRates>) => {
|
||||
return rates && rates.allIds && rates.allIds.length > 0;
|
||||
};
|
||||
|
||||
|
@ -118,7 +119,7 @@ class CurrentRates extends PureComponent<Props> {
|
|||
return fixedRates;
|
||||
};
|
||||
|
||||
public swapEl = (providerURL, providerLogo, children) => {
|
||||
public swapEl = (providerURL: string, providerLogo: string, children: any) => {
|
||||
return (
|
||||
<article className="SwapRates">
|
||||
<h3 className="SwapRates-title">{translate('SWAP_rates')}</h3>
|
||||
|
|
|
@ -47,7 +47,7 @@ interface State {
|
|||
}
|
||||
|
||||
export default class Rates extends Component<Props, State> {
|
||||
public state = {
|
||||
public state: State = {
|
||||
pairs: {}
|
||||
};
|
||||
|
||||
|
@ -72,7 +72,7 @@ export default class Rates extends Component<Props, State> {
|
|||
public getPairs = () => {
|
||||
const { rates } = this.props;
|
||||
const { allIds } = rates;
|
||||
return allIds.reduce((acc, cur) => {
|
||||
return allIds.reduce<{ [id: string]: 1 }>((acc, cur) => {
|
||||
acc[cur] = 1;
|
||||
return acc;
|
||||
}, {});
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
|
||||
|
|
|
@ -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`,
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
GetCurrentBlockRequest
|
||||
} from './types';
|
||||
import { Token } from 'types/network';
|
||||
import { IHexStrWeb3Transaction, IHexStrTransaction } from 'libs/transaction';
|
||||
|
||||
export default class EtherscanRequests extends RPCRequests {
|
||||
public sendRawTx(signedTx: string): SendRawTxRequest {
|
||||
|
@ -21,7 +22,7 @@ export default class EtherscanRequests extends RPCRequests {
|
|||
};
|
||||
}
|
||||
|
||||
public estimateGas(transaction): EstimateGasRequest {
|
||||
public estimateGas(transaction: IHexStrWeb3Transaction): EstimateGasRequest {
|
||||
return {
|
||||
module: 'proxy',
|
||||
action: 'eth_estimateGas',
|
||||
|
@ -41,7 +42,7 @@ export default class EtherscanRequests extends RPCRequests {
|
|||
};
|
||||
}
|
||||
|
||||
public ethCall(transaction): CallRequest {
|
||||
public ethCall(transaction: Pick<IHexStrTransaction, 'to' | 'data'>): CallRequest {
|
||||
return {
|
||||
module: 'proxy',
|
||||
action: 'eth_call',
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -13,14 +13,13 @@ import {
|
|||
import { hexEncodeData } from './utils';
|
||||
import { TxObj } from '../INode';
|
||||
import { Token } from 'types/network';
|
||||
import { IHexStrTransaction } from 'libs/transaction';
|
||||
|
||||
export default class RPCRequests {
|
||||
public getNetVersion() {
|
||||
return { method: 'net_version' };
|
||||
}
|
||||
|
||||
/* TODO: Fix `| any` on all of these */
|
||||
|
||||
public sendRawTx(signedTx: string): SendRawTxRequest | any {
|
||||
return {
|
||||
method: 'eth_sendRawTransaction',
|
||||
|
@ -28,7 +27,7 @@ export default class RPCRequests {
|
|||
};
|
||||
}
|
||||
|
||||
public estimateGas(transaction): EstimateGasRequest | any {
|
||||
public estimateGas(transaction: Partial<IHexStrTransaction>): EstimateGasRequest | any {
|
||||
return {
|
||||
method: 'eth_estimateGas',
|
||||
params: [transaction]
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -6,6 +6,7 @@ import { IFullWallet } from 'libs/wallet';
|
|||
import { translateRaw } from 'translations';
|
||||
import { ITransaction, IHexStrTransaction } from '../typings';
|
||||
import { hexEncodeQuantity, hexEncodeData } from 'libs/nodes/rpc/utils';
|
||||
import { TransactionFieldValues } from 'selectors/transaction/helpers';
|
||||
|
||||
// we dont include the signature paramaters because web3 transactions are unsigned
|
||||
const computeIndexingHash = (tx: Buffer) => bufferToHex(makeTransaction(tx).hash(false));
|
||||
|
@ -75,7 +76,13 @@ const validAddress = (t: ITransaction) => {
|
|||
};
|
||||
|
||||
const makeTransaction = (
|
||||
t: Partial<Tx> | Partial<ITransaction> | Partial<IHexStrTransaction> | Buffer | string
|
||||
t:
|
||||
| Partial<Tx>
|
||||
| Partial<ITransaction>
|
||||
| Partial<IHexStrTransaction>
|
||||
| Buffer
|
||||
| string
|
||||
| TransactionFieldValues
|
||||
) => new Tx(t);
|
||||
|
||||
//TODO: check that addresses are always checksummed
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}` : ''
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 => ({
|
||||
|
|
|
@ -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];
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }),
|
||||
{}
|
||||
);
|
||||
|
|
|
@ -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)
|
||||
];
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}, {});
|
||||
|
|
|
@ -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'
|
||||
);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
import { AppState } from 'reducers';
|
||||
import { ICurrentTo, ICurrentValue } from 'selectors/transaction';
|
||||
import { isNetworkUnit } from 'selectors/config';
|
||||
|
||||
type TransactionFields = AppState['transaction']['fields'];
|
||||
|
||||
export type TransactionFieldValues = {
|
||||
[field in keyof TransactionFields]: TransactionFields[field]['value']
|
||||
};
|
||||
|
||||
export const reduceToValues = (transactionFields: AppState['transaction']['fields']) =>
|
||||
Object.keys(transactionFields).reduce(
|
||||
(obj, currFieldName) => {
|
||||
Object.keys(transactionFields).reduce<TransactionFieldValues>(
|
||||
(obj, currFieldName: keyof TransactionFields) => {
|
||||
const currField = transactionFields[currFieldName];
|
||||
return { ...obj, [currFieldName]: currField.value };
|
||||
},
|
||||
{} as any //TODO: Fix types
|
||||
{} as TransactionFieldValues
|
||||
);
|
||||
|
||||
export const isFullTx = (
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
State as TransactionState
|
||||
} from 'reducers/transaction';
|
||||
import { State as SwapState, INITIAL_STATE as swapInitialState } from 'reducers/swap';
|
||||
import { applyMiddleware, createStore } from 'redux';
|
||||
import { applyMiddleware, createStore, Store } from 'redux';
|
||||
import { composeWithDevTools } from 'redux-devtools-extension';
|
||||
import { createLogger } from 'redux-logger';
|
||||
import createSagaMiddleware from 'redux-saga';
|
||||
|
@ -24,7 +24,7 @@ const configureStore = () => {
|
|||
});
|
||||
const sagaMiddleware = createSagaMiddleware();
|
||||
let middleware;
|
||||
let store;
|
||||
let store: Store<AppState>;
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
middleware = composeWithDevTools(
|
||||
|
@ -45,7 +45,7 @@ const configureStore = () => {
|
|||
|
||||
const savedTransactionState = loadStatePropertyOrEmptyObject<TransactionState>('transaction');
|
||||
|
||||
const persistedInitialState = {
|
||||
const persistedInitialState: Partial<AppState> = {
|
||||
transaction: {
|
||||
...transactionInitialState,
|
||||
fields: {
|
||||
|
@ -65,10 +65,10 @@ const configureStore = () => {
|
|||
...rehydrateConfigAndCustomTokenState()
|
||||
};
|
||||
|
||||
store = createStore(RootReducer, persistedInitialState, middleware);
|
||||
store = createStore<AppState>(RootReducer, persistedInitialState as any, middleware);
|
||||
|
||||
// Add all of the sagas to the middleware
|
||||
Object.keys(sagas).forEach(saga => {
|
||||
Object.keys(sagas).forEach((saga: keyof typeof sagas) => {
|
||||
sagaMiddleware.run(sagas[saga]);
|
||||
});
|
||||
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
declare module 'ethereum-blockies' {
|
||||
export function toDataUrl(address: string): string;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
declare module 'ethereumjs-abi' {
|
||||
import BN from 'bn.js';
|
||||
type Values = (string | number | BN)[];
|
||||
type Types = string[];
|
||||
export function eventID(name: string, types: Types): Buffer;
|
||||
export function methodID(name: string, types: Types): Buffer;
|
||||
export function rawEncode(types: Types, values: Values): Buffer;
|
||||
export function rawDecode(
|
||||
types: Types,
|
||||
data: string | Buffer
|
||||
): (Buffer | boolean | number | BN | string)[];
|
||||
export function simpleEncode(method: string, values: Values): Buffer;
|
||||
export function simpleDecode(
|
||||
method: string,
|
||||
data: string | Buffer
|
||||
): (Buffer | boolean | number | BN | string)[];
|
||||
export function stringify(types: Types, values: Values): string;
|
||||
export function solidityPack(types: Types, values: Values): Buffer;
|
||||
export function soliditySHA3(types: Types, values: Values): Buffer;
|
||||
export function soliditySHA256(types: Types, values: Values): Buffer;
|
||||
export function solidityRIPEMD160(types: Types, values: Values): Buffer;
|
||||
export function fromSerpent(sig: string): Types;
|
||||
export function toSerpent(types: Types): string;
|
||||
}
|
|
@ -92,7 +92,7 @@ declare module 'ethereumjs-tx' {
|
|||
* sign a transaction with a given a private key
|
||||
* @param {Buffer} privateKey
|
||||
*/
|
||||
public sign(privateKey: Buffer);
|
||||
public sign(privateKey: Buffer): void;
|
||||
|
||||
/**
|
||||
* The amount of gas paid for the data in this tx
|
||||
|
|
|
@ -65,7 +65,7 @@ declare module 'ethereumjs-wallet/hdkey' {
|
|||
/**
|
||||
* @description derive a node based on a child index
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
declare module 'ethjs-util' {
|
||||
export function arrayContainsArray(arrayA: any[], arrayB: any[]): Boolean;
|
||||
export function getBinarySize(num: string): number;
|
||||
export function intToBuffer(integer: number): Buffer;
|
||||
export function isHexPrefixed(hex: string): boolean;
|
||||
export function stripHexPrefix(hexWithPrefix: string): string;
|
||||
export function padToEven(unpaddedNumber: string): string;
|
||||
export function intToHex(integer: number): string;
|
||||
export function fromAscii(ascii: string): string;
|
||||
export function fromUtf8(utf8: string): string;
|
||||
export function toAscii(nonAscii: string): string;
|
||||
export function toUtf8(nonUtf8: string): string;
|
||||
export function getKeys(keys: any[], query: string): any[];
|
||||
export function isHexString(inputString: string): boolean;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
declare module 'hdkey' {
|
||||
export default class HDKey {
|
||||
privateKey: Buffer;
|
||||
publicKey: Buffer;
|
||||
chainCode: Buffer | string;
|
||||
static fromMasterSeed(seedBuffer: Buffer, versions?: any[]): HDKey;
|
||||
static fromExtendedKey(base58key: any, versions?: any[]): HDKey;
|
||||
static fromJSON(obj: any): HDKey;
|
||||
derive(path: string): HDKey;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
declare module 'idna-uts46' {
|
||||
export interface Options {
|
||||
transitional?: boolean;
|
||||
useStd3ASCII?: boolean;
|
||||
verifyDnsLength?: boolean;
|
||||
}
|
||||
|
||||
export function toAscii(domain: string, options: Options): string;
|
||||
export function toUnicode(domain: string, args: Options): string;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
declare module 'ledgerco' {
|
||||
// TODO: fill the library typings out
|
||||
export const comm_u2f: any;
|
||||
export class eth {
|
||||
constructor(transport: any);
|
||||
getAddress_async(
|
||||
path: string,
|
||||
boolDisplay?: boolean,
|
||||
boolChaincode?: boolean
|
||||
): Promise<{
|
||||
publicKey: string;
|
||||
address: string;
|
||||
chainCode: string;
|
||||
}>;
|
||||
|
||||
signTransaction_async(
|
||||
path: string,
|
||||
rawTxHex: string
|
||||
): Promise<{
|
||||
s: string;
|
||||
v: string;
|
||||
r: string;
|
||||
}>;
|
||||
|
||||
getAppConfiguration_async(): Promise<{
|
||||
arbitraryDataEnabled: number;
|
||||
version: string;
|
||||
}>;
|
||||
|
||||
signPersonalMessage_async(
|
||||
path: string,
|
||||
messageHex: string
|
||||
): Promise<{
|
||||
v: number;
|
||||
s: string;
|
||||
r: string;
|
||||
}>;
|
||||
|
||||
signPersonalMessage_async(
|
||||
path: string,
|
||||
messageHex: string,
|
||||
cb: (signed: any, error: any) => any
|
||||
): void;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
declare module 'react-copy-to-clipboard' {
|
||||
interface Options {
|
||||
debug: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
onCopy?(a: string, b: boolean): void;
|
||||
options?: Options;
|
||||
}
|
||||
|
||||
export class CopyToClipboard extends React.Component<Props> {}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
interface PropTypes {
|
||||
activeStep: number;
|
||||
steps: any[];
|
||||
activeColor?: string;
|
||||
completeColor?: string;
|
||||
defaultColor?: string;
|
||||
activeTitleColor?: string;
|
||||
completeTitleColor?: string;
|
||||
defaultTitleColor?: string;
|
||||
circleFontColor?: string;
|
||||
size?: number;
|
||||
circleFontSize?: number;
|
||||
titleFontSize?: number;
|
||||
circleTop?: number;
|
||||
titleTop?: number;
|
||||
defaultOpacity?: string;
|
||||
completeOpacity?: string;
|
||||
activeOpacity?: string;
|
||||
defaultTitleOpacity?: string;
|
||||
completeTitleOpacity?: string;
|
||||
activeTitleOpacity?: string;
|
||||
barStyle?: string;
|
||||
defaultBarColor?: string;
|
||||
completeBarColor?: string;
|
||||
defaultBorderColor?: string;
|
||||
completeBorderColor?: string;
|
||||
activeBorderColor?: string;
|
||||
defaultBorderStyle?: string;
|
||||
completeBorderStyle?: string;
|
||||
activeBorderStyle?: string;
|
||||
}
|
||||
declare module 'react-stepper-horizontal' {
|
||||
import React from 'react';
|
||||
class Stepper extends React.Component<PropTypes> {
|
||||
constructor();
|
||||
}
|
||||
export = Stepper;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
declare module 'redux-test-utils' {
|
||||
import { Store } from 'react-redux';
|
||||
|
||||
export function createMockStore(testState: any): Store<any>;
|
||||
export function createMockDispatch(testAction: any): any;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
declare module 'wallet-address-validator' {
|
||||
export function validate(
|
||||
address: string,
|
||||
currency?: CurrencyNames | CurrencySymbols,
|
||||
networkType?: 'prod' | 'testnet' | 'both'
|
||||
): boolean;
|
||||
export function getAddressType(address: string): string;
|
||||
}
|
||||
|
||||
type CurrencyNames =
|
||||
| 'bitcoin'
|
||||
| 'litecoin'
|
||||
| 'peercoin'
|
||||
| 'dogecoin'
|
||||
| 'beavercoin'
|
||||
| 'freicoin'
|
||||
| 'protoshares'
|
||||
| 'megacoin'
|
||||
| 'primecoin'
|
||||
| 'auroracoin'
|
||||
| 'namecoin'
|
||||
| 'biocoin';
|
||||
|
||||
type CurrencySymbols =
|
||||
| 'BTC'
|
||||
| 'LTC'
|
||||
| 'PPC'
|
||||
| 'DOGE'
|
||||
| 'BVC'
|
||||
| 'FRC'
|
||||
| 'PTS'
|
||||
| 'MEC'
|
||||
| 'XPM'
|
||||
| 'AUR'
|
||||
| 'NMC'
|
||||
| 'BIO';
|
|
@ -1,13 +1,20 @@
|
|||
import qs from 'query-string';
|
||||
import 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)], []);
|
||||
|
|
|
@ -2,6 +2,7 @@ export const REDUX_STATE = 'REDUX_STATE';
|
|||
import { State as SwapState } from 'reducers/swap';
|
||||
import { IWallet, WalletConfig } from 'libs/wallet';
|
||||
import { sha256 } from 'ethereumjs-util';
|
||||
import { AppState } from 'reducers';
|
||||
|
||||
export function loadState<T>(): T | undefined {
|
||||
try {
|
||||
|
@ -26,8 +27,8 @@ export const saveState = (state: any) => {
|
|||
|
||||
export type SwapLocalStorage = SwapState;
|
||||
|
||||
export function loadStatePropertyOrEmptyObject<T>(key: string): T | undefined {
|
||||
const localStorageState = loadState();
|
||||
export function loadStatePropertyOrEmptyObject<T>(key: keyof AppState): T | undefined {
|
||||
const localStorageState: Partial<AppState> | undefined = loadState();
|
||||
if (localStorageState) {
|
||||
if (localStorageState.hasOwnProperty(key)) {
|
||||
return localStorageState[key] as T;
|
||||
|
|
|
@ -18,8 +18,8 @@ export default function(element: React.ReactElement<any>, opts: PrintOptions = {
|
|||
// Convert popupFeatures into a key=value,key=value string. See
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Window/open#Window_features
|
||||
// for more information.
|
||||
const featuresStr = Object.keys(options.popupFeatures)
|
||||
.map(key => `${key}=${options.popupFeatures[key]}`)
|
||||
const featuresStr = Object.entries(options.popupFeatures)
|
||||
.map(([key, value]) => `${key}=${value}`)
|
||||
.join(',');
|
||||
|
||||
const popup = window.open('about:blank', 'printWindow', featuresStr);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
33
package.json
33
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": {
|
||||
|
|
|
@ -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}'`);
|
||||
}
|
||||
|
|
|
@ -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}'`);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { RPCNode } from '../../common/libs/nodes';
|
||||
import { Validator } from 'jsonschema';
|
||||
import { Validator, ValidatorResult } from 'jsonschema';
|
||||
import { schema } from '../../common/libs/validators';
|
||||
import 'url-search-params-polyfill';
|
||||
import EtherscanNode from 'libs/nodes/etherscan';
|
||||
|
@ -25,6 +25,10 @@ const validRequests = {
|
|||
}
|
||||
};
|
||||
|
||||
interface RPCTestList {
|
||||
[key: string]: ((n: RPCNode) => Promise<ValidatorResult>);
|
||||
}
|
||||
|
||||
const testGetBalance = (n: RPCNode) => {
|
||||
return n.client
|
||||
.call(n.requests.getBalance(validRequests.address))
|
||||
|
@ -44,7 +48,7 @@ const testGetTokenBalance = (n: RPCNode) => {
|
|||
.then(data => v.validate(data, schema.RpcNode));
|
||||
};
|
||||
|
||||
const RPCTests = {
|
||||
const RPCTests: RPCTestList = {
|
||||
getBalance: testGetBalance,
|
||||
estimateGas: testEstimateGas,
|
||||
getTokenBalance: testGetTokenBalance
|
||||
|
|
|
@ -9,7 +9,7 @@ const dockerTag = 'latest';
|
|||
|
||||
function promiseFromChildProcess(command: string): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
return exec(command, (err, stdout) => {
|
||||
return exec(command, (err: string, stdout: string) => {
|
||||
err ? reject(err) : resolve(stdout);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)();
|
||||
|
|
|
@ -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))
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ describe('broadcastTransactionWrapper*', () => {
|
|||
blockExplorer: 'blockExplorer'
|
||||
};
|
||||
|
||||
let random;
|
||||
let random: () => number;
|
||||
const func: any = () => undefined;
|
||||
const action: any = {};
|
||||
const gens: any = {};
|
||||
|
|
|
@ -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));
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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) },
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -21,7 +21,7 @@ describe('handleNonceRequest*', () => {
|
|||
|
||||
const gens: any = {};
|
||||
gens.gen = cloneableGenerator(handleNonceRequest)();
|
||||
let random;
|
||||
let random: () => number;
|
||||
|
||||
beforeAll(() => {
|
||||
random = Math.random;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue