Browse Source

Make shitcoin integration great again

master
Gaëtan Renaudeau 7 years ago
parent
commit
343c90b672
  1. 2
      package.json
  2. 4
      src/api/Ethereum.js
  3. 5
      src/api/Fees.js
  4. 15
      src/api/Ledger.js
  5. 17
      src/bridge/index.js
  6. 4
      src/components/modals/OperationDetails.js
  7. 17
      src/components/modals/Send/ConfirmationFooter.js
  8. 1
      src/components/modals/Send/SendModalBody.js
  9. 49
      src/helpers/SettingsDefaults.js
  10. 34
      src/helpers/explorers.js
  11. 35
      src/helpers/getAddressForCurrency/index.js
  12. 6
      yarn.lock

2
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",

4
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(

5
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<Fees> => {
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
}

15
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 = <A>(p: Promise<A>): Promise<A> =>
p.catch(error => {
if (error.response) {
@ -48,5 +37,5 @@ export const userFriendlyError = <A>(p: Promise<A>): Promise<A> =>
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

17
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<any> => {
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
}

4
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 (

17
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 ({
<Button onClick={onClose}>{t('common:close')}</Button>
{optimisticOperation ? (
// TODO: actually go to operations details
<Button onClick={onClose} primary>
<Button
onClick={() => {
const url = account && getAccountOperationExplorer(account, optimisticOperation)
if (url) {
shell.openExternal(url)
}
onClose()
}}
primary
>
{t('send:steps.confirmation.success.cta')}
</Button>
) : (

1
src/components/modals/Send/SendModalBody.js

@ -242,6 +242,7 @@ class SendModalBody extends PureComponent<Props, State<*>> {
{stepIndex === 3 ? (
<ConfirmationFooter
t={t}
account={account}
optimisticOperation={optimisticOperation}
onClose={onClose}
onGoToFirstStep={this.onGoToFirstStep}

49
src/helpers/SettingsDefaults.js

@ -1,6 +1,6 @@
// @flow
import type { CryptoCurrencyConfig, CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
type ConfirmationDefaults = {
confirmationsNb: ?{
@ -10,44 +10,15 @@ type ConfirmationDefaults = {
},
}
// This is approximated to be a 30mn confirmation in number of blocks on blockchains
// to disable the confirmations feature simply set 0.
const confirmationsNbPerCoin: CryptoCurrencyConfig<number> = {
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,
}
}

34
src/helpers/explorers.js

@ -1,34 +0,0 @@
// @flow
import type { Account, Operation, CryptoCurrencyConfig } from '@ledgerhq/live-common/lib/types'
type Explorer = Operation => ?string
const txExplorers: CryptoCurrencyConfig<Explorer> = {
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)

35
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<Resolver> = {
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

6
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"

Loading…
Cancel
Save