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