diff --git a/package.json b/package.json index 3384d2fd..c5e620f1 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@ledgerhq/hw-transport": "^4.12.0", "@ledgerhq/hw-transport-node-hid": "^4.12.0", "@ledgerhq/ledger-core": "1.4.1", - "@ledgerhq/live-common": "2.22.0", + "@ledgerhq/live-common": "2.23.0", "axios": "^0.18.0", "babel-runtime": "^6.26.0", "bcryptjs": "^2.4.3", diff --git a/src/api/Ethereum.js b/src/api/Ethereum.js index 9b3d4c9b..a182b681 100644 --- a/src/api/Ethereum.js +++ b/src/api/Ethereum.js @@ -46,31 +46,35 @@ export const apiForCurrency = (currency: CryptoCurrency): API => { return { async getTransactions(address, blockHash) { const { data } = await userFriendlyError( - axios.get(`${baseURL}/addresses/${address}/transactions`, { - params: { blockHash, noToken: 1 }, - }), + retry( + () => + axios.get(`${baseURL}/addresses/${address}/transactions`, { + params: { blockHash, noToken: 1 }, + }), + { maxRetry: 3 }, + ), ) return data }, async getCurrentBlock() { - const { data } = await userFriendlyError(retry(() => axios.get(`${baseURL}/blocks/current`))) + const { data } = await userFriendlyError( + retry(() => axios.get(`${baseURL}/blocks/current`), { maxRetry: 3 }), + ) return data }, async getAccountNonce(address) { const { data } = await userFriendlyError( - retry(() => axios.get(`${baseURL}/addresses/${address}/nonce`)), + retry(() => axios.get(`${baseURL}/addresses/${address}/nonce`), { maxRetry: 3 }), ) return data[0].nonce }, async broadcastTransaction(tx) { - const { data } = await userFriendlyError( - retry(() => axios.post(`${baseURL}/transactions/send`, { tx })), - ) + const { data } = await userFriendlyError(axios.post(`${baseURL}/transactions/send`, { tx })) return data.result }, async getAccountBalance(address) { const { data } = await userFriendlyError( - retry(() => axios.get(`${baseURL}/addresses/${address}/balance`)), + retry(() => axios.get(`${baseURL}/addresses/${address}/balance`), { maxRetry: 3 }), ) return data[0].balance }, diff --git a/src/bridge/EthereumJSBridge.js b/src/bridge/EthereumJSBridge.js index 89549f63..634b73ab 100644 --- a/src/bridge/EthereumJSBridge.js +++ b/src/bridge/EthereumJSBridge.js @@ -1,6 +1,7 @@ // @flow import React from 'react' -import EthereumKind from 'components/FeesField/EthereumKind' +import FeesField from 'components/FeesField/EthereumKind' +import AdvancedOptions from 'components/AdvancedOptions/EthereumKind' import throttle from 'lodash/throttle' import flatMap from 'lodash/flatMap' import uniqBy from 'lodash/uniqBy' @@ -14,10 +15,15 @@ import type { EditProps, WalletBridge } from './types' // TODO in future it would be neat to support eip55 -type Transaction = * +type Transaction = { + amount: number, + recipient: string, + gasPrice: number, + gasLimit: number, +} const EditFees = ({ account, onChange, value }: EditProps) => ( - { onChange({ ...value, gasPrice }) }} @@ -26,6 +32,15 @@ const EditFees = ({ account, onChange, value }: EditProps) => ( /> ) +const EditAdvancedOptions = ({ onChange, value }: EditProps) => ( + { + onChange({ ...value, gasLimit }) + }} + /> +) + // in case of a SELF send, 2 ops are returned. const txToOps = (account: Account) => (tx: Tx): Operation[] => { const freshAddress = account.freshAddress.toLowerCase() @@ -174,7 +189,6 @@ const EthereumBridge: WalletBridge = { } txs.reverse() account.operations = mergeOps([], flatMap(txs, txToOps(account))) - console.log(account) return { account } } @@ -270,6 +284,7 @@ const EthereumBridge: WalletBridge = { amount: 0, recipient: '', gasPrice: 0, + gasLimit: 0x5208, }), editTransactionAmount: (account, t, amount) => ({ @@ -291,10 +306,12 @@ const EthereumBridge: WalletBridge = { // $FlowFixMe EditFees, - // FIXME gasPrice calc is wrong... need to multiply with gasLimit I guess ? - canBeSpent: (a, t) => Promise.resolve(t.amount + t.gasPrice <= a.balance), - getTotalSpent: (a, t) => Promise.resolve(t.amount + t.gasPrice), - getMaxAmount: (a, t) => Promise.resolve(a.balance - t.gasPrice), + // $FlowFixMe + EditAdvancedOptions, + + canBeSpent: (a, t) => Promise.resolve(t.amount <= a.balance), + getTotalSpent: (a, t) => Promise.resolve(t.amount + t.gasPrice * t.gasLimit), + getMaxAmount: (a, t) => Promise.resolve(a.balance - t.gasPrice * t.gasLimit), signAndBroadcast: async (a, t, deviceId) => { const api = apiForCurrency(a.currency) diff --git a/src/components/AdvancedOptions/EthereumKind.js b/src/components/AdvancedOptions/EthereumKind.js new file mode 100644 index 00000000..fe2faf83 --- /dev/null +++ b/src/components/AdvancedOptions/EthereumKind.js @@ -0,0 +1,36 @@ +// @flow +import React from 'react' +import { translate } from 'react-i18next' + +import Box from 'components/base/Box' +import Input from 'components/base/Input' +import Label from 'components/base/Label' +import Spoiler from 'components/base/Spoiler' + +type Props = { + gasLimit: number, + onChangeGasLimit: (?number) => void, + t: *, +} + +export default translate()(({ gasLimit, onChangeGasLimit, t }: Props) => ( + + + + + + + { + const gasLimit = parseInt(str, 10) + if (!isNaN(gasLimit) && isFinite(gasLimit)) onChangeGasLimit(gasLimit) + else onChangeGasLimit(0x5208) + }} + /> + + + +)) diff --git a/src/components/FeesField/EthereumKind.js b/src/components/FeesField/EthereumKind.js index 0ac63bbc..82313ad2 100644 --- a/src/components/FeesField/EthereumKind.js +++ b/src/components/FeesField/EthereumKind.js @@ -34,7 +34,7 @@ class FeesField extends Component { return ( 1 ? units[1] : units[0]} units={units} containerProps={{ grow: true }} value={gasPrice} diff --git a/src/components/modals/Send/SendModalBody.js b/src/components/modals/Send/SendModalBody.js index 00f64486..567a207f 100644 --- a/src/components/modals/Send/SendModalBody.js +++ b/src/components/modals/Send/SendModalBody.js @@ -127,6 +127,7 @@ class SendModalBody extends PureComponent> { this.setState({ appStatus: null, deviceSelected: null, + error: null, stepIndex: step.prevStep, }) } diff --git a/src/helpers/signTransactionForCurrency/ethereum.js b/src/helpers/signTransactionForCurrency/ethereum.js index 3f0b432f..9ae753bb 100644 --- a/src/helpers/signTransactionForCurrency/ethereum.js +++ b/src/helpers/signTransactionForCurrency/ethereum.js @@ -27,6 +27,7 @@ export default async ( nonce: string, recipient: string, gasPrice: number, + gasLimit: number, amount: number, }, ) => { @@ -34,11 +35,10 @@ export default async ( const chainId = getNetworkId(currencyId) if (!chainId) throw new Error(`chainId not found for currency=${currencyId}`) - const gasLimit = '0x5208' // cost of a simple send const tx = new EthereumTx({ nonce: t.nonce, gasPrice: `0x${t.gasPrice.toString(16)}`, - gasLimit, + gasLimit: `0x${t.gasLimit.toString(16)}`, to: t.recipient, value: `0x${t.amount.toString(16)}`, chainId, diff --git a/static/i18n/en/send.yml b/static/i18n/en/send.yml index dd9047e8..3a8d25f9 100644 --- a/static/i18n/en/send.yml +++ b/static/i18n/en/send.yml @@ -12,6 +12,7 @@ steps: useRBF: Use the RBF transaction message: Leave a message (140) rippleTag: Tag + ethereumGasLimit: Gas limit connectDevice: title: Connect device verification: diff --git a/yarn.lock b/yarn.lock index 799f056e..39061848 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1495,9 +1495,9 @@ npm "^5.7.1" prebuild-install "^2.2.2" -"@ledgerhq/live-common@2.22.0": - version "2.22.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-2.22.0.tgz#f958ee28cc09af40a6bed484e73204f01b54d709" +"@ledgerhq/live-common@2.23.0": + version "2.23.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-2.23.0.tgz#c039bbb444ceb909fa9c7f17645c39d9c3ce125e" dependencies: axios "^0.18.0" invariant "^2.2.2"