estimateGasLimit while sending data + feeLevels fix

pull/2/merge
Szymon Lesisz 6 years ago
parent d4f921ba84
commit 55728f6ba3

@ -120,15 +120,41 @@ const calculateMaxAmount = (balance: string, gasPrice: string, gasLimit: string)
}
const getMaxAmount = () => {
const setAmountAndTotal = (state: State): State => {
// if (state.setMax) {
// const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
// if (!account) return;
// if (isToken) {
// const token: ?Token = findToken(getState().tokens, account.address, state.selectedCurrency, account.deviceState);
// if (!token) return;
// state.amount = token.balance;
// } else {
// state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit);
// }
// }
// state.total = calculateTotal(isToken ? '0' : state.amount, state.gasPrice, state.gasLimit);
return state;
}
export const getFeeLevels = (symbol: string, gasPrice: BigNumber | string, gasLimit: string): Array<FeeLevel> => {
export const getFeeLevels = (symbol: string, gasPrice: BigNumber | string, gasLimit: string, selected?: FeeLevel): Array<FeeLevel> => {
const price: BigNumber = typeof gasPrice === 'string' ? new BigNumber(gasPrice) : gasPrice
const quarter: BigNumber = price.dividedBy(4);
const high: string = price.plus(quarter.times(2)).toString();
const low: string = price.minus(quarter.times(2)).toString();
const customLevel: FeeLevel = selected && selected.value === 'Custom' ? {
value: 'Custom',
gasPrice: selected.gasPrice,
// label: `${ calculateFee(gasPrice, gasLimit) } ${ symbol }`
label: `${ calculateFee(selected.gasPrice, gasLimit) } ${ symbol }`
} : {
value: 'Custom',
gasPrice: low,
label: ''
}
return [
{
@ -146,11 +172,7 @@ export const getFeeLevels = (symbol: string, gasPrice: BigNumber | string, gasLi
gasPrice: low,
label: `${ calculateFee(low, gasLimit) } ${ symbol }`
},
{
value: 'Custom',
gasPrice: low,
label: '',
},
customLevel
]
}
@ -424,12 +446,10 @@ export const onCurrencyChange = (currency: any): ThunkAction => {
let gasLimit: string = '';
let amount: string = currentState.amount;
let total: string;
console.warn("SEL", currency, currentState.coinSymbol)
if (isToken) {
gasLimit = coin.defaultGasLimitTokens.toString();
if (currentState.setMax) {
const token: ?Token = findToken(getState().tokens, account.address, currency.value, accountState.deviceState);
console.warn("SEL", token, currency.value)
if (!token) return;
amount = token.balance;
}
@ -442,7 +462,7 @@ export const onCurrencyChange = (currency: any): ThunkAction => {
total = calculateTotal(amount, currentState.gasPrice, currentState.gasLimit);
}
const feeLevels: Array<FeeLevel> = getFeeLevels(currentState.coinSymbol, currentState.gasPrice, gasLimit);
const feeLevels: Array<FeeLevel> = getFeeLevels(currentState.coinSymbol, currentState.gasPrice, gasLimit, currentState.selectedFeeLevel);
const selectedFeeLevel: ?FeeLevel = feeLevels.find(f => f.value === currentState.selectedFeeLevel.value);
if (!selectedFeeLevel) return;
@ -528,7 +548,6 @@ export const onFeeLevelChange = (feeLevel: FeeLevel): ThunkAction => {
};
if (feeLevel.value === 'Custom') {
// TODO: update value for custom fee
state.advanced = true;
feeLevel.gasPrice = state.gasPrice;
feeLevel.label = `${ calculateFee(state.gasPrice, state.gasLimit) } ${ state.coinSymbol }`;
@ -538,7 +557,6 @@ export const onFeeLevelChange = (feeLevel: FeeLevel): ThunkAction => {
customLevel.label = '';
state.gasPrice = feeLevel.gasPrice;
state.gasLimit = isToken ? coin.defaultGasLimitTokens.toString() : coin.defaultGasLimit.toString();
// reset custom gasLimit
}
if (currentState.setMax) {
@ -563,6 +581,9 @@ export const onFeeLevelChange = (feeLevel: FeeLevel): ThunkAction => {
}
}
// Manually triggered from user
// Update gasPrice to recommended value
export const updateFeeLevels = (): ThunkAction => {
return (dispatch: Dispatch, getState: GetState): void => {
const accountState: ?AccountState = getState().abstractAccount;
@ -570,7 +591,7 @@ export const updateFeeLevels = (): ThunkAction => {
const currentState: State = getState().sendForm;
const isToken: boolean = currentState.selectedCurrency !== currentState.coinSymbol;
const feeLevels: Array<FeeLevel> = getFeeLevels(currentState.coinSymbol, currentState.recommendedGasPrice, currentState.gasLimit);
const feeLevels: Array<FeeLevel> = getFeeLevels(currentState.coinSymbol, currentState.recommendedGasPrice, currentState.gasLimit, currentState.selectedFeeLevel);
const selectedFeeLevel: ?FeeLevel = feeLevels.find(f => f.value === currentState.selectedFeeLevel.value);
if (!selectedFeeLevel) return;
@ -578,8 +599,7 @@ export const updateFeeLevels = (): ThunkAction => {
...currentState,
feeLevels,
selectedFeeLevel,
//gasPrice: currentState.recommendedGasPrice, // TODO HERE!
gasPrice: selectedFeeLevel.gasPrice, // TODO HERE!
gasPrice: selectedFeeLevel.gasPrice,
gasPriceNeedsUpdate: false,
};
@ -642,9 +662,13 @@ export const onGasPriceChange = (gasPrice: string): ThunkAction => {
state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit);
}
}
state.total = calculateTotal(isToken ? '0' : state.amount, state.gasPrice, state.gasLimit);
} else {
// state.gasPrice = currentState.gasPrice;
}
state.total = calculateTotal(isToken ? '0' : state.amount, state.gasPrice, state.gasLimit);
dispatch({
type: SEND.GAS_PRICE_CHANGE,
@ -703,8 +727,8 @@ export const onGasLimitChange = (gasLimit: string): ThunkAction => {
}
}
export const onDataChange = (data: string): ThunkAction => {
return (dispatch: Dispatch, getState: GetState): void => {
export const onDataChange = (data: string): AsyncAction => {
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const currentState: State = getState().sendForm;
const touched = { ...currentState.touched };
touched.data = true;
@ -721,12 +745,44 @@ export const onDataChange = (data: string): ThunkAction => {
state
});
dispatch( validation() );
dispatch( estimateGasPrice() );
}
}
const estimateGasPrice = (): AsyncAction => {
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const accountState: ?AccountState = getState().abstractAccount;
if (!accountState) return;
const web3instance: ?Web3Instance = getState().web3.filter(w3 => w3.network === accountState.network)[0];
if (!web3instance) return;
const web3 = web3instance.web3;
const currentState: State = getState().sendForm;
const data: string = '0x' + (currentState.data.length % 2 === 0 ? currentState.data : '0' + currentState.data);
const gasLimit = await estimateGas(web3instance.web3, {
to: '0xdb6e09ddca62d0959dc4725697e66b8152222aee',
data,
value: web3.toHex(web3.toWei(currentState.amount, 'ether')),
gasPrice: web3.toHex( EthereumjsUnits.convert(currentState.gasPrice, 'gwei', 'wei') ),
});
dispatch({
type: SEND.GAS_LIMIT_CHANGE,
state: {
...currentState,
gasLimit: gasLimit.toString()
}
});
}
}
export const onSend = (): AsyncAction => {
//return onSendERC20();
return async (dispatch: Dispatch, getState: GetState): Promise<any> => {
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const accountState: ?AccountState = getState().abstractAccount;
if (!accountState) return;
@ -741,7 +797,7 @@ export const onSend = (): AsyncAction => {
const address_n = account.addressPath;
let data: string = '';
let data: string = '0x' + currentState.data;
let txAmount: string = web3.toHex(web3.toWei(currentState.amount, 'ether'));
let txAddress: string = currentState.address;
if (isToken) {

@ -49,8 +49,6 @@ export const load = (input: string, network: string): AsyncAction => {
if (!web3instance) return;
const info = await getTokenInfoAsync(web3instance.erc20, input);
info.address = input;
if (info) {
return {
options: [ info ]

@ -18,13 +18,14 @@ import type {
Action,
AsyncAction,
} from '../flowtype';
import type { ContractFactory } from 'web3';
import type { ContractFactory, EstimateGasOptions } from 'web3';
import type { BigNumber } from 'bignumber.js';
import type { Account } from '../reducers/AccountsReducer';
import type { PendingTx } from '../reducers/PendingTxReducer';
import type { Web3Instance } from '../reducers/Web3Reducer';
import type { Token } from '../reducers/TokensReducer';
import type { NetworkToken } from '../reducers/LocalStorageReducer';
export type Web3Action = {
type: typeof WEB3.READY,
@ -384,30 +385,39 @@ export const getNonceAsync = (web3: Web3, address: string): Promise<number> => {
}
export const getTokenInfoAsync = (erc20: ContractFactory, address: string): Promise<any> => {
export const getTokenInfoAsync = (erc20: ContractFactory, address: string): Promise<?NetworkToken> => {
return new Promise((resolve, reject) => {
const contract = erc20.at(address, (error, res) => {
console.warn("callback", error, res)
// console.warn("callback", error, res)
});
const info = {};
// TODO: handle errors
const info: NetworkToken = {
address,
name: '',
symbol: '',
decimals: 0
};
contract.name.call((error: ?Error, name: ?string) => {
if (error) {
//resolve(null);
//return;
resolve(null);
return;
} else if (name) {
info.name = name;
}
info.name = name;
contract.symbol.call((error: ?Error, symbol: ?string) => {
if (error) {
resolve(null);
return;
} else if (symbol) {
info.symbol = symbol;
}
info.symbol = symbol;
contract.decimals.call((error: ?Error, decimals: ?BigNumber) => {
if (decimals) {
info.decimals = decimals.toString();
info.decimals = decimals.toNumber();
resolve(info);
} else {
resolve(null);
@ -418,25 +428,13 @@ export const getTokenInfoAsync = (erc20: ContractFactory, address: string): Prom
});
}
export const estimateGas = (web3: Web3, gasOptions: any): Promise<any> => {
return new Promise((resolve, reject) => {
web3.eth.estimateGas(gasOptions, (error, result) => {
if (error) {
reject(error);
} else {
resolve(result);
}
});
})
}
export const getGasPrice2 = (web3: Web3): Promise<any> => {
export const estimateGas = (web3: Web3, options: EstimateGasOptions): Promise<number> => {
return new Promise((resolve, reject) => {
web3.eth.getGasPrice((error, result) => {
web3.eth.estimateGas(options, (error: ?Error, gas: ?number) => {
if (error) {
reject(error);
} else {
resolve(result);
} else if (typeof gas === 'number'){
resolve(gas);
}
});
})

@ -85,6 +85,7 @@ const AdvancedForm = (props: Props) => {
autoCapitalize="off"
spellCheck="false"
value={ gasLimit }
disabled={ coinSymbol === selectedCurrency && data.length > 0 }
onChange={ event => onGasLimitChange(event.target.value) } />
{ errors.gasLimit ? (<span className="error">{ errors.gasLimit }</span>) : null }
{ warnings.gasLimit ? (<span className="warning">{ warnings.gasLimit }</span>) : null }
@ -121,8 +122,7 @@ const AdvancedForm = (props: Props) => {
<span className="what-is-it"></span>
</Tooltip>
</label>
<textarea value={ data } onChange={ event => onDataChange(event.target.value) }></textarea>
{/* <textarea disabled={ coinSymbol !== selectedCurrency } value={ coinSymbol !== selectedCurrency ? '' : data } onChange={ event => onDataChange(event.target.value) }></textarea> */}
<textarea disabled={ coinSymbol !== selectedCurrency } value={ coinSymbol !== selectedCurrency ? '' : data } onChange={ event => onDataChange(event.target.value) }></textarea>
{ errors.data ? (<span className="error">{ errors.data }</span>) : null }
</div>

@ -36,6 +36,17 @@ declare module 'web3' {
}
declare export type EstimateGasOptions = {
to: string;
data: string;
value?: string;
gasPrice?: string;
}
declare export type RawTransaction = {
id: string;
}
declare class Eth {
getGasPrice: (callback: (error: Error, gasPrice: string) => void) => void,
getBalance: (address: string, callback: (error: Error, balance: BigNumber) => void) => void,
@ -43,10 +54,10 @@ declare module 'web3' {
getTransaction: (txid: string, callback: (error: Error, result: any) => void) => void,
getBlockNumber: (callback: (error: Error, blockNumber: number) => void) => void,
getBlock: (hash: string, callback: (error: Error, result: any) => void) => void,
getAccounts: (callback: (error: Error, accounts: Array<EthereumAddressT>) => void) => void,
sign: (payload: string, signer: EthereumAddressT) => Promise<string>,
// getAccounts: (callback: (error: Error, accounts: Array<EthereumAddressT>) => void) => void,
// sign: (payload: string, signer: EthereumAddressT) => Promise<string>,
contract: (abi: Array<Object>) => ContractFactory,
estimateGas: (options: any, callback: (error: Error, result: any) => void) => void,
estimateGas: (options: EstimateGasOptions, callback: (error: ?Error, gas: ?number) => void) => void,
sendRawTransaction: (tx: any, callback: (error: Error, result: any) => void) => void,
filter: (type: string) => Filter; // return intance with "watch"
}

Loading…
Cancel
Save