Browse Source

Merge pull request #1785 from juan-cortes/LL-898

Handle source===destination on select recipient for xrp
gre-patch-1
Gaëtan Renaudeau 6 years ago
committed by GitHub
parent
commit
c98bd17858
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      package.json
  2. 8
      src/bridge/EthereumJSBridge.js
  3. 8
      src/bridge/LibcoreBridge.js
  4. 20
      src/bridge/RippleJSBridge.js
  5. 2
      src/bridge/makeMockBridge.js
  6. 4
      src/bridge/types.js
  7. 10
      src/components/modals/Send/fields/RecipientField.js
  8. 2
      src/components/modals/Send/steps/01-step-amount.js
  9. 3
      static/i18n/en/app.json
  10. 8
      yarn.lock

1
package.json

@ -35,6 +35,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@ledgerhq/errors": "^4.35.1",
"@ledgerhq/hw-app-btc": "^4.34.0", "@ledgerhq/hw-app-btc": "^4.34.0",
"@ledgerhq/hw-app-eth": "^4.32.0", "@ledgerhq/hw-app-eth": "^4.32.0",
"@ledgerhq/hw-app-xrp": "^4.32.0", "@ledgerhq/hw-app-xrp": "^4.32.0",

8
src/bridge/EthereumJSBridge.js

@ -129,7 +129,7 @@ function isRecipientValid(currency, recipient) {
} }
// Returns a warning if we detect a non-eip address // Returns a warning if we detect a non-eip address
function getRecipientWarning(currency, recipient) { function getRecipientWarning(account, recipient) {
if (!recipient.match(/^0x[0-9a-fA-F]{40}$/)) return null if (!recipient.match(/^0x[0-9a-fA-F]{40}$/)) return null
const slice = recipient.substr(2) const slice = recipient.substr(2)
const isFullUpper = slice === slice.toUpperCase() const isFullUpper = slice === slice.toUpperCase()
@ -420,9 +420,9 @@ const EthereumBridge: WalletBridge<Transaction> = {
pullMoreOperations: () => Promise.resolve(a => a), // NOT IMPLEMENTED pullMoreOperations: () => Promise.resolve(a => a), // NOT IMPLEMENTED
isRecipientValid: (currency, recipient) => Promise.resolve(isRecipientValid(currency, recipient)), isRecipientValid: (account, recipient) => Promise.resolve(isRecipientValid(account, recipient)),
getRecipientWarning: (currency, recipient) => getRecipientWarning: (account, recipient) =>
Promise.resolve(getRecipientWarning(currency, recipient)), Promise.resolve(getRecipientWarning(account, recipient)),
createTransaction: () => ({ createTransaction: () => ({
amount: BigNumber(0), amount: BigNumber(0),

8
src/bridge/LibcoreBridge.js

@ -60,15 +60,15 @@ const EditAdvancedOptions = ({ onChange, value }: EditProps<Transaction>) => (
const recipientValidLRU = LRU({ max: 100 }) const recipientValidLRU = LRU({ max: 100 })
const isRecipientValid = (currency, recipient) => { const isRecipientValid = (account, recipient) => {
const key = `${currency.id}_${recipient}` const key = `${account.currency.id}_${recipient}`
let promise = recipientValidLRU.get(key) let promise = recipientValidLRU.get(key)
if (promise) return promise if (promise) return promise
if (!recipient) return Promise.resolve(false) if (!recipient) return Promise.resolve(false)
promise = libcoreValidAddress promise = libcoreValidAddress
.send({ .send({
address: recipient, address: recipient,
currencyId: currency.id, currencyId: account.currency.id,
}) })
.toPromise() .toPromise()
recipientValidLRU.set(key, promise) recipientValidLRU.set(key, promise)
@ -83,7 +83,7 @@ const getFeesKey = (a, t) =>
}` }`
const getFees = async (a, transaction) => { const getFees = async (a, transaction) => {
const isValid = await isRecipientValid(a.currency, transaction.recipient) const isValid = await isRecipientValid(a, transaction.recipient)
if (!isValid) return null if (!isValid) return null
const key = getFeesKey(a, transaction) const key = getFeesKey(a, transaction)
let promise = feesLRU.get(key) let promise = feesLRU.get(key)

20
src/bridge/RippleJSBridge.js

@ -34,6 +34,7 @@ import {
NotEnoughBalance, NotEnoughBalance,
FeeNotLoaded, FeeNotLoaded,
NotEnoughBalanceBecauseDestinationNotCreated, NotEnoughBalanceBecauseDestinationNotCreated,
InvalidAddressBecauseDestinationIsAlsoSource,
} from '@ledgerhq/errors' } from '@ledgerhq/errors'
import type { WalletBridge, EditProps } from './types' import type { WalletBridge, EditProps } from './types'
@ -136,15 +137,23 @@ async function signAndBroadcast({ a, t, deviceId, isCancelled, onSigned, onOpera
} }
} }
function isRecipientValid(recipient) { function isRecipientValid(account, recipient) {
try { try {
bs58check.decode(recipient) bs58check.decode(recipient)
return true
return !(account && account.freshAddress === recipient)
} catch (e) { } catch (e) {
return false return false
} }
} }
function getRecipientWarning(account, recipient) {
if (account.freshAddress === recipient) {
return new InvalidAddressBecauseDestinationIsAlsoSource()
}
return null
}
function mergeOps(existing: Operation[], newFetched: Operation[]) { function mergeOps(existing: Operation[], newFetched: Operation[]) {
const ids = existing.map(o => o.id) const ids = existing.map(o => o.id)
const all = existing.concat(newFetched.filter(o => !ids.includes(o.id))) const all = existing.concat(newFetched.filter(o => !ids.includes(o.id)))
@ -270,7 +279,7 @@ const getServerInfo = (map => endpointConfig => {
})({}) })({})
const recipientIsNew = async (endpointConfig, recipient) => { const recipientIsNew = async (endpointConfig, recipient) => {
if (!isRecipientValid(recipient)) return false if (!isRecipientValid(null, recipient)) return false
const api = apiForEndpointConfig(RippleAPI, endpointConfig) const api = apiForEndpointConfig(RippleAPI, endpointConfig)
try { try {
await api.connect() await api.connect()
@ -505,8 +514,9 @@ const RippleJSBridge: WalletBridge<Transaction> = {
pullMoreOperations: () => Promise.resolve(a => a), // FIXME not implemented pullMoreOperations: () => Promise.resolve(a => a), // FIXME not implemented
isRecipientValid: (currency, recipient) => Promise.resolve(isRecipientValid(recipient)), isRecipientValid: (account, recipient) => Promise.resolve(isRecipientValid(account, recipient)),
getRecipientWarning: () => Promise.resolve(null), getRecipientWarning: (account, recipient) =>
Promise.resolve(getRecipientWarning(account, recipient)),
createTransaction: () => ({ createTransaction: () => ({
amount: BigNumber(0), amount: BigNumber(0),

2
src/bridge/makeMockBridge.js

@ -128,7 +128,7 @@ function makeMockBridge(opts?: Opts): WalletBridge<*> {
} }
}, },
isRecipientValid: (currency, recipient) => Promise.resolve(recipient.length > 0), isRecipientValid: (account, recipient) => Promise.resolve(recipient.length > 0),
getRecipientWarning: () => Promise.resolve(null), getRecipientWarning: () => Promise.resolve(null),
createTransaction: () => ({ createTransaction: () => ({

4
src/bridge/types.js

@ -52,8 +52,8 @@ export interface WalletBridge<Transaction> {
// count is user's desired number of ops to pull (but implementation can decide to ignore it or not) // count is user's desired number of ops to pull (but implementation can decide to ignore it or not)
pullMoreOperations(initialAccount: Account, count: number): Promise<(Account) => Account>; pullMoreOperations(initialAccount: Account, count: number): Promise<(Account) => Account>;
isRecipientValid(currency: Currency, recipient: string): Promise<boolean>; isRecipientValid(account: Account, recipient: string): Promise<boolean>;
getRecipientWarning(currency: Currency, recipient: string): Promise<?Error>; getRecipientWarning(account: Account, recipient: string): Promise<?Error>;
// Related to send funds: // Related to send funds:

10
src/components/modals/Send/fields/RecipientField.js

@ -53,8 +53,8 @@ class RecipientField<Transaction> extends Component<
const { account, bridge, transaction } = this.props const { account, bridge, transaction } = this.props
const syncId = ++this.syncId const syncId = ++this.syncId
const recipient = bridge.getTransactionRecipient(account, transaction) const recipient = bridge.getTransactionRecipient(account, transaction)
const isValid = await bridge.isRecipientValid(account.currency, recipient) const isValid = await bridge.isRecipientValid(account, recipient)
const warning = await bridge.getRecipientWarning(account.currency, recipient) const warning = await bridge.getRecipientWarning(account, recipient)
if (syncId !== this.syncId) return if (syncId !== this.syncId) return
if (this.isUnmounted) return if (this.isUnmounted) return
this.setState({ isValid, warning }) this.setState({ isValid, warning })
@ -69,9 +69,7 @@ class RecipientField<Transaction> extends Component<
if (amount) { if (amount) {
t = bridge.editTransactionAmount(account, t, amount) t = bridge.editTransactionAmount(account, t, amount)
} }
const warning = fromQRCode const warning = fromQRCode ? await bridge.getRecipientWarning(account, recipient) : null
? await bridge.getRecipientWarning(account.currency, recipient)
: null
if (this.isUnmounted) return false if (this.isUnmounted) return false
if (warning) { if (warning) {
// clear the input if field has warning AND has a warning // clear the input if field has warning AND has a warning
@ -97,7 +95,7 @@ class RecipientField<Transaction> extends Component<
const error = const error =
!value || isValid !value || isValid
? QRCodeRefusedReason ? QRCodeRefusedReason
: new InvalidAddress(null, { currencyName: account.currency.name }) : warning || new InvalidAddress(null, { currencyName: account.currency.name })
return ( return (
<Box flow={1}> <Box flow={1}>

2
src/components/modals/Send/steps/01-step-amount.js

@ -133,7 +133,7 @@ export class StepAmountFooter extends PureComponent<
const totalSpent = await bridge.getTotalSpent(account, transaction) const totalSpent = await bridge.getTotalSpent(account, transaction)
if (syncId !== this.syncId) return if (syncId !== this.syncId) return
const isRecipientValid = await bridge.isRecipientValid( const isRecipientValid = await bridge.isRecipientValid(
account.currency, account,
bridge.getTransactionRecipient(account, transaction), bridge.getTransactionRecipient(account, transaction),
) )
if (syncId !== this.syncId) return if (syncId !== this.syncId) return

3
static/i18n/en/app.json

@ -900,6 +900,9 @@
"InvalidAddress": { "InvalidAddress": {
"title": "This is not a valid {{currencyName}} address" "title": "This is not a valid {{currencyName}} address"
}, },
"InvalidAddressBecauseDestinationIsAlsoSource": {
"title": "Recipient address is the same as the sender address"
},
"CantOpenDevice": { "CantOpenDevice": {
"title": "Oops, couldn’t connect to device", "title": "Oops, couldn’t connect to device",
"description": "Device detected but connection failed. Please try again or contact us if the problem persists." "description": "Device detected but connection failed. Please try again or contact us if the problem persists."

8
yarn.lock

@ -1677,10 +1677,10 @@
camelcase "^5.0.0" camelcase "^5.0.0"
prettier "^1.13.7" prettier "^1.13.7"
"@ledgerhq/errors@^4.32.0": "@ledgerhq/errors@^4.32.0", "@ledgerhq/errors@^4.35.1":
version "4.33.7" version "4.35.1"
resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-4.33.7.tgz#b78becd20e8a68f7115ad0986fa357a8adddf6b7" resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-4.35.1.tgz#3f162dc05480e444083b6381bd098df187751633"
integrity sha512-1vKWcttI5NHpT6rMKKuxWPAjfwDgfgUTf/AyNAT5KXHlhiLvqnA3NDCdNUVadajVNKSa/s1u1ZWKismtbfePzg== integrity sha512-2Bo3/NRKyz3ddR07TvZ87VpDJc8fz4+ONLJnhzC0mwIwu+Pxal6SgCBiGtv503oGxkgDuG5PtODZBaehWkGRnQ==
"@ledgerhq/hw-app-btc@^4.32.0": "@ledgerhq/hw-app-btc@^4.32.0":
version "4.32.0" version "4.32.0"

Loading…
Cancel
Save