From 343c90b6728a9717e2894ba59058cc2c495304e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Mon, 4 Jun 2018 16:53:34 +0200 Subject: [PATCH] Make shitcoin integration great again --- package.json | 2 +- src/api/Ethereum.js | 4 +- src/api/Fees.js | 5 +- src/api/Ledger.js | 15 +----- src/bridge/index.js | 17 ++++--- src/components/modals/OperationDetails.js | 4 +- .../modals/Send/ConfirmationFooter.js | 17 ++++++- src/components/modals/Send/SendModalBody.js | 1 + src/helpers/SettingsDefaults.js | 49 ++++--------------- src/helpers/explorers.js | 34 ------------- src/helpers/getAddressForCurrency/index.js | 35 ++++--------- yarn.lock | 6 +-- 12 files changed, 60 insertions(+), 129 deletions(-) delete mode 100644 src/helpers/explorers.js diff --git a/package.json b/package.json index e12a1d47..0fb91a36 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.4", - "@ledgerhq/live-common": "^2.25.0", + "@ledgerhq/live-common": "2.26.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 a182b681..5abb3139 100644 --- a/src/api/Ethereum.js +++ b/src/api/Ethereum.js @@ -42,7 +42,9 @@ export type API = { export const apiForCurrency = (currency: CryptoCurrency): API => { const baseURL = blockchainBaseURL(currency) - + if (!baseURL) { + throw new Error(`ledger API not available for currency ${currency.id}`) + } return { async getTransactions(address, blockHash) { const { data } = await userFriendlyError( diff --git a/src/api/Fees.js b/src/api/Fees.js index 1ce1b83b..6f933309 100644 --- a/src/api/Fees.js +++ b/src/api/Fees.js @@ -1,4 +1,5 @@ // @flow +import invariant from 'invariant' import axios from 'axios' import type { Currency } from '@ledgerhq/live-common/lib/types' import { blockchainBaseURL, userFriendlyError } from './Ledger' @@ -8,7 +9,9 @@ export type Fees = { } export const getEstimatedFees = async (currency: Currency): Promise => { - const { data, status } = await userFriendlyError(axios.get(`${blockchainBaseURL(currency)}/fees`)) + const baseURL = blockchainBaseURL(currency) + invariant(baseURL, `Fees for ${currency.id} are not supported`) + const { data, status } = await userFriendlyError(axios.get(`${baseURL}/fees`)) if (data) { return data } diff --git a/src/api/Ledger.js b/src/api/Ledger.js index 76c66191..bbf8eaed 100644 --- a/src/api/Ledger.js +++ b/src/api/Ledger.js @@ -3,17 +3,6 @@ import type { Currency } from '@ledgerhq/live-common/lib/types' const BASE_URL = process.env.LEDGER_REST_API_BASE || 'https://api.ledgerwallet.com/' -const mapping = { - bitcoin_cash: 'abc', - ethereum_classic: 'ethc', - ethereum_testnet: 'eth_testnet', -} - -export const currencyToFeeTicker = (currency: Currency) => { - const tickerLowerCase = currency.ticker.toLowerCase() - return mapping[currency.id] || tickerLowerCase -} - export const userFriendlyError = (p: Promise): Promise => p.catch(error => { if (error.response) { @@ -48,5 +37,5 @@ export const userFriendlyError = (p: Promise): Promise => throw error }) -export const blockchainBaseURL = (currency: Currency) => - `${BASE_URL}blockchain/v2/${currencyToFeeTicker(currency)}` +export const blockchainBaseURL = ({ ledgerExplorerId }: Currency): ?string => + ledgerExplorerId ? `${BASE_URL}blockchain/v2/${ledgerExplorerId}` : null diff --git a/src/bridge/index.js b/src/bridge/index.js index 3ea7fe37..4b947578 100644 --- a/src/bridge/index.js +++ b/src/bridge/index.js @@ -1,16 +1,19 @@ // @flow import type { Currency } from '@ledgerhq/live-common/lib/types' +import invariant from 'invariant' import { WalletBridge } from './types' import LibcoreBridge from './LibcoreBridge' import EthereumJSBridge from './EthereumJSBridge' import RippleJSBridge from './RippleJSBridge' +const perFamily = { + bitcoin: LibcoreBridge, + ripple: RippleJSBridge, + ethereum: EthereumJSBridge, +} + export const getBridgeForCurrency = (currency: Currency): WalletBridge => { - if (currency.id.indexOf('ethereum') === 0) { - return EthereumJSBridge // polyfill js - } - if (currency.id === 'ripple') { - return RippleJSBridge // polyfill js - } - return LibcoreBridge // libcore for the rest + const bridge = perFamily[currency.family] + invariant(bridge, `${currency.id} currency is not supported`) + return bridge } diff --git a/src/components/modals/OperationDetails.js b/src/components/modals/OperationDetails.js index db73a489..2c6d4cc9 100644 --- a/src/components/modals/OperationDetails.js +++ b/src/components/modals/OperationDetails.js @@ -8,7 +8,7 @@ import { translate } from 'react-i18next' import styled from 'styled-components' import moment from 'moment' import { getOperationAmountNumber } from '@ledgerhq/live-common/lib/helpers/operation' -import { getTxURL } from 'helpers/explorers' +import { getAccountOperationExplorer } from '@ledgerhq/live-common/lib/explorers' import type { Account, Operation } from '@ledgerhq/live-common/lib/types' import type { T, CurrencySettings } from 'types/common' @@ -78,7 +78,7 @@ const OperationDetails = connect(mapStateToProps)((props: Props) => { const confirmations = operation.blockHeight ? account.blockHeight - operation.blockHeight : 0 const isConfirmed = confirmations >= currencySettings.confirmationsNb - const url = getTxURL(account, operation) + const url = getAccountOperationExplorer(account, operation) const uniqSenders = uniq(senders) return ( diff --git a/src/components/modals/Send/ConfirmationFooter.js b/src/components/modals/Send/ConfirmationFooter.js index 085bb6e6..99abd760 100644 --- a/src/components/modals/Send/ConfirmationFooter.js +++ b/src/components/modals/Send/ConfirmationFooter.js @@ -1,17 +1,21 @@ // @flow import React from 'react' -import type { Operation } from '@ledgerhq/live-common/lib/types' +import type { Operation, Account } from '@ledgerhq/live-common/lib/types' +import { shell } from 'electron' import Button from 'components/base/Button' import { ModalFooter } from 'components/base/Modal' +import { getAccountOperationExplorer } from '@ledgerhq/live-common/lib/explorers' import type { T } from 'types/common' export default ({ t, + account, optimisticOperation, onClose, onGoToFirstStep, }: { t: T, + account: ?Account, optimisticOperation: ?Operation, onClose: () => void, onGoToFirstStep: () => void, @@ -20,7 +24,16 @@ export default ({ {optimisticOperation ? ( // TODO: actually go to operations details - ) : ( diff --git a/src/components/modals/Send/SendModalBody.js b/src/components/modals/Send/SendModalBody.js index 7620f454..c6343d0a 100644 --- a/src/components/modals/Send/SendModalBody.js +++ b/src/components/modals/Send/SendModalBody.js @@ -242,6 +242,7 @@ class SendModalBody extends PureComponent> { {stepIndex === 3 ? ( = { - bitcoin_cash: 2, - bitcoin_gold: 2, - bitcoin_testnet: 2, - bitcoin: 2, - dash: 12, - digibyte: 30, - dogecoin: 30, - ethereum_classic: 120, - ethereum_testnet: 120, - ethereum: 120, - hcash: 12, // FIXME can't grab the block time info anywhere... - komodo: 30, - litecoin: 6, - peercoin: 4, - pivx: 12, // FIXME can't grab the block time info anywhere... - poswallet: 28, - qtum: 15, - ripple: 0, - stealthcoin: 12, // FIXME can't grab the block time info anywhere... - stratis: 12, // FIXME can't grab the block time info anywhere... - vertcoin: 12, - viacoin: 75, - zcash: 12, - zencash: 12, -} - -export const currencySettingsDefaults = (currency: CryptoCurrency): ConfirmationDefaults => { - const confirmationsNbDef = confirmationsNbPerCoin[currency.id] +export const currencySettingsDefaults = ({ + blockAvgTime, +}: CryptoCurrency): ConfirmationDefaults => { + let confirmationsNb + if (blockAvgTime) { + const def = Math.ceil(30 * 60 / blockAvgTime) // 30 min approx validation + confirmationsNb = { min: 1, def, max: 2 * def } + } return { - confirmationsNb: confirmationsNbDef - ? { - min: 1, - def: confirmationsNbDef, - max: 2 * confirmationsNbDef, - } - : null, + confirmationsNb, } } diff --git a/src/helpers/explorers.js b/src/helpers/explorers.js deleted file mode 100644 index 2ae03aa3..00000000 --- a/src/helpers/explorers.js +++ /dev/null @@ -1,34 +0,0 @@ -// @flow -import type { Account, Operation, CryptoCurrencyConfig } from '@ledgerhq/live-common/lib/types' - -type Explorer = Operation => ?string - -const txExplorers: CryptoCurrencyConfig = { - bitcoin_cash: op => `https://bitcoincash.blockexplorer.com/tx/${op.hash}`, - bitcoin_gold: op => `https://btgexplorer.com/tx/${op.hash}`, - bitcoin_testnet: op => `https://testnet.blockchain.info/tx/${op.hash}`, - bitcoin: op => `https://blockchain.info/tx/${op.hash}`, - dash: op => `https://explorer.dash.org/tx/${op.hash}`, - digibyte: op => `https://digiexplorer.info/tx/${op.hash}`, - dogecoin: op => `https://dogechain.info/tx/${op.hash}`, - ethereum_classic: op => `https://gastracker.io/tx/${op.hash}`, - ethereum_testnet: op => `https://ropsten.etherscan.io/tx/${op.hash}`, - ethereum: op => `https://etherscan.io/tx/${op.hash}`, - hcash: op => `http://explorer.h.cash/tx/${op.hash}`, - komodo: op => `https://kmd.explorer.supernet.org/tx/${op.hash}`, - litecoin: op => `http://explorer.litecoin.net/tx/${op.hash}`, - peercoin: op => `https://explorer.peercoin.net/tx/${op.hash}`, - pivx: () => null, // FIXME can't find a reliable/official explorer - poswallet: () => null, // FIXME can't find a reliable/official explorer - qtum: op => `https://explorer.qtum.org/tx/${op.hash}`, - ripple: op => `https://bithomp.com/explorer/${op.hash}`, - stealthcoin: () => null, // FIXME can't find a reliable/official explorer - stratis: () => null, // FIXME can't find a reliable/official explorer - vertcoin: op => `http://explorer.vertcoin.info/tx/${op.hash}`, - viacoin: op => `https://explorer.viacoin.org/tx/${op.hash}`, - zcash: op => `https://explorer.zcha.in/transactions/${op.hash}`, - zencash: op => `https://explorer.zensystem.io/tx/${op.hash}`, -} - -export const getTxURL = (account: Account, operation: Operation): ?string => - txExplorers[account.currency.id](operation) diff --git a/src/helpers/getAddressForCurrency/index.js b/src/helpers/getAddressForCurrency/index.js index 0abad82d..09e46319 100644 --- a/src/helpers/getAddressForCurrency/index.js +++ b/src/helpers/getAddressForCurrency/index.js @@ -1,8 +1,8 @@ // @flow -import type { CryptoCurrencyConfig } from '@ledgerhq/live-common/lib/types' +import invariant from 'invariant' import type Transport from '@ledgerhq/hw-transport' -import btc from './btc' +import bitcoin from './btc' import ethereum from './ethereum' import ripple from './ripple' @@ -18,33 +18,16 @@ type Resolver = ( type Module = (currencyId: string) => Resolver -const all: CryptoCurrencyConfig = { - bitcoin_cash: btc, - bitcoin_gold: btc, - bitcoin_testnet: btc, - bitcoin: btc, - dash: btc, - digibyte: btc, - dogecoin: btc, - ethereum_classic: ethereum, - ethereum_testnet: ethereum, +const perFamily = { + bitcoin, ethereum, - hcash: btc, - komodo: btc, - litecoin: btc, - peercoin: btc, - pivx: btc, - poswallet: btc, - qtum: btc, ripple, - stealthcoin: btc, - stratis: btc, - vertcoin: btc, - viacoin: btc, - zcash: btc, - zencash: btc, } -const getAddressForCurrency: Module = (currencyId: string) => all[currencyId] +const getAddressForCurrency: Module = (currencyId: string) => { + const getAddress = perFamily[currencyId] + invariant(getAddress, `getAddress not implemented for ${currencyId}`) + return getAddress +} export default getAddressForCurrency diff --git a/yarn.lock b/yarn.lock index d198ae78..f4b7978a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1495,9 +1495,9 @@ npm "^5.7.1" prebuild-install "^2.2.2" -"@ledgerhq/live-common@^2.25.0": - version "2.25.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-2.25.0.tgz#00cca102598c9b604922fc4047d2c009d316aede" +"@ledgerhq/live-common@2.26.0": + version "2.26.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-2.26.0.tgz#2dde8da97ef28b9326f1b060e8db9033ad788efe" dependencies: axios "^0.18.0" invariant "^2.2.2"