diff --git a/renderer/components/Pay/PaySummaryLightning.js b/renderer/components/Pay/PaySummaryLightning.js index 75e2a062f7d..56a554f50d3 100644 --- a/renderer/components/Pay/PaySummaryLightning.js +++ b/renderer/components/Pay/PaySummaryLightning.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import { Box, Flex } from 'rebass/styled-components' import { FormattedMessage } from 'react-intl' import { convert } from '@zap/utils/btc' -import { decodePayReq, getNodeAlias } from '@zap/utils/crypto' +import { decodePayReq, getNodeAlias, getTag } from '@zap/utils/crypto' import BigArrowRight from 'components/Icon/BigArrowRight' import { Bar, DataRow, Spinner, Text } from 'components/UI' import { CryptoSelector, CryptoValue, FiatValue } from 'containers/UI' @@ -63,8 +63,7 @@ class PaySummaryLightning extends React.Component { } const { satoshis, millisatoshis, payeeNodeKey } = invoice - const descriptionTag = invoice.tags.find(tag => tag.tagName === 'description') || {} - const memo = descriptionTag.data + const memo = getTag(invoice, 'description') const amountInSatoshis = satoshis || convert('msats', 'sats', millisatoshis) || amount const nodeAlias = getNodeAlias(payeeNodeKey, nodes) diff --git a/renderer/components/Request/RequestSummary.js b/renderer/components/Request/RequestSummary.js index ef8bd29825d..b53a6d12a9c 100644 --- a/renderer/components/Request/RequestSummary.js +++ b/renderer/components/Request/RequestSummary.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import { Box, Flex } from 'rebass/styled-components' import { FormattedMessage, FormattedTime, injectIntl } from 'react-intl' import copy from 'copy-to-clipboard' -import { decodePayReq } from '@zap/utils/crypto' +import { decodePayReq, getTag } from '@zap/utils/crypto' import getUnixTime from '@zap/utils/time' import { Bar, DataRow, Button, QRCode, Text, Countdown } from 'components/UI' import { CryptoSelector, CryptoValue, FiatSelector, FiatValue } from 'containers/UI' @@ -31,13 +31,12 @@ const RequestSummary = ({ invoice = {}, payReq, intl, showNotification, ...rest showNotification(notifBody) } - const { satoshis: invoiceAmount, tags, timestampString } = decodedInvoice + const { satoshis: invoiceAmount, timestampString } = decodedInvoice const satoshis = invoice.finalAmount || invoiceAmount || 0 - const descriptionTag = tags.find(tag => tag.tagName === 'description') || {} - const memo = descriptionTag.data + const memo = getTag(decodedInvoice, 'description') - const fallbackTag = tags.find(tag => tag.tagName === 'fallback_address') - const fallback = fallbackTag && fallbackTag.data.address + const fallbackTag = getTag(decodedInvoice, 'fallback_address') + const fallback = fallbackTag && fallbackTag.address const getStatusColor = () => { if (invoice.settled) { diff --git a/renderer/reducers/autopay.js b/renderer/reducers/autopay.js index e9907af1aee..241db910eec 100644 --- a/renderer/reducers/autopay.js +++ b/renderer/reducers/autopay.js @@ -2,6 +2,7 @@ import { createSelector } from 'reselect' import { isAutopayEnabled } from '@zap/utils/featureFlag' import { showSystemNotification } from '@zap/utils/notifications' import { getIntl } from '@zap/i18n' +import { getTag } from '@zap/utils/crypto' import truncateNodePubkey from '@zap/utils/truncateNodePubkey' import { contactFormSelectors } from './contactsform' import { tickerSelectors } from './ticker' @@ -232,7 +233,7 @@ function setAutopayListFromArray(state, { list }) { export const showAutopayNotification = invoice => async (dispatch, getState) => { const nodes = networkSelectors.nodes(getState()) - const descriptionTag = invoice.tags.find(tag => tag.tagName === 'description') || {} + const memo = getTag(invoice, 'description') const node = nodes.find(n => n.pub_key === invoice.payeeNodeKey) const nodeName = node ? getNodeDisplayName(node) : truncateNodePubkey(invoice.payeeNodeKey) @@ -247,9 +248,9 @@ export const showAutopayNotification = invoice => async (dispatch, getState) => }) let body = message - if (descriptionTag.data) { + if (memo) { const detail = intl.formatMessage(messages.autopay_notification_detail, { - reason: descriptionTag.data, + reason: memo, }) body += ` ${detail}` } diff --git a/renderer/reducers/payment.js b/renderer/reducers/payment.js index 149e6b0a92f..0d23140d1bf 100644 --- a/renderer/reducers/payment.js +++ b/renderer/reducers/payment.js @@ -4,7 +4,7 @@ import uniqBy from 'lodash/uniqBy' import find from 'lodash/find' import errorToUserFriendly from '@zap/utils/userFriendlyErrors' import { getIntl } from '@zap/i18n' -import { decodePayReq, getNodeAlias } from '@zap/utils/crypto' +import { decodePayReq, getNodeAlias, getTag } from '@zap/utils/crypto' import { convert } from '@zap/utils/btc' import delay from '@zap/utils/delay' import genId from '@zap/utils/genId' @@ -116,9 +116,9 @@ export function getPayments() { */ export const sendPayment = data => dispatch => { const invoice = decodePayReq(data.paymentRequest) - const paymentHashTag = invoice.tags ? invoice.tags.find(t => t.tagName === 'payment_hash') : null + const paymentHash = getTag(invoice, 'payment_hash') - if (!paymentHashTag || !paymentHashTag.data) { + if (!paymentHash) { dispatch(showError(getIntl().formatMessage(messages.payment_send_error))) return } @@ -128,7 +128,7 @@ export const sendPayment = data => dispatch => { status: PAYMENT_STATUS_SENDING, isSending: true, creation_date: Math.round(new Date() / 1000), - payment_hash: paymentHashTag.data, + payment_hash: paymentHash, } dispatch({ diff --git a/services/grpc/lightning.methods.js b/services/grpc/lightning.methods.js index 43aea41cee5..035229ba6eb 100644 --- a/services/grpc/lightning.methods.js +++ b/services/grpc/lightning.methods.js @@ -1,5 +1,5 @@ import promisifiedCall from '@zap/utils/promisifiedCall' -import { decodePayReq as bolt11DecodePayReq } from '@zap/utils/crypto' +import { decodePayReq as bolt11DecodePayReq, getTag } from '@zap/utils/crypto' import { grpcLog } from '@zap/utils/log' import { logGrpcCmd } from './helpers' @@ -278,10 +278,7 @@ async function sendPayment(payload = {}) { // In some cases lnd does not return the payment_hash. If this happens, retrieve it from the invoice. else { const invoice = bolt11DecodePayReq(payload.payment_request) - const paymentHashTag = invoice.tags - ? invoice.tags.find(t => t.tagName === 'payment_hash') - : null - data.payment_hash = paymentHashTag ? paymentHashTag.data : null + data.payment_hash = getTag(invoice, 'payment_hash') } // Convert the preimage to a hex string. diff --git a/utils/crypto.js b/utils/crypto.js index fcaeb3d7222..a4a279d374d 100644 --- a/utils/crypto.js +++ b/utils/crypto.js @@ -31,6 +31,21 @@ export const coinTypes = { }, } +/** + * getTag = Get tag data for `tagName` from a decoded bolt11 invoice. + * + * @param {object} invoice Decoded bolt11 invoice + * @param {string} tagName Tag to fetch + * @returns {*|null} Tag data or null if not found + */ +export const getTag = (invoice, tagName) => { + try { + return invoice.tags.find(t => t.tagName === tagName).data + } catch (e) { + return null + } +} + /** * decodePayReq - Decodes a payment request. * @@ -40,7 +55,7 @@ export const coinTypes = { */ export const decodePayReq = (payReq, addDefaults = true) => { const data = lightningRequestReq.decode(payReq) - const expiry = data.tags.find(t => t.tagName === 'expire_time') + const expiry = getTag(data, 'expire_time') if (addDefaults && !expiry) { data.tags.push({ tagName: 'expire_time',