Address Miscellaneous Todos (#534)
* Fix TODO issues * Update / Removd old comments * Update types & Fix todos
This commit is contained in:
parent
43d90c9dae
commit
d1174fb324
|
@ -38,7 +38,7 @@ export default class AccountInfo extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
// TODO: don't use any;
|
||||
public toggleShowLongBalance = (e: any) => {
|
||||
public toggleShowLongBalance = (e: React.SyntheticEvent<HTMLSpanElement>) => {
|
||||
e.preventDefault();
|
||||
this.setState(state => {
|
||||
return {
|
||||
|
@ -55,9 +55,7 @@ export default class AccountInfo extends React.Component<Props, State> {
|
|||
return (
|
||||
<div className="AccountInfo">
|
||||
<div className="AccountInfo-section">
|
||||
<h5 className="AccountInfo-section-header">
|
||||
{translate('sidebar_AccountAddr')}
|
||||
</h5>
|
||||
<h5 className="AccountInfo-section-header">{translate('sidebar_AccountAddr')}</h5>
|
||||
<div className="AccountInfo-address">
|
||||
<div className="AccountInfo-address-icon">
|
||||
<Identicon address={address} size="100%" />
|
||||
|
@ -67,9 +65,7 @@ export default class AccountInfo extends React.Component<Props, State> {
|
|||
</div>
|
||||
|
||||
<div className="AccountInfo-section">
|
||||
<h5 className="AccountInfo-section-header">
|
||||
{translate('sidebar_AccountBal')}
|
||||
</h5>
|
||||
<h5 className="AccountInfo-section-header">{translate('sidebar_AccountBal')}</h5>
|
||||
<ul className="AccountInfo-list">
|
||||
<li className="AccountInfo-list-item">
|
||||
<span
|
||||
|
@ -86,20 +82,14 @@ export default class AccountInfo extends React.Component<Props, State> {
|
|||
/>
|
||||
)}
|
||||
</span>
|
||||
{!balance.isPending ? (
|
||||
balance.wei ? (
|
||||
<span> {network.name}</span>
|
||||
) : null
|
||||
) : null}
|
||||
{!balance.isPending ? balance.wei ? <span> {network.name}</span> : null : null}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{(!!blockExplorer || !!tokenExplorer) && (
|
||||
<div className="AccountInfo-section">
|
||||
<h5 className="AccountInfo-section-header">
|
||||
{translate('sidebar_TransHistory')}
|
||||
</h5>
|
||||
<h5 className="AccountInfo-section-header">{translate('sidebar_TransHistory')}</h5>
|
||||
<ul className="AccountInfo-list">
|
||||
{!!blockExplorer && (
|
||||
<li className="AccountInfo-list-item">
|
||||
|
|
|
@ -41,11 +41,7 @@ export default class TokenRow extends React.Component<Props, State> {
|
|||
/>
|
||||
)}
|
||||
<span>
|
||||
<UnitDisplay
|
||||
value={balance}
|
||||
decimal={decimal}
|
||||
displayShortBalance={!showLongBalance}
|
||||
/>
|
||||
<UnitDisplay value={balance} decimal={decimal} displayShortBalance={!showLongBalance} />
|
||||
</span>
|
||||
</td>
|
||||
<td className="TokenRow-symbol">{symbol}</td>
|
||||
|
@ -53,10 +49,7 @@ export default class TokenRow extends React.Component<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
public toggleShowLongBalance = (
|
||||
// TODO: don't use any
|
||||
e: any
|
||||
) => {
|
||||
public toggleShowLongBalance = (e: React.SyntheticEvent<HTMLTableDataCellElement>) => {
|
||||
e.preventDefault();
|
||||
this.setState(state => {
|
||||
return {
|
||||
|
|
|
@ -82,18 +82,14 @@ export class WalletDecrypt extends Component<Props, State> {
|
|||
password: ''
|
||||
},
|
||||
unlock: this.props.unlockKeystore,
|
||||
helpLink: `${
|
||||
knowledgeBaseURL
|
||||
}/private-keys-passwords/difference-beween-private-key-and-keystore-file.html`
|
||||
helpLink: `${knowledgeBaseURL}/private-keys-passwords/difference-beween-private-key-and-keystore-file.html`
|
||||
},
|
||||
'mnemonic-phrase': {
|
||||
lid: 'x_Mnemonic',
|
||||
component: MnemonicDecrypt,
|
||||
initialParams: {},
|
||||
unlock: this.props.unlockMnemonic,
|
||||
helpLink: `${
|
||||
knowledgeBaseURL
|
||||
}/private-keys-passwords/difference-beween-private-key-and-keystore-file.html`
|
||||
helpLink: `${knowledgeBaseURL}/private-keys-passwords/difference-beween-private-key-and-keystore-file.html`
|
||||
},
|
||||
'private-key': {
|
||||
lid: 'x_PrivKey2',
|
||||
|
@ -103,9 +99,7 @@ export class WalletDecrypt extends Component<Props, State> {
|
|||
password: ''
|
||||
},
|
||||
unlock: this.props.unlockPrivateKey,
|
||||
helpLink: `${
|
||||
knowledgeBaseURL
|
||||
}/private-keys-passwords/difference-beween-private-key-and-keystore-file.html`
|
||||
helpLink: `${knowledgeBaseURL}/private-keys-passwords/difference-beween-private-key-and-keystore-file.html`
|
||||
},
|
||||
'view-only': {
|
||||
lid: 'View with Address Only',
|
||||
|
|
|
@ -14,10 +14,7 @@ export default function Identicon(props: Props) {
|
|||
? toDataUrl(props.address.toLowerCase())
|
||||
: '';
|
||||
return (
|
||||
<div
|
||||
style={{ position: 'relative', width: size, height: size }}
|
||||
title="Address Identicon"
|
||||
>
|
||||
<div style={{ position: 'relative', width: size, height: size }} title="Address Identicon">
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
|
@ -33,7 +30,7 @@ export default function Identicon(props: Props) {
|
|||
`
|
||||
}}
|
||||
/>
|
||||
{identiconDataUrl &&
|
||||
{identiconDataUrl && (
|
||||
<img
|
||||
src={identiconDataUrl}
|
||||
style={{
|
||||
|
@ -41,7 +38,8 @@ export default function Identicon(props: Props) {
|
|||
width: '100%',
|
||||
height: '100%'
|
||||
}}
|
||||
/>}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -104,9 +104,7 @@ export default class DownloadWallet extends Component<Props, State> {
|
|||
</li>
|
||||
<li>
|
||||
<NewTabLink
|
||||
href={`${
|
||||
knowledgeBaseURL
|
||||
}/private-keys-passwords/difference-beween-private-key-and-keystore-file`}
|
||||
href={`${knowledgeBaseURL}/private-keys-passwords/difference-beween-private-key-and-keystore-file`}
|
||||
>
|
||||
<strong>{translate('GEN_Help_14')}</strong>
|
||||
</NewTabLink>
|
||||
|
|
|
@ -66,9 +66,7 @@ const help = (
|
|||
</li>
|
||||
<li>
|
||||
<NewTabLink
|
||||
href={`${
|
||||
knowledgeBaseURL
|
||||
}/private-keys-passwords/difference-beween-private-key-and-keystore-file`}
|
||||
href={`${knowledgeBaseURL}/private-keys-passwords/difference-beween-private-key-and-keystore-file`}
|
||||
>
|
||||
<strong>{translate('GEN_Help_16')}</strong>
|
||||
</NewTabLink>
|
||||
|
|
|
@ -31,35 +31,17 @@ import {
|
|||
import { UnitKey, Wei, getDecimal, toWei } from 'libs/units';
|
||||
import { isValidETHAddress } from 'libs/validators';
|
||||
// LIBS
|
||||
import {
|
||||
IWallet,
|
||||
Balance,
|
||||
Web3Wallet,
|
||||
LedgerWallet,
|
||||
TrezorWallet
|
||||
} from 'libs/wallet';
|
||||
import { IWallet, Balance, Web3Wallet, LedgerWallet, TrezorWallet } from 'libs/wallet';
|
||||
import pickBy from 'lodash/pickBy';
|
||||
import React from 'react';
|
||||
// REDUX
|
||||
import { connect } from 'react-redux';
|
||||
import { AppState } from 'reducers';
|
||||
import { showNotification, TShowNotification } from 'actions/notifications';
|
||||
import {
|
||||
broadcastTx,
|
||||
TBroadcastTx,
|
||||
resetWallet,
|
||||
TResetWallet
|
||||
} from 'actions/wallet';
|
||||
import {
|
||||
pollOfflineStatus as dPollOfflineStatus,
|
||||
TPollOfflineStatus
|
||||
} from 'actions/config';
|
||||
import { broadcastTx, TBroadcastTx, resetWallet, TResetWallet } from 'actions/wallet';
|
||||
import { pollOfflineStatus as dPollOfflineStatus, TPollOfflineStatus } from 'actions/config';
|
||||
// SELECTORS
|
||||
import {
|
||||
getGasPriceGwei,
|
||||
getNetworkConfig,
|
||||
getNodeLib
|
||||
} from 'selectors/config';
|
||||
import { getGasPriceGwei, getNetworkConfig, getNodeLib } from 'selectors/config';
|
||||
import {
|
||||
getTokenBalances,
|
||||
getTokens,
|
||||
|
@ -264,9 +246,7 @@ export class SendTransaction extends React.Component<Props, State> {
|
|||
const { offline, forceOffline, balance } = this.props;
|
||||
const customMessage = customMessages.find(m => m.to === to);
|
||||
const decimal =
|
||||
unit === 'ether'
|
||||
? getDecimal('ether')
|
||||
: (this.state.token && this.state.token.decimal) || 0;
|
||||
unit === 'ether' ? getDecimal('ether') : (this.state.token && this.state.token.decimal) || 0;
|
||||
const isWeb3Wallet = this.props.wallet instanceof Web3Wallet;
|
||||
const isLedgerWallet = this.props.wallet instanceof LedgerWallet;
|
||||
const isTrezorWallet = this.props.wallet instanceof TrezorWallet;
|
||||
|
@ -277,9 +257,7 @@ export class SendTransaction extends React.Component<Props, State> {
|
|||
title={
|
||||
<div>
|
||||
{translate('NAV_SendEther')}
|
||||
{offline || forceOffline ? (
|
||||
<span style={{ color: 'red' }}> (Offline)</span>
|
||||
) : null}
|
||||
{offline || forceOffline ? <span style={{ color: 'red' }}> (Offline)</span> : null}
|
||||
</div>
|
||||
}
|
||||
allowReadOnly={true}
|
||||
|
@ -314,24 +292,14 @@ export class SendTransaction extends React.Component<Props, State> {
|
|||
isReadOnly={readOnly}
|
||||
onUnitChange={this.onUnitChange}
|
||||
/>
|
||||
<GasField
|
||||
value={gasLimit}
|
||||
onChange={readOnly ? void 0 : this.onGasChange}
|
||||
/>
|
||||
<GasField value={gasLimit} onChange={readOnly ? void 0 : this.onGasChange} />
|
||||
{(offline || forceOffline) && (
|
||||
<div>
|
||||
<NonceField
|
||||
value={nonce}
|
||||
onChange={this.onNonceChange}
|
||||
placeholder={'0'}
|
||||
/>
|
||||
<NonceField value={nonce} onChange={this.onNonceChange} placeholder={'0'} />
|
||||
</div>
|
||||
)}
|
||||
{unit === 'ether' && (
|
||||
<DataField
|
||||
value={data}
|
||||
onChange={readOnly ? void 0 : this.onDataChange}
|
||||
/>
|
||||
<DataField value={data} onChange={readOnly ? void 0 : this.onDataChange} />
|
||||
)}
|
||||
<CustomMessage message={customMessage} />
|
||||
|
||||
|
@ -341,9 +309,7 @@ export class SendTransaction extends React.Component<Props, State> {
|
|||
disabled={this.state.generateDisabled}
|
||||
className="btn btn-info btn-block"
|
||||
onClick={
|
||||
isWeb3Wallet
|
||||
? this.generateWeb3TxFromState
|
||||
: this.generateTxFromState
|
||||
isWeb3Wallet ? this.generateWeb3TxFromState : this.generateTxFromState
|
||||
}
|
||||
>
|
||||
{isWeb3Wallet
|
||||
|
@ -392,17 +358,12 @@ export class SendTransaction extends React.Component<Props, State> {
|
|||
/>
|
||||
{offline && (
|
||||
<p>
|
||||
To broadcast this transaction, paste the above
|
||||
into{' '}
|
||||
To broadcast this transaction, paste the above into{' '}
|
||||
<a href="https://myetherwallet.com/pushTx">
|
||||
{' '}
|
||||
myetherwallet.com/pushTx
|
||||
</a>{' '}
|
||||
or{' '}
|
||||
<a href="https://etherscan.io/pushTx">
|
||||
{' '}
|
||||
etherscan.io/pushTx
|
||||
</a>
|
||||
or <a href="https://etherscan.io/pushTx"> etherscan.io/pushTx</a>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
@ -432,9 +393,7 @@ export class SendTransaction extends React.Component<Props, State> {
|
|||
<main className="col-sm-8">
|
||||
<div className="Tab-content-pane">
|
||||
<h4>Sorry...</h4>
|
||||
<p>
|
||||
MetaMask / Mist wallets are not available in offline mode.
|
||||
</p>
|
||||
<p>MetaMask / Mist wallets are not available in offline mode.</p>
|
||||
</div>
|
||||
</main>
|
||||
)}
|
||||
|
@ -579,23 +538,14 @@ export class SendTransaction extends React.Component<Props, State> {
|
|||
this.setState({ gasLimit: value, gasChanged: true });
|
||||
};
|
||||
|
||||
public handleEverythingAmountChange = (
|
||||
value: string,
|
||||
unit: string
|
||||
): string => {
|
||||
public handleEverythingAmountChange = (value: string, unit: string): string => {
|
||||
if (unit === 'ether') {
|
||||
const { balance, gasPrice } = this.props;
|
||||
const { gasLimit } = this.state;
|
||||
const bigGasLimit = Wei(gasLimit);
|
||||
value = getBalanceMinusGasCosts(
|
||||
bigGasLimit,
|
||||
gasPrice,
|
||||
balance.wei
|
||||
).toString();
|
||||
value = getBalanceMinusGasCosts(bigGasLimit, gasPrice, balance.wei).toString();
|
||||
} else {
|
||||
const tokenBalance = this.props.tokenBalances.find(
|
||||
tBalance => tBalance.symbol === unit
|
||||
);
|
||||
const tokenBalance = this.props.tokenBalances.find(tBalance => tBalance.symbol === unit);
|
||||
if (!tokenBalance) {
|
||||
throw new Error(`${unit}: not found in token balances;`);
|
||||
}
|
||||
|
@ -673,10 +623,7 @@ export class SendTransaction extends React.Component<Props, State> {
|
|||
if (network.blockExplorer !== undefined) {
|
||||
this.props.showNotification(
|
||||
'success',
|
||||
<TransactionSucceeded
|
||||
txHash={txHash}
|
||||
blockExplorer={network.blockExplorer}
|
||||
/>,
|
||||
<TransactionSucceeded txHash={txHash} blockExplorer={network.blockExplorer} />,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// TODO support events, constructors, fallbacks, array slots, types
|
||||
import abi from 'ethereumjs-abi';
|
||||
import BN from 'bn.js';
|
||||
|
||||
// There are too many to enumerate since they're somewhat dynamic, list here
|
||||
// https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#types
|
||||
|
@ -24,8 +25,7 @@ export type ABI = ABIMethod[];
|
|||
|
||||
export interface DecodedCall {
|
||||
method: ABIMethod;
|
||||
// TODO: Type this to be an array of BNs when we switch
|
||||
args: any[];
|
||||
args: BN[];
|
||||
}
|
||||
|
||||
// Contract helper, returns data for given call
|
||||
|
@ -52,23 +52,17 @@ export default class Contract {
|
|||
}
|
||||
|
||||
public getMethodSelector(method: ABIMethod): string {
|
||||
return abi
|
||||
.methodID(method.name, this.getMethodTypes(method))
|
||||
.toString('hex');
|
||||
return abi.methodID(method.name, this.getMethodTypes(method)).toString('hex');
|
||||
}
|
||||
|
||||
public call(name: string, args: any[]): string {
|
||||
const method = this.getMethodAbi(name);
|
||||
|
||||
return (
|
||||
'0x' + this.getMethodSelector(method) + this.encodeArgs(method, args)
|
||||
);
|
||||
return '0x' + this.getMethodSelector(method) + this.encodeArgs(method, args);
|
||||
}
|
||||
|
||||
public $call(data: string): DecodedCall {
|
||||
const method = this.abi.find(
|
||||
mth => data.indexOf(this.getMethodSelector(mth)) !== -1
|
||||
);
|
||||
const method = this.abi.find(mth => data.indexOf(this.getMethodSelector(mth)) !== -1);
|
||||
|
||||
if (!method) {
|
||||
throw new Error('Unknown method');
|
||||
|
@ -89,8 +83,7 @@ export default class Contract {
|
|||
return abi.rawEncode(inputTypes, args).toString('hex');
|
||||
}
|
||||
|
||||
// TODO: Type this return to be an array of BNs when we switch
|
||||
public decodeArgs(method: ABIMethod, argData: string): any[] {
|
||||
public decodeArgs(method: ABIMethod, argData: string): BN[] {
|
||||
// Remove method selector from data, if present
|
||||
argData = argData.replace(`0x${this.getMethodSelector(method)}`, '');
|
||||
// Convert argdata to a hex buffer for ethereumjs-abi
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
// TODO - move this out of transaction; it's only for estimating gas costs
|
||||
export interface TransactionWithoutGas {
|
||||
to: string;
|
||||
value: string;
|
||||
|
|
|
@ -2,7 +2,6 @@ import { Token } from 'config/data';
|
|||
import EthTx from 'ethereumjs-tx';
|
||||
import { addHexPrefix, padToEven, toChecksumAddress } from 'ethereumjs-util';
|
||||
import ERC20 from 'libs/erc20';
|
||||
import { TransactionWithoutGas } from 'libs/messages';
|
||||
import { RPCNode } from 'libs/nodes';
|
||||
import { INode } from 'libs/nodes/INode';
|
||||
import { UnitKey, Wei, TokenValue, toTokenBase } from 'libs/units';
|
||||
|
@ -71,10 +70,7 @@ export function getTransactionFields(tx: EthTx) {
|
|||
};
|
||||
}
|
||||
|
||||
function getValue(
|
||||
token: Token | null | undefined,
|
||||
tx: ExtendedRawTransaction
|
||||
): Wei {
|
||||
function getValue(token: Token | null | undefined, tx: ExtendedRawTransaction): Wei {
|
||||
let value;
|
||||
if (token) {
|
||||
value = Wei(ERC20.$transfer(tx.data).value);
|
||||
|
@ -93,10 +89,7 @@ async function getBalance(
|
|||
const ETHBalance = await node.getBalance(from);
|
||||
let balance: Wei;
|
||||
if (token) {
|
||||
balance = toTokenBase(
|
||||
await node.getTokenBalance(tx.from, token).toString(),
|
||||
token.decimal
|
||||
);
|
||||
balance = toTokenBase(await node.getTokenBalance(tx.from, token).toString(), token.decimal);
|
||||
} else {
|
||||
balance = ETHBalance;
|
||||
}
|
||||
|
@ -159,9 +152,7 @@ function generateTxValidation(
|
|||
// Reject gasPrice over 1000gwei (1000000000000)
|
||||
const gwei = Wei('1000000000000');
|
||||
if (gasPrice.gt(gwei)) {
|
||||
throw new Error(
|
||||
'Gas price too high. Please contact support if this was not a mistake.'
|
||||
);
|
||||
throw new Error('Gas price too high. Please contact support if this was not a mistake.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,12 +206,12 @@ export async function generateCompleteTransactionFromRawTransaction(
|
|||
export async function formatTxInput(
|
||||
wallet: IFullWallet,
|
||||
{ token, unit, value, to, data }: TransactionInput
|
||||
): Promise<TransactionWithoutGas> {
|
||||
): Promise<{ to: string; from: string; value: string; data: string }> {
|
||||
if (unit === 'ether') {
|
||||
return {
|
||||
to,
|
||||
from: await wallet.getAddressString(),
|
||||
value: toHexWei(value), //turn users ether to wei
|
||||
value: toHexWei(value), // turn users ether to wei
|
||||
data
|
||||
};
|
||||
} else {
|
||||
|
@ -246,10 +237,7 @@ export async function confirmAndSendWeb3Transaction(
|
|||
chainId: number,
|
||||
transactionInput: TransactionInput
|
||||
): Promise<string> {
|
||||
const { from, to, value, data } = await formatTxInput(
|
||||
wallet,
|
||||
transactionInput
|
||||
);
|
||||
const { from, to, value, data } = await formatTxInput(wallet, transactionInput);
|
||||
const transaction: ExtendedRawTransaction = {
|
||||
nonce: await nodeLib.getTransactionCount(from),
|
||||
from,
|
||||
|
@ -276,10 +264,7 @@ export async function generateCompleteTransaction(
|
|||
offline?: boolean
|
||||
): Promise<CompleteTransaction> {
|
||||
const { token } = transactionInput;
|
||||
const { from, to, value, data } = await formatTxInput(
|
||||
wallet,
|
||||
transactionInput
|
||||
);
|
||||
const { from, to, value, data } = await formatTxInput(wallet, transactionInput);
|
||||
const transaction: ExtendedRawTransaction = {
|
||||
nonce: nonce ? `0x${nonce}` : await nodeLib.getTransactionCount(from),
|
||||
from,
|
||||
|
@ -301,20 +286,14 @@ export async function generateCompleteTransaction(
|
|||
}
|
||||
|
||||
// TODO determine best place for helper function
|
||||
export function getBalanceMinusGasCosts(
|
||||
gasLimit: Wei,
|
||||
gasPrice: Wei,
|
||||
balance: Wei
|
||||
): Wei {
|
||||
export function getBalanceMinusGasCosts(gasLimit: Wei, gasPrice: Wei, balance: Wei): Wei {
|
||||
const weiGasCosts = gasPrice.mul(gasLimit);
|
||||
const weiBalanceMinusGasCosts = balance.sub(weiGasCosts);
|
||||
return Wei(weiBalanceMinusGasCosts);
|
||||
}
|
||||
|
||||
export function decodeTransaction(transaction: EthTx, token: Token | false) {
|
||||
const { to, value, data, gasPrice, nonce, from } = getTransactionFields(
|
||||
transaction
|
||||
);
|
||||
const { to, value, data, gasPrice, nonce, from } = getTransactionFields(transaction);
|
||||
let fixedValue: TokenValue;
|
||||
let toAddress;
|
||||
|
||||
|
|
|
@ -15,13 +15,9 @@ export function padLeftEven(hex: string) {
|
|||
return hex.length % 2 !== 0 ? `0${hex}` : hex;
|
||||
}
|
||||
|
||||
// TODO: refactor to not mutate argument
|
||||
export function sanitizeHex(hex: string) {
|
||||
hex = hex.substring(0, 2) === '0x' ? hex.substring(2) : hex;
|
||||
if (hex === '') {
|
||||
return '';
|
||||
}
|
||||
return `0x${padLeftEven(hex)}`;
|
||||
const hexStr = hex.substring(0, 2) === '0x' ? hex.substring(2) : hex;
|
||||
return hex !== '' ? `0x${padLeftEven(hexStr)}` : '';
|
||||
}
|
||||
|
||||
export function networkIdToName(networkId: string | number): string {
|
||||
|
|
Loading…
Reference in New Issue