diff --git a/package.json b/package.json index a71ef710..ad43dc8d 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "@ledgerhq/hw-transport": "^4.39.0", "@ledgerhq/hw-transport-node-hid": "^4.40.0", "@ledgerhq/ledger-core": "2.0.0-rc.21", - "@ledgerhq/live-common": "4.18.0", + "@ledgerhq/live-common": "4.20.0", "animated": "^0.2.2", "async": "^2.6.1", "axios": "^0.18.0", diff --git a/src/components/CurrenciesStatusBanner.js b/src/components/CurrenciesStatusBanner.js index 2138f73d..a208f38f 100644 --- a/src/components/CurrenciesStatusBanner.js +++ b/src/components/CurrenciesStatusBanner.js @@ -92,15 +92,19 @@ class CurrenciesStatusBanner extends PureComponent<Props> { render() { const { dismissedBanners, accountsCurrencies, currenciesStatus, t } = this.props + const filtered = currenciesStatus.filter( item => accountsCurrencies.find(cur => cur.id === item.id) && dismissedBanners.indexOf(getItemKey(item)) === -1, ) + if (!filtered.length) return null return ( <Box flow={2} style={styles.container}> - {filtered.map(r => <BannerItem key={r.id} t={t} item={r} onItemDismiss={this.dismiss} />)} + {filtered.map(r => ( + <BannerItem key={`{r.id}_${r.nonce}`} t={t} item={r} onItemDismiss={this.dismiss} /> + ))} </Box> ) } diff --git a/src/components/ManagerPage/AppsList.js b/src/components/ManagerPage/AppsList.js index d2935f46..7f8267c7 100644 --- a/src/components/ManagerPage/AppsList.js +++ b/src/components/ManagerPage/AppsList.js @@ -9,8 +9,10 @@ import { compose } from 'redux' import type { Device, T } from 'types/common' import type { ApplicationVersion, DeviceInfo } from '@ledgerhq/live-common/lib/types/manager' +import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types/currencies' import manager from '@ledgerhq/live-common/lib/manager' import { getFullListSortedCryptoCurrencies } from 'helpers/countervalues' +import { listCryptoCurrencies } from 'config/cryptocurrencies' import { developerModeSelector } from 'reducers/settings' import installApp from 'commands/installApp' import uninstallApp from 'commands/uninstallApp' @@ -89,7 +91,10 @@ type State = { } const oldAppsInstallDisabled = ['ZenCash', 'Ripple'] -const canHandleInstall = c => !oldAppsInstallDisabled.includes(c.name) +const terminatedCryptoCurrencies: Array<CryptoCurrency> = listCryptoCurrencies(true, true) +const canHandleInstall = app => + !oldAppsInstallDisabled.includes(app.name) && + !terminatedCryptoCurrencies.some(coin => coin.managerAppName === app.name) const LoadingApp = () => ( <FakeManagerAppContainer noShadow align="center" justify="center" style={{ height: 90 }}> diff --git a/src/components/modals/Send/steps/01-step-amount.js b/src/components/modals/Send/steps/01-step-amount.js index fd810e9c..feb239d1 100644 --- a/src/components/modals/Send/steps/01-step-amount.js +++ b/src/components/modals/Send/steps/01-step-amount.js @@ -19,6 +19,7 @@ import RecipientField from '../fields/RecipientField' import AmountField from '../fields/AmountField' import type { StepProps } from '../index' +import { listCryptoCurrencies } from '../../../../config/cryptocurrencies' export default ({ t, @@ -154,6 +155,9 @@ export class StepAmountFooter extends PureComponent< render() { const { t, transitionTo, account } = this.props const { isSyncing, totalSpent, canNext } = this.state + const isTerminated = + account && listCryptoCurrencies(true, true).some(coin => coin.name === account.currency.name) + return ( <Fragment> <Box grow> @@ -190,7 +194,11 @@ export class StepAmountFooter extends PureComponent< {isSyncing && <Spinner size={10} />} </Box> </Box> - <Button disabled={!canNext} primary onClick={() => transitionTo('device')}> + <Button + disabled={!canNext || !!isTerminated} + primary + onClick={() => transitionTo('device')} + > {t('common.continue')} </Button> </Fragment> diff --git a/src/config/cryptocurrencies.js b/src/config/cryptocurrencies.js index 4c29f7b3..28706048 100644 --- a/src/config/cryptocurrencies.js +++ b/src/config/cryptocurrencies.js @@ -32,8 +32,11 @@ const supported: CryptoCurrencyIds[] = [ 'bitcoin_testnet', ] -export const listCryptoCurrencies = memoize((withDevCrypto?: boolean) => - listCC(withDevCrypto) - .filter(c => supported.includes(c.id)) - .sort((a, b) => a.name.localeCompare(b.name)), +export const listCryptoCurrencies = memoize( + (withDevCrypto?: boolean, onlyTerminated?: boolean = false) => + listCC(withDevCrypto) + .filter(c => supported.includes(c.id)) + .filter(c => (onlyTerminated ? c.terminated : !c.terminated)) + .sort((a, b) => a.name.localeCompare(b.name)), + (a?: boolean, b?: boolean) => `${a ? 1 : 0}_${b ? 1 : 0}`, ) diff --git a/src/reducers/currenciesStatus.js b/src/reducers/currenciesStatus.js index b582fa87..b0a228a6 100644 --- a/src/reducers/currenciesStatus.js +++ b/src/reducers/currenciesStatus.js @@ -1,4 +1,5 @@ // @flow +import React from 'react' import { handleActions, createAction } from 'redux-actions' import { createSelector } from 'reselect' @@ -8,7 +9,9 @@ import network from 'api/network' import { urls } from 'config/urls' import logger from 'logger' +import { Trans } from 'react-i18next' import type { State } from './index' +import { listCryptoCurrencies } from '../config/cryptocurrencies' export type CurrencyStatus = { id: string, // the currency id @@ -39,8 +42,24 @@ export const fetchCurrenciesStatus = () => async (dispatch: *) => { method: 'GET', url: process.env.LL_STATUS_ENDPOINT || urls.currenciesStatus, }) + + const terminatedCurrencies = listCryptoCurrencies(true, true).map(coin => ({ + id: coin.id, + nonce: 98, + message: ( + <Trans + i18nKey="banners.genericTerminatedCrypto" + values={{ coinName: coin.name }} + parent="div" + /> + ), + link: (coin.terminated && coin.terminated.link) || '#', + })) + if (Array.isArray(data)) { - dispatch(setCurrenciesStatus(data)) + dispatch(setCurrenciesStatus(data.concat(terminatedCurrencies))) + } else { + setCurrenciesStatus(terminatedCurrencies) } } catch (err) { logger.error(err) diff --git a/static/i18n/en/app.json b/static/i18n/en/app.json index 49211dd2..bdb8bfbf 100644 --- a/static/i18n/en/app.json +++ b/static/i18n/en/app.json @@ -112,7 +112,8 @@ } }, "banners": { - "promoteMobile": "Enjoy the Ledger Live experience, now available on mobile with the Ledger Nano X" + "promoteMobile": "Enjoy the Ledger Live experience, now available on mobile with the Ledger Nano X", + "genericTerminatedCrypto": "{{coinName}} is not supported anymore" }, "dashboard": { "title": "Portfolio", diff --git a/yarn.lock b/yarn.lock index 1b40b916..f76aae9a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1684,12 +1684,12 @@ dependencies: "@ledgerhq/errors" "^4.39.0" -"@ledgerhq/errors@^4.32.0", "@ledgerhq/errors@^4.39.0": +"@ledgerhq/errors@^4.39.0": version "4.39.0" resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-4.39.0.tgz#10b9889f78df94ce36a4b34d9a3a45aac77be0e9" integrity sha512-kBr2rnoYDACRCxTLtEufE4oCvYj6vx2oFWVVjwskBxYsF5LC9R8Mbg5C4GgvDweiWW4Io8HA9p9jCsOfdCDygg== -"@ledgerhq/hw-app-btc@^4.32.0", "@ledgerhq/hw-app-btc@^4.39.0": +"@ledgerhq/hw-app-btc@^4.39.0": version "4.39.0" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-4.39.0.tgz#5b564e683a43a50002579834ec54aa790fde35f1" integrity sha512-xPOtoIgsErycMFTKHb0yHLqlKn0C+9msLBsA1zRPNsWMdxEEBO5pzFVmn5ha1j3q/73yeICHlcB4KZcTb7CShA== @@ -1697,14 +1697,14 @@ "@ledgerhq/hw-transport" "^4.39.0" create-hash "^1.1.3" -"@ledgerhq/hw-app-eth@^4.32.0", "@ledgerhq/hw-app-eth@^4.39.0": +"@ledgerhq/hw-app-eth@^4.39.0": version "4.39.0" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-4.39.0.tgz#3cbba1f1650665c4c29c7b9fa246cb2360495867" integrity sha512-IKPcLTcGohh/S6Z1LaAfn2pGyxfT6xu958/xV+5H4a3Ej0CWKaxcno4FkhaxH4OiViF0F5SEFzxtH+UntH2jdg== dependencies: "@ledgerhq/hw-transport" "^4.39.0" -"@ledgerhq/hw-app-xrp@^4.32.0", "@ledgerhq/hw-app-xrp@^4.39.0": +"@ledgerhq/hw-app-xrp@^4.39.0": version "4.39.0" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-xrp/-/hw-app-xrp-4.39.0.tgz#cc399649f17873778e34bcde16f488faef3117e5" integrity sha512-lbrG7AhQdJzt/zhu0G5yfC2t4zlytWuzbNLrPp/VQKJJPUKsC98H81pmfMzn1lFBdm8frmBVUW6reN5p7wDS2Q== @@ -1724,7 +1724,7 @@ node-hid "^0.7.6" usb "^1.5.0" -"@ledgerhq/hw-transport@^4.21.0", "@ledgerhq/hw-transport@^4.32.0", "@ledgerhq/hw-transport@^4.39.0": +"@ledgerhq/hw-transport@^4.21.0", "@ledgerhq/hw-transport@^4.39.0": version "4.39.0" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-4.39.0.tgz#602c6ea3fef56d1df205274ea742b4cf85613f6c" integrity sha512-XkVAy2SFRDdE3qQGGVxB7RQdsdIx1fcoRNReU7NQXK59fYqxue+ZoiGtynEoHq9RKMg8EBG2kBXSVEh1iPdOlA== @@ -1741,20 +1741,21 @@ bindings "^1.3.0" nan "^2.6.2" -"@ledgerhq/live-common@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.18.0.tgz#0e087e18ec147feaebfaf66e6346138b4a7e4fd2" - integrity sha512-hcIzeuw96T2eYm13KYatg32zNyl5o16yyJrc+C+xB5mG0FeL6zSAEvodLsLqVIeJ22YXl5lVAlx8y4VVI0AseA== +"@ledgerhq/live-common@4.20.0": + version "4.20.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.20.0.tgz#034763f79a308245b0d7754341e0c9731e4d77c0" + integrity sha512-zOamSAo9kIVi7zmYAovDh7xDFOF9DThSQGtXmu25zIIPhGeAWPQo9rVvtDCV9CDHTjsPs5baN0qFSCHwFIM9Cw== dependencies: "@aeternity/ledger-app-api" "0.0.4" - "@ledgerhq/errors" "^4.32.0" - "@ledgerhq/hw-app-btc" "^4.32.0" - "@ledgerhq/hw-app-eth" "^4.32.0" - "@ledgerhq/hw-app-xrp" "^4.32.0" - "@ledgerhq/hw-transport" "^4.32.0" + "@ledgerhq/errors" "^4.39.0" + "@ledgerhq/hw-app-btc" "^4.39.0" + "@ledgerhq/hw-app-eth" "^4.39.0" + "@ledgerhq/hw-app-xrp" "^4.39.0" + "@ledgerhq/hw-transport" "^4.39.0" bignumber.js "^7.2.1" compressjs gre/compressjs#hermit eip55 "^1.0.3" + ethereumjs-tx "^1.3.7" invariant "^2.2.2" lodash "^4.17.4" numeral "^2.0.6" @@ -1764,6 +1765,10 @@ react-redux "^5.0.7" redux "^4.0.0" reselect "^3.0.1" + ripple-binary-codec "^0.2.0" + ripple-bs58check "^2.0.2" + ripple-hashes "^0.3.1" + ripple-lib "^1.1.2" rxjs "^6.3.3" rxjs-compat "^6.3.3" @@ -7453,6 +7458,14 @@ ethereumjs-tx@^1.3.4: ethereum-common "^0.0.18" ethereumjs-util "^5.0.0" +ethereumjs-tx@^1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" + integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== + dependencies: + ethereum-common "^0.0.18" + ethereumjs-util "^5.0.0" + ethereumjs-util@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" @@ -14244,6 +14257,19 @@ ripple-address-codec@^2.0.1: hash.js "^1.0.3" x-address-codec "^0.7.0" +ripple-binary-codec@0.2.0, ripple-binary-codec@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ripple-binary-codec/-/ripple-binary-codec-0.2.0.tgz#cef049f671f398de255e5c190b9f6545c7c7c36f" + integrity sha512-qCf3syhtwPFq70JIh/7VSegynj5gWXVNI5T5I7dobqiNxY3fZQvOePRnchnN1OzC0jMh8x0b2ASmkvIlf259zQ== + dependencies: + babel-runtime "^6.6.1" + bn.js "^4.11.3" + create-hash "^1.1.2" + decimal.js "^5.0.8" + inherits "^2.0.1" + lodash "^4.12.0" + ripple-address-codec "^2.0.1" + ripple-binary-codec@^0.1.0, ripple-binary-codec@^0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/ripple-binary-codec/-/ripple-binary-codec-0.1.13.tgz#c68951405a17a71695551e789966ff376da552e4" @@ -14294,6 +14320,14 @@ ripple-keypairs@^0.10.1: hash.js "^1.0.3" ripple-address-codec "^2.0.1" +ripple-lib-transactionparser@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ripple-lib-transactionparser/-/ripple-lib-transactionparser-0.7.1.tgz#5ececb1e03d65d05605343f4b9dbb76d1089145b" + integrity sha1-Xs7LHgPWXQVgU0P0udu3bRCJFFs= + dependencies: + bignumber.js "^4.1.0" + lodash "^4.17.4" + ripple-lib-transactionparser@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/ripple-lib-transactionparser/-/ripple-lib-transactionparser-0.6.2.tgz#eb117834816cab3398445a74ec3cacec95b6b5fa" @@ -14320,6 +14354,24 @@ ripple-lib@^1.0.0-beta.0: ripple-lib-transactionparser "^0.6.2" ws "^3.3.1" +ripple-lib@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/ripple-lib/-/ripple-lib-1.1.2.tgz#e9cf21e7ac61c70c90dd0b105bacc561e5046f12" + integrity sha512-LPWsOi0trS1gcBKJpQPA9vDCn3IUfW0RYaWLLlELoNQY0MJUOG1e0J3qQlDrL+/gRW/MywlPtux5D+I4GiEVHw== + dependencies: + "@types/lodash" "^4.14.85" + "@types/ws" "^3.2.0" + bignumber.js "^4.1.0" + https-proxy-agent "2.2.1" + jsonschema "1.2.2" + lodash "^4.17.4" + ripple-address-codec "^2.0.1" + ripple-binary-codec "0.2.0" + ripple-hashes "^0.3.1" + ripple-keypairs "^0.10.1" + ripple-lib-transactionparser "0.7.1" + ws "^3.3.1" + rlp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.1.0.tgz#e4f9886d5a982174f314543831e36e1a658460f9"