diff --git a/package.json b/package.json
index 6cea84ba..eeeac8c0 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"productName": "Ledger Live",
"description": "Ledger Live - Desktop",
"repository": "https://github.com/LedgerHQ/ledger-live-desktop",
- "version": "1.1.6",
+ "version": "1.1.7",
"author": "Ledger",
"license": "MIT",
"scripts": {
@@ -39,7 +39,7 @@
"@ledgerhq/hw-transport": "^4.13.0",
"@ledgerhq/hw-transport-node-hid": "4.22.0",
"@ledgerhq/ledger-core": "2.0.0-rc.6",
- "@ledgerhq/live-common": "3.0.0",
+ "@ledgerhq/live-common": "3.0.2",
"animated": "^0.2.2",
"async": "^2.6.1",
"axios": "^0.18.0",
diff --git a/src/components/ExchangePage/index.js b/src/components/ExchangePage/index.js
index 6f40ae6c..9e612a78 100644
--- a/src/components/ExchangePage/index.js
+++ b/src/components/ExchangePage/index.js
@@ -5,6 +5,7 @@ import { translate } from 'react-i18next'
import type { T } from 'types/common'
import { urls } from 'config/urls'
+import { i } from 'helpers/staticPath'
import TrackPage from 'analytics/TrackPage'
import Box from 'components/base/Box'
@@ -51,6 +52,24 @@ const cards = [
url: urls.paybis,
logo: ,
},
+ {
+ key: 'luno',
+ id: 'luno',
+ url: urls.luno,
+ logo: ,
+ },
+ {
+ key: 'shapeshift',
+ id: 'shapeshift',
+ url: urls.shapeshift,
+ logo: ,
+ },
+ {
+ key: 'genesis',
+ id: 'genesis',
+ url: urls.genesis,
+ logo: ,
+ },
]
class ExchangePage extends PureComponent {
diff --git a/src/components/QRCodeCameraPickerCanvas.js b/src/components/QRCodeCameraPickerCanvas.js
index b2f6643e..c4340e72 100644
--- a/src/components/QRCodeCameraPickerCanvas.js
+++ b/src/components/QRCodeCameraPickerCanvas.js
@@ -155,7 +155,7 @@ export default class QRCodeCameraPickerCanvas extends Component<
.catch(e => {
if (this.unmounted) return
this.setState({
- message: String(e.message || e),
+ message: String(e.message || e.name || e),
})
})
}
diff --git a/src/components/RecipientAddress/index.js b/src/components/RecipientAddress/index.js
index 24f7895d..e825d2d4 100644
--- a/src/components/RecipientAddress/index.js
+++ b/src/components/RecipientAddress/index.js
@@ -47,7 +47,7 @@ const BackgroundLayer = styled(Box)`
type Props = {
value: string,
// return false if it can't be changed (invalid info)
- onChange: (string, ?{ amount?: BigNumber, currency?: CryptoCurrency }) => ?boolean,
+ onChange: (string, ?{ amount?: BigNumber, currency?: CryptoCurrency }) => Promise,
withQrCode: boolean,
}
@@ -76,6 +76,8 @@ class RecipientAddress extends PureComponent {
handleOnPick = (code: string) => {
const { address, ...rest } = decodeURIScheme(code)
+ // $FlowFixMe
+ Object.assign(rest, { fromQRCode: true })
if (this.props.onChange(address, rest) !== false) {
this.setState({ qrReaderOpened: false })
}
diff --git a/src/components/modals/AddAccounts/steps/04-step-finish.js b/src/components/modals/AddAccounts/steps/04-step-finish.js
index 6170af8e..312c4aea 100644
--- a/src/components/modals/AddAccounts/steps/04-step-finish.js
+++ b/src/components/modals/AddAccounts/steps/04-step-finish.js
@@ -52,7 +52,7 @@ export default StepFinish
export const StepFinishFooter = ({ onGoStep1, t }: StepProps) => (
-
diff --git a/src/components/modals/Send/fields/RecipientField.js b/src/components/modals/Send/fields/RecipientField.js
index c037a150..f083cfa7 100644
--- a/src/components/modals/Send/fields/RecipientField.js
+++ b/src/components/modals/Send/fields/RecipientField.js
@@ -9,6 +9,8 @@ import Box from 'components/base/Box'
import LabelWithExternalIcon from 'components/base/LabelWithExternalIcon'
import RecipientAddress from 'components/RecipientAddress'
import { track } from 'analytics/segment'
+import { createCustomErrorClass } from 'helpers/errors'
+import { CantScanQRCode } from 'config/errors'
import { InvalidAddress } from 'config/errors'
type Props = {
@@ -22,11 +24,12 @@ type Props = {
class RecipientField extends Component<
Props,
- { isValid: boolean, warning: ?Error },
+ { isValid: boolean, warning: ?Error, QRCodeRefusedReason: ?Error },
> {
state = {
isValid: true,
warning: null,
+ QRCodeRefusedReason: null,
}
componentDidMount() {
this.resync()
@@ -41,7 +44,9 @@ class RecipientField extends Component<
}
componentWillUnmount() {
this.syncId++
+ this.isUnmounted = true
}
+ isUnmounted = false
syncId = 0
async resync() {
const { account, bridge, transaction } = this.props
@@ -50,18 +55,31 @@ class RecipientField extends Component<
const isValid = await bridge.isRecipientValid(account.currency, recipient)
const warning = await bridge.getRecipientWarning(account.currency, recipient)
if (syncId !== this.syncId) return
+ if (this.isUnmounted) return
this.setState({ isValid, warning })
}
- onChange = (recipient: string, maybeExtra: ?Object) => {
+ onChange = async (recipient: string, maybeExtra: ?Object) => {
const { bridge, account, transaction, onChangeTransaction } = this.props
- const { amount, currency } = maybeExtra || {}
+ const { QRCodeRefusedReason } = this.state
+ const { amount, currency, fromQRCode } = maybeExtra || {}
if (currency && currency.scheme !== account.currency.scheme) return false
let t = transaction
if (amount) {
t = bridge.editTransactionAmount(account, t, amount)
}
- t = bridge.editTransactionRecipient(account, t, recipient)
+ const warning = fromQRCode
+ ? await bridge.getRecipientWarning(account.currency, recipient)
+ : null
+ if (this.isUnmounted) return false
+ if (warning) {
+ // clear the input if field has warning AND has a warning
+ t = bridge.editTransactionRecipient(account, t, '')
+ this.setState({ QRCodeRefusedReason: new CantScanQRCode() })
+ } else {
+ t = bridge.editTransactionRecipient(account, t, recipient)
+ if (QRCodeRefusedReason) this.setState({ QRCodeRefusedReason: null })
+ }
onChangeTransaction(t)
return true
}
@@ -72,11 +90,13 @@ class RecipientField extends Component<
}
render() {
const { bridge, account, transaction, t, autoFocus } = this.props
- const { isValid, warning } = this.state
+ const { isValid, warning, QRCodeRefusedReason } = this.state
const value = bridge.getTransactionRecipient(account, transaction)
const error =
- !value || isValid ? null : new InvalidAddress(null, { currencyName: account.currency.name })
+ !value || isValid
+ ? QRCodeRefusedReason
+ : new InvalidAddress(null, { currencyName: account.currency.name })
return (
@@ -86,7 +106,7 @@ class RecipientField extends Component<
/>
+
+
+
+
+
diff --git a/static/images/logos/exchanges/luno.svg b/static/images/logos/exchanges/luno.svg
new file mode 100644
index 00000000..e2ee1781
--- /dev/null
+++ b/static/images/logos/exchanges/luno.svg
@@ -0,0 +1,14 @@
+
diff --git a/static/images/logos/exchanges/shapeshift.svg b/static/images/logos/exchanges/shapeshift.svg
new file mode 100644
index 00000000..5efd76eb
--- /dev/null
+++ b/static/images/logos/exchanges/shapeshift.svg
@@ -0,0 +1,93 @@
+
diff --git a/yarn.lock b/yarn.lock
index ff1b4421..23aa34ce 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1542,9 +1542,9 @@
npm "^5.7.1"
prebuild-install "^2.2.2"
-"@ledgerhq/live-common@3.0.0":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-3.0.0.tgz#abbd88e351c7d0ffffabf7e8502f5b2fbecdc150"
+"@ledgerhq/live-common@3.0.2":
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-3.0.2.tgz#1ee5fcc6044c5a049c067978d81892f79789863c"
dependencies:
axios "^0.18.0"
bignumber.js "^7.2.1"