mirror of
https://github.com/trezor/trezor-wallet
synced 2024-11-24 09:18:09 +00:00
estimateGasLimit while sending data + feeLevels fix
This commit is contained in:
parent
d4f921ba84
commit
55728f6ba3
@ -120,16 +120,42 @@ 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 [
|
||||
{
|
||||
value: 'High',
|
||||
@ -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> => {
|
||||
export const estimateGas = (web3: Web3, options: EstimateGasOptions): Promise<number> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
web3.eth.estimateGas(gasOptions, (error, result) => {
|
||||
web3.eth.estimateGas(options, (error: ?Error, gas: ?number) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
export const getGasPrice2 = (web3: Web3): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
web3.eth.getGasPrice((error, result) => {
|
||||
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…
Reference in New Issue
Block a user