From ae2fe0401c0e13d4f00fc74e84b8f54cd36368d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Wed, 18 Jul 2018 10:36:42 +0200 Subject: [PATCH] Migrate the app to BigNumber.js --- package.json | 3 +- src/api/Ethereum.js | 6 ++- src/api/Ripple.js | 5 ++- src/bridge/EthereumJSBridge.js | 44 ++++++++++++------- src/bridge/LibcoreBridge.js | 39 ++++++++++------ src/bridge/RippleJSBridge.js | 36 ++++++++------- src/bridge/UnsupportedBridge.js | 7 +-- src/bridge/makeMockBridge.js | 2 +- src/bridge/types.js | 9 ++-- src/commands/libcoreGetFees.js | 21 +++++---- src/commands/libcoreSignAndBroadcast.js | 24 +++++----- .../AccountBalanceSummaryHeader.js | 7 +-- .../AccountPage/AccountHeaderActions.js | 2 +- src/components/AccountPage/index.js | 2 +- .../AdvancedOptions/EthereumKind.js | 11 ++--- src/components/BalanceSummary/BalanceInfos.js | 11 ++--- src/components/BalanceSummary/index.js | 18 ++++---- src/components/CalculateBalance.js | 17 +++---- src/components/CounterValue/index.js | 5 ++- src/components/DashboardPage/AccountCard.js | 2 +- src/components/DeltaChange.js | 13 ++++-- src/components/FeesField/BitcoinKind.js | 21 ++++----- src/components/FeesField/EthereumKind.js | 9 ++-- src/components/FeesField/RippleKind.js | 7 +-- src/components/OperationsList/AmountCell.js | 2 +- src/components/RecipientAddress/index.js | 3 +- .../base/Chart/handleMouseEvents.js | 2 +- src/components/base/Chart/index.js | 2 +- src/components/base/Chart/refreshDraw.js | 4 +- src/components/base/Chart/stories.js | 3 +- src/components/base/Chart/types.js | 8 ++-- src/components/base/FlipTicker/stories.js | 3 +- src/components/base/FormattedVal/index.js | 16 ++++--- src/components/base/InputCurrency/index.js | 34 +++++++------- src/components/modals/OperationDetails.js | 2 +- .../modals/Send/steps/01-step-amount.js | 7 +-- src/helpers/libcore.js | 11 +++++ .../signTransactionForCurrency/ethereum.js | 13 +++--- yarn.lock | 11 +++-- 39 files changed, 260 insertions(+), 182 deletions(-) diff --git a/package.json b/package.json index d2e5b857..6d3cc888 100644 --- a/package.json +++ b/package.json @@ -37,12 +37,13 @@ "@ledgerhq/hw-transport": "^4.13.0", "@ledgerhq/hw-transport-node-hid": "^4.13.0", "@ledgerhq/ledger-core": "2.0.0-rc.4", - "@ledgerhq/live-common": "^2.35.0", + "@ledgerhq/live-common": "3.0.0-beta.2", "animated": "^0.2.2", "async": "^2.6.1", "axios": "^0.18.0", "babel-runtime": "^6.26.0", "bcryptjs": "^2.4.3", + "bignumber.js": "^7.2.1", "bitcoinjs-lib": "^3.3.2", "bs58": "^4.0.1", "color": "^3.0.0", diff --git a/src/api/Ethereum.js b/src/api/Ethereum.js index c6a6efcb..68f72f90 100644 --- a/src/api/Ethereum.js +++ b/src/api/Ethereum.js @@ -1,5 +1,6 @@ // @flow import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types' +import { BigNumber } from 'bignumber.js' import { createCustomErrorClass } from 'helpers/errors' import network from './network' import { blockchainBaseURL } from './Ledger' @@ -39,7 +40,7 @@ export type API = { getCurrentBlock: () => Promise, getAccountNonce: (address: string) => Promise, broadcastTransaction: (signedTransaction: string) => Promise, - getAccountBalance: (address: string) => Promise, + getAccountBalance: (address: string) => Promise, } export const apiForCurrency = (currency: CryptoCurrency): API => { @@ -85,7 +86,8 @@ export const apiForCurrency = (currency: CryptoCurrency): API => { method: 'GET', url: `${baseURL}/addresses/${address}/balance`, }) - return data[0].balance + // FIXME precision lost here. nothing we can do easily + return BigNumber(data[0].balance) }, } } diff --git a/src/api/Ripple.js b/src/api/Ripple.js index 8f0d5fd4..ada06bb4 100644 --- a/src/api/Ripple.js +++ b/src/api/Ripple.js @@ -1,5 +1,6 @@ // @flow import logger from 'logger' +import { BigNumber } from 'bignumber.js' import { RippleAPI } from 'ripple-lib' import { parseCurrencyUnit, @@ -31,12 +32,12 @@ export const parseAPICurrencyObject = ({ }) => { if (currency !== 'XRP') { logger.warn(`RippleJS: attempt to parse unknown currency ${currency}`) - return 0 + return BigNumber(0) } return parseAPIValue(value) } -export const formatAPICurrencyXRP = (amount: number) => { +export const formatAPICurrencyXRP = (amount: BigNumber) => { const value = formatCurrencyUnit(rippleUnit, amount, { showAllDigits: true, disableRounding: true, diff --git a/src/bridge/EthereumJSBridge.js b/src/bridge/EthereumJSBridge.js index 48972922..496a15ba 100644 --- a/src/bridge/EthereumJSBridge.js +++ b/src/bridge/EthereumJSBridge.js @@ -1,5 +1,6 @@ // @flow import { Observable } from 'rxjs' +import { BigNumber } from 'bignumber.js' import React from 'react' import FeesField from 'components/FeesField/EthereumKind' import AdvancedOptions from 'components/AdvancedOptions/EthereumKind' @@ -21,12 +22,19 @@ const NotEnoughBalance = createCustomErrorClass('NotEnoughBalance') // TODO in future it would be neat to support eip55 type Transaction = { - amount: number, recipient: string, - gasPrice: number, - gasLimit: number, + amount: BigNumber, + gasPrice: BigNumber, + gasLimit: BigNumber, } +const serializeTransaction = t => ({ + recipient: t.recipient, + amount: `0x${BigNumber(t.amount).toString(16)}`, + gasPrice: `0x${BigNumber(t.gasPrice).toString(16)}`, + gasLimit: `0x${BigNumber(t.gasLimit).toString(16)}`, +}) + const EditFees = ({ account, onChange, value }: EditProps) => ( { @@ -60,8 +68,8 @@ const txToOps = (account: Account) => (tx: Tx): Operation[] => { id: `${account.id}-${tx.hash}-OUT`, hash: tx.hash, type: 'OUT', - value: tx.value, - fee, + value: BigNumber(tx.value), // FIXME problem with our api, precision lost here... + fee: BigNumber(fee), // FIXME problem with our api, precision lost here... blockHeight: tx.block && tx.block.height, blockHash: tx.block && tx.block.hash, accountId: account.id, @@ -75,8 +83,8 @@ const txToOps = (account: Account) => (tx: Tx): Operation[] => { id: `${account.id}-${tx.hash}-IN`, hash: tx.hash, type: 'IN', - value: tx.value, - fee, + value: BigNumber(tx.value), // FIXME problem with our api, precision lost here... + fee: BigNumber(fee), // FIXME problem with our api, precision lost here... blockHeight: tx.block && tx.block.height, blockHash: tx.block && tx.block.hash, accountId: account.id, @@ -115,7 +123,7 @@ const signAndBroadcast = async ({ currencyId: a.currency.id, devicePath: deviceId, path: a.freshAddressPath, - transaction: { ...t, nonce }, + transaction: { ...serializeTransaction(t), nonce }, }) .toPromise() @@ -129,7 +137,7 @@ const signAndBroadcast = async ({ hash, type: 'OUT', value: t.amount, - fee: t.gasPrice * t.gasLimit, + fee: t.gasPrice.times(t.gasLimit), blockHeight: null, blockHash: null, accountId: a.id, @@ -351,10 +359,10 @@ const EthereumBridge: WalletBridge = { isRecipientValid: (currency, recipient) => Promise.resolve(isRecipientValid(currency, recipient)), createTransaction: () => ({ - amount: 0, + amount: BigNumber(0), recipient: '', - gasPrice: 0, - gasLimit: 0x5208, + gasPrice: BigNumber(0), + gasLimit: BigNumber(0x5208), }), editTransactionAmount: (account, t, amount) => ({ @@ -371,16 +379,20 @@ const EthereumBridge: WalletBridge = { getTransactionRecipient: (a, t) => t.recipient, - isValidTransaction: (a, t) => (t.amount > 0 && t.recipient && true) || false, + isValidTransaction: (a, t) => (!t.amount.isZero() && t.recipient && true) || false, EditFees, EditAdvancedOptions, checkCanBeSpent: (a, t) => - t.amount <= a.balance ? Promise.resolve() : Promise.reject(new NotEnoughBalance()), - getTotalSpent: (a, t) => Promise.resolve(t.amount + t.gasPrice * t.gasLimit), - getMaxAmount: (a, t) => Promise.resolve(a.balance - t.gasPrice * t.gasLimit), + t.amount.isLessThanOrEqualTo(a.balance) + ? Promise.resolve() + : Promise.reject(new NotEnoughBalance()), + + getTotalSpent: (a, t) => Promise.resolve(t.amount.plus(t.gasPrice.times(t.gasLimit))), + + getMaxAmount: (a, t) => Promise.resolve(a.balance.minus(t.gasPrice.times(t.gasLimit))), signAndBroadcast: (a, t, deviceId) => Observable.create(o => { diff --git a/src/bridge/LibcoreBridge.js b/src/bridge/LibcoreBridge.js index 6ea7ff24..c725a98d 100644 --- a/src/bridge/LibcoreBridge.js +++ b/src/bridge/LibcoreBridge.js @@ -1,5 +1,6 @@ // @flow import React from 'react' +import { BigNumber } from 'bignumber.js' import { Observable } from 'rxjs' import LRU from 'lru-cache' import { map } from 'rxjs/operators' @@ -20,11 +21,17 @@ const NotEnoughBalance = createCustomErrorClass('NotEnoughBalance') const notImplemented = new Error('LibcoreBridge: not implemented') type Transaction = { - amount: number, - feePerByte: number, + amount: BigNumber, + feePerByte: BigNumber, recipient: string, } +const serializeTransaction = t => ({ + recipient: t.recipient, + amount: t.amount.toString(), + feePerByte: t.feePerByte.toString(), +}) + const decodeOperation = (encodedAccount, rawOp) => decodeAccount({ ...encodedAccount, operations: [rawOp] }).operations[0] @@ -70,7 +77,7 @@ const isRecipientValid = (currency, recipient) => { const feesLRU = LRU({ max: 100 }) const getFeesKey = (a, t) => - `${a.id}_${a.blockHeight || 0}_${t.amount}_${t.recipient}_${t.feePerByte}` + `${a.id}_${a.blockHeight || 0}_${t.amount.toString()}_${t.recipient}_${t.feePerByte.toString()}` const getFees = async (a, transaction) => { const isValid = await isRecipientValid(a.currency, transaction.recipient) @@ -79,9 +86,13 @@ const getFees = async (a, transaction) => { let promise = feesLRU.get(key) if (promise) return promise promise = libcoreGetFees - .send({ accountId: a.id, accountIndex: a.index, transaction }) + .send({ + accountId: a.id, + accountIndex: a.index, + transaction: serializeTransaction(transaction), + }) .toPromise() - .then(r => r.totalFees) + .then(r => BigNumber(r.totalFees)) feesLRU.set(key, promise) return promise } @@ -168,9 +179,9 @@ const LibcoreBridge: WalletBridge = { isRecipientValid, createTransaction: () => ({ - amount: 0, + amount: BigNumber(0), recipient: '', - feePerByte: 0, + feePerByte: BigNumber(0), isRBF: false, }), @@ -192,28 +203,28 @@ const LibcoreBridge: WalletBridge = { // EditAdvancedOptions, - isValidTransaction: (a, t) => (t.amount > 0 && t.recipient && true) || false, + isValidTransaction: (a, t) => (!t.amount.isZero() && t.recipient && true) || false, checkCanBeSpent, getTotalSpent: (a, t) => !t.amount - ? Promise.resolve(0) + ? Promise.resolve(BigNumber(0)) : getFees(a, t) - .then(totalFees => t.amount + (totalFees || 0)) - .catch(() => 0), + .then(totalFees => t.amount.plus(totalFees || 0)) + .catch(() => BigNumber(0)), getMaxAmount: (a, t) => getFees(a, t) - .catch(() => 0) - .then(totalFees => a.balance - (totalFees || 0)), + .catch(() => BigNumber(0)) + .then(totalFees => a.balance.minus(totalFees || 0)), signAndBroadcast: (account, transaction, deviceId) => { const encodedAccount = encodeAccount(account) // FIXME no need to send the whole account over the threads return libcoreSignAndBroadcast .send({ account: encodedAccount, - transaction, + transaction: serializeTransaction(transaction), deviceId, }) .pipe( diff --git a/src/bridge/RippleJSBridge.js b/src/bridge/RippleJSBridge.js index 53c5f181..919f0740 100644 --- a/src/bridge/RippleJSBridge.js +++ b/src/bridge/RippleJSBridge.js @@ -1,5 +1,6 @@ // @flow import invariant from 'invariant' +import { BigNumber } from 'bignumber.js' import { Observable } from 'rxjs' import React from 'react' import bs58check from 'ripple-bs58check' @@ -25,9 +26,9 @@ import type { WalletBridge, EditProps } from './types' const NotEnoughBalance = createCustomErrorClass('NotEnoughBalance') type Transaction = { - amount: number, + amount: BigNumber, recipient: string, - fee: number, + fee: BigNumber, tag: ?number, } @@ -196,11 +197,11 @@ const txToOperation = (account: Account) => ({ specification: { source, destination }, }: Tx): ?Operation => { const type = source.address === account.freshAddress ? 'OUT' : 'IN' - let value = deliveredAmount ? parseAPICurrencyObject(deliveredAmount) : 0 + let value = deliveredAmount ? parseAPICurrencyObject(deliveredAmount) : BigNumber(0) const feeValue = parseAPIValue(fee) if (type === 'OUT') { if (!isNaN(feeValue)) { - value += feeValue + value = value.plus(feeValue) } } @@ -292,7 +293,7 @@ const RippleJSBridge: WalletBridge = { name: getNewAccountPlaceholderName(currency, index), freshAddress, freshAddressPath, - balance: 0, + balance: BigNumber(0), blockHeight: maxLedgerVersion, index, currency, @@ -309,8 +310,8 @@ const RippleJSBridge: WalletBridge = { if (finished) return const balance = parseAPIValue(info.xrpBalance) invariant( - !isNaN(balance) && isFinite(balance), - `Ripple: invalid balance=${balance} for address ${address}`, + !balance.isNaN() && balance.isFinite(), + `Ripple: invalid balance=${balance.toString()} for address ${address}`, ) const transactions = await api.getTransactions(address, { @@ -393,8 +394,8 @@ const RippleJSBridge: WalletBridge = { const balance = parseAPIValue(info.xrpBalance) invariant( - !isNaN(balance) && isFinite(balance), - `Ripple: invalid balance=${balance} for address ${freshAddress}`, + !balance.isNaN() && balance.isFinite(), + `Ripple: invalid balance=${balance.toString()} for address ${freshAddress}`, ) o.next(a => ({ ...a, balance })) @@ -448,9 +449,9 @@ const RippleJSBridge: WalletBridge = { isRecipientValid: (currency, recipient) => Promise.resolve(isRecipientValid(currency, recipient)), createTransaction: () => ({ - amount: 0, + amount: BigNumber(0), recipient: '', - fee: 0, + fee: BigNumber(0), tag: undefined, }), @@ -472,19 +473,24 @@ const RippleJSBridge: WalletBridge = { getTransactionRecipient: (a, t) => t.recipient, - isValidTransaction: (a, t) => (t.amount > 0 && t.recipient && true) || false, + isValidTransaction: (a, t) => (!t.amount.isZero() && t.recipient && true) || false, checkCanBeSpent: async (a, t) => { const r = await getServerInfo(a.endpointConfig) - if (t.amount + t.fee + parseAPIValue(r.validatedLedger.reserveBaseXRP) <= a.balance) { + if ( + t.amount + .plus(t.fee) + .plus(parseAPIValue(r.validatedLedger.reserveBaseXRP)) + .isLessThanOrEqualTo(a.balance) + ) { return } throw new NotEnoughBalance() }, - getTotalSpent: (a, t) => Promise.resolve(t.amount + t.fee), + getTotalSpent: (a, t) => Promise.resolve(t.amount.plus(t.fee)), - getMaxAmount: (a, t) => Promise.resolve(a.balance - t.fee), + getMaxAmount: (a, t) => Promise.resolve(a.balance.minus(t.fee)), signAndBroadcast: (a, t, deviceId) => Observable.create(o => { diff --git a/src/bridge/UnsupportedBridge.js b/src/bridge/UnsupportedBridge.js index 526624eb..37b6edae 100644 --- a/src/bridge/UnsupportedBridge.js +++ b/src/bridge/UnsupportedBridge.js @@ -1,5 +1,6 @@ // @flow import { Observable } from 'rxjs' +import { BigNumber } from 'bignumber.js' import type { WalletBridge } from './types' const genericError = new Error('UnsupportedBridge') @@ -23,7 +24,7 @@ const UnsupportedBridge: WalletBridge<*> = { editTransactionAmount: () => null, - getTransactionAmount: () => 0, + getTransactionAmount: () => BigNumber(0), isValidTransaction: () => false, @@ -33,9 +34,9 @@ const UnsupportedBridge: WalletBridge<*> = { checkCanBeSpent: () => Promise.resolve(), - getTotalSpent: () => Promise.resolve(0), + getTotalSpent: () => Promise.resolve(BigNumber(0)), - getMaxAmount: () => Promise.resolve(0), + getMaxAmount: () => Promise.resolve(BigNumber(0)), signAndBroadcast: () => Observable.create(o => { diff --git a/src/bridge/makeMockBridge.js b/src/bridge/makeMockBridge.js index e84a6beb..6ee9eb06 100644 --- a/src/bridge/makeMockBridge.js +++ b/src/bridge/makeMockBridge.js @@ -58,7 +58,7 @@ function makeMockBridge(opts?: Opts): WalletBridge<*> { account = { ...account } account.blockHeight++ for (const op of ops) { - account.balance += getOperationAmountNumber(op) + account.balance = account.balance.plus(getOperationAmountNumber(op)) } return account }) diff --git a/src/bridge/types.js b/src/bridge/types.js index 4b1a8d47..244a1251 100644 --- a/src/bridge/types.js +++ b/src/bridge/types.js @@ -1,6 +1,7 @@ // @flow import type { Observable } from 'rxjs' +import type { BigNumber } from 'bignumber.js' import type { Account, Operation, Currency } from '@ledgerhq/live-common/lib/types' // a WalletBridge is implemented on renderer side. @@ -62,9 +63,9 @@ export interface WalletBridge { createTransaction(account: Account): Transaction; - editTransactionAmount(account: Account, transaction: Transaction, amount: number): Transaction; + editTransactionAmount(account: Account, transaction: Transaction, amount: BigNumber): Transaction; - getTransactionAmount(account: Account, transaction: Transaction): number; + getTransactionAmount(account: Account, transaction: Transaction): BigNumber; editTransactionRecipient( account: Account, @@ -84,10 +85,10 @@ export interface WalletBridge { checkCanBeSpent(account: Account, transaction: Transaction): Promise; - getTotalSpent(account: Account, transaction: Transaction): Promise; + getTotalSpent(account: Account, transaction: Transaction): Promise; // NB this is not used yet but we'll use it when we have MAX - getMaxAmount(account: Account, transaction: Transaction): Promise; + getMaxAmount(account: Account, transaction: Transaction): Promise; /** * finalize the transaction by diff --git a/src/commands/libcoreGetFees.js b/src/commands/libcoreGetFees.js index fb0dc690..e6d5a005 100644 --- a/src/commands/libcoreGetFees.js +++ b/src/commands/libcoreGetFees.js @@ -1,18 +1,19 @@ // @flow import { Observable } from 'rxjs' +import { BigNumber } from 'bignumber.js' import withLibcore from 'helpers/withLibcore' import { createCommand, Command } from 'helpers/ipc' import * as accountIdHelper from 'helpers/accountId' -import { isValidAddress } from 'helpers/libcore' +import { isValidAddress, libcoreAmountToBigNumber, bigNumberToLibcoreAmount } from 'helpers/libcore' import { createCustomErrorClass } from 'helpers/errors' const InvalidAddress = createCustomErrorClass('InvalidAddress') type BitcoinLikeTransaction = { // TODO we rename this Transaction concept into transactionInput - amount: number, - feePerByte: number, + amount: string, + feePerByte: string, recipient: string, } @@ -22,7 +23,7 @@ type Input = { transaction: BitcoinLikeTransaction, } -type Result = { totalFees: number } +type Result = { totalFees: string } const cmd: Command = createCommand( 'libcoreGetFees', @@ -39,13 +40,15 @@ const cmd: Command = createCommand( if (isCancelled()) return const bitcoinLikeAccount = njsAccount.asBitcoinLikeAccount() const njsWalletCurrency = njsWallet.getCurrency() - const amount = new core.NJSAmount(njsWalletCurrency, transaction.amount).fromLong( + const amount = bigNumberToLibcoreAmount( + core, njsWalletCurrency, - transaction.amount, + BigNumber(transaction.amount), ) - const feesPerByte = new core.NJSAmount(njsWalletCurrency, transaction.feePerByte).fromLong( + const feesPerByte = bigNumberToLibcoreAmount( + core, njsWalletCurrency, - transaction.feePerByte, + BigNumber(transaction.feePerByte), ) const transactionBuilder = bitcoinLikeAccount.buildTransaction() if (!isValidAddress(core, njsWalletCurrency, transaction.recipient)) { @@ -56,7 +59,7 @@ const cmd: Command = createCommand( transactionBuilder.pickInputs(0, 0xffffff) transactionBuilder.setFeesPerByte(feesPerByte) const builded = await transactionBuilder.build() - const totalFees = builded.getFees().toLong() + const totalFees = libcoreAmountToBigNumber(builded.getFees()).toString() o.next({ totalFees }) }).then(() => o.complete(), e => o.error(e)) diff --git a/src/commands/libcoreSignAndBroadcast.js b/src/commands/libcoreSignAndBroadcast.js index 07f36f7a..7805595e 100644 --- a/src/commands/libcoreSignAndBroadcast.js +++ b/src/commands/libcoreSignAndBroadcast.js @@ -1,11 +1,13 @@ // @flow import logger from 'logger' +import { BigNumber } from 'bignumber.js' import type { AccountRaw, OperationRaw } from '@ledgerhq/live-common/lib/types' import Btc from '@ledgerhq/hw-app-btc' import { Observable } from 'rxjs' import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/helpers/currencies' import { isSegwitAccount } from 'helpers/bip32' +import { libcoreAmountToBigNumber, bigNumberToLibcoreAmount } from 'helpers/libcore' import withLibcore from 'helpers/withLibcore' import { createCommand, Command } from 'helpers/ipc' @@ -13,8 +15,8 @@ import { withDevice } from 'helpers/deviceAccess' import * as accountIdHelper from 'helpers/accountId' type BitcoinLikeTransaction = { - amount: number, - feePerByte: number, + amount: string, + feePerByte: string, recipient: string, } @@ -169,14 +171,8 @@ export async function doSignAndBroadcast({ if (isCancelled()) return const bitcoinLikeAccount = njsAccount.asBitcoinLikeAccount() const njsWalletCurrency = njsWallet.getCurrency() - const amount = new core.NJSAmount(njsWalletCurrency, transaction.amount).fromLong( - njsWalletCurrency, - transaction.amount, - ) - const fees = new core.NJSAmount(njsWalletCurrency, transaction.feePerByte).fromLong( - njsWalletCurrency, - transaction.feePerByte, - ) + const amount = bigNumberToLibcoreAmount(core, njsWalletCurrency, BigNumber(transaction.amount)) + const fees = bigNumberToLibcoreAmount(core, njsWalletCurrency, BigNumber(transaction.feePerByte)) const transactionBuilder = bitcoinLikeAccount.buildTransaction() // TODO: check if is valid address. if not, it will fail silently on invalid @@ -218,15 +214,17 @@ export async function doSignAndBroadcast({ .asBitcoinLikeAccount() .broadcastRawTransaction(Array.from(Buffer.from(signedTransaction, 'hex'))) - const fee = builded.getFees().toLong() + const fee = libcoreAmountToBigNumber(builded.getFees()) // NB we don't check isCancelled() because the broadcast is not cancellable now! onOperationBroadcasted({ id: `${account.xpub}-${txHash}-OUT`, hash: txHash, type: 'OUT', - value: transaction.amount + fee, - fee, + value: BigNumber(transaction.amount) + .plus(fee) + .toString(), + fee: fee.toString(), blockHash: null, blockHeight: null, senders: [account.freshAddress], diff --git a/src/components/AccountPage/AccountBalanceSummaryHeader.js b/src/components/AccountPage/AccountBalanceSummaryHeader.js index 33fe9cdb..0cb8c114 100644 --- a/src/components/AccountPage/AccountBalanceSummaryHeader.js +++ b/src/components/AccountPage/AccountBalanceSummaryHeader.js @@ -1,6 +1,7 @@ // @flow import React, { PureComponent } from 'react' +import type { BigNumber } from 'bignumber.js' import { createStructuredSelector } from 'reselect' import { compose } from 'redux' import { connect } from 'react-redux' @@ -25,9 +26,9 @@ import PillsDaysCount from 'components/PillsDaysCount' type OwnProps = { isAvailable: boolean, - totalBalance: number, - sinceBalance: number, - refBalance: number, + totalBalance: BigNumber, + sinceBalance: BigNumber, + refBalance: BigNumber, accountId: string, } diff --git a/src/components/AccountPage/AccountHeaderActions.js b/src/components/AccountPage/AccountHeaderActions.js index c510c9cb..e6fa1cbd 100644 --- a/src/components/AccountPage/AccountHeaderActions.js +++ b/src/components/AccountPage/AccountHeaderActions.js @@ -62,7 +62,7 @@ class AccountHeaderActions extends PureComponent { const { account, openModal, t } = this.props return ( - {account.operations.length > 0 || account.balance > 0 ? ( + {account.operations.length > 0 || !account.balance.isZero() ? (