Skip to content

Commit

Permalink
fix: use same invoice for NFC (#2728)
Browse files Browse the repository at this point in the history
  • Loading branch information
sandipndev authored Oct 27, 2023
1 parent 5162cf0 commit b063518
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 75 deletions.
28 changes: 17 additions & 11 deletions app/components/modal-nfc/modal-nfc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,14 @@ import {
import { useIsAuthed } from "@app/graphql/is-authed-context"
import { LNURL_DOMAINS } from "@app/config"
import { isIOS } from "@rneui/base"
import {
MoneyAmount,
WalletAmount,
toBtcMoneyAmount,
toUsdMoneyAmount,
} from "@app/types/amounts"
import { WalletAmount, toUsdMoneyAmount } from "@app/types/amounts"
import { usePriceConversion } from "@app/hooks"

export const ModalNfc: React.FC<{
isActive: boolean
setIsActive: (arg: boolean) => void
settlementAmount?: WalletAmount<WalletCurrency>
receiveViaNFC: (
destination: ReceiveDestination,
settlementAmount: MoneyAmount<"BTC">,
) => Promise<void>
receiveViaNFC: (destination: ReceiveDestination) => Promise<void>
}> = ({ isActive, setIsActive, settlementAmount, receiveViaNFC }) => {
const { data } = useScanningQrCodeScreenQuery({ skip: !useIsAuthed() })
const wallets = data?.me?.defaultAccount.wallets
Expand Down Expand Up @@ -67,6 +59,20 @@ export const ModalNfc: React.FC<{
return
}

if (!convertMoneyAmount) return

if (
isActive &&
settlementAmount &&
convertMoneyAmount &&
convertMoneyAmount(toUsdMoneyAmount(settlementAmount?.amount), WalletCurrency.Btc)
.amount === 0
) {
Alert.alert(LL.ReceiveScreen.cantReceiveZeroSats())
setIsActive(false)
return
}

if (
!LL ||
!wallets ||
Expand Down Expand Up @@ -161,7 +167,7 @@ export const ModalNfc: React.FC<{
destination.validDestination.minWithdrawable = amount * 1000 // coz msats
destination.validDestination.maxWithdrawable = amount * 1000 // coz msats

receiveViaNFC(destination, toBtcMoneyAmount(settlementAmount.amount))
receiveViaNFC(destination)
}
}

Expand Down
1 change: 1 addition & 0 deletions app/i18n/en/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2133,6 +2133,7 @@ const en: BaseTranslation = {
receiveViaPaycode: "Receive via Paycode",
receiveViaOnchain: "Receive via Onchain",
payCodeOrLNURL: "Paycode / LNURL",
cantReceiveZeroSats: "You can't receive zero sats. Please enter an amount corresponding to 1 or more sats."
},
RedeemBitcoinScreen: {
title: "Redeem Bitcoin",
Expand Down
8 changes: 8 additions & 0 deletions app/i18n/i18n-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6651,6 +6651,10 @@ type RootTranslation = {
* P​a​y​c​o​d​e​ ​/​ ​L​N​U​R​L
*/
payCodeOrLNURL: string
/**
* Y​o​u​ ​c​a​n​'​t​ ​r​e​c​e​i​v​e​ ​z​e​r​o​ ​s​a​t​s​.​ ​P​l​e​a​s​e​ ​e​n​t​e​r​ ​a​n​ ​a​m​o​u​n​t​ ​c​o​r​r​e​s​p​o​n​d​i​n​g​ ​t​o​ ​1​ ​o​r​ ​m​o​r​e​ ​s​a​t​s​.
*/
cantReceiveZeroSats: string
}
RedeemBitcoinScreen: {
/**
Expand Down Expand Up @@ -15346,6 +15350,10 @@ export type TranslationFunctions = {
* Paycode / LNURL
*/
payCodeOrLNURL: () => LocalizedString
/**
* You can't receive zero sats. Please enter an amount corresponding to 1 or more sats.
*/
cantReceiveZeroSats: () => LocalizedString
}
RedeemBitcoinScreen: {
/**
Expand Down
3 changes: 2 additions & 1 deletion app/i18n/raw-i18n/source/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2100,7 +2100,8 @@
"receiveViaInvoice": "Receive via Lightning",
"receiveViaPaycode": "Receive via Paycode",
"receiveViaOnchain": "Receive via Onchain",
"payCodeOrLNURL": "Paycode / LNURL"
"payCodeOrLNURL": "Paycode / LNURL",
"cantReceiveZeroSats": "You can't receive zero sats. Please enter an amount corresponding to 1 or more sats."
},
"RedeemBitcoinScreen": {
"title": "Redeem Bitcoin",
Expand Down
32 changes: 21 additions & 11 deletions app/screens/receive-bitcoin-screen/receive-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,27 @@ const ReceiveScreen = () => {
const [displayReceiveNfc, setDisplayReceiveNfc] = useState(false)

useEffect(() => {
navigation.setOptions({
headerRight: () => (
<TouchableOpacity
style={styles.rotateIconHeaderRight}
onPress={() => setDisplayReceiveNfc(true)}
>
<Icon name="wifi" color={colors.black} size={25} />
</TouchableOpacity>
),
})
})
if (request?.type === "Lightning" && request.state === "Created")
navigation.setOptions({
headerRight: () => (
<TouchableOpacity
style={styles.rotateIconHeaderRight}
onPress={() => setDisplayReceiveNfc(true)}
>
<Icon name="wifi" color={colors.black} size={25} />
</TouchableOpacity>
),
})
else {
navigation.setOptions({ headerRight: () => <></> })
}
}, [
colors.black,
navigation,
request?.state,
request?.type,
styles.rotateIconHeaderRight,
])

// notification permission
useEffect(() => {
Expand Down
85 changes: 33 additions & 52 deletions app/screens/receive-bitcoin-screen/use-receive-bitcoin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useLayoutEffect, useMemo, useState } from "react"
import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from "react"
import {
BaseCreatePaymentRequestCreationDataParams,
Invoice,
Expand Down Expand Up @@ -30,6 +30,7 @@ import { generateFutureLocalTime, secondsToH, secondsToHMS } from "./payment/hel
import { toastShow } from "@app/utils/toast"
import { useI18nContext } from "@app/i18n/i18n-react"
import fetch from "cross-fetch"
import ReactNativeHapticFeedback from "react-native-haptic-feedback"

import crashlytics from "@react-native-firebase/crashlytics"
import { Alert, Share } from "react-native"
Expand Down Expand Up @@ -265,6 +266,9 @@ export const useReceiveBitcoin = () => {
lastHash === pr.info.data.paymentHash
) {
setPR((pq) => pq && pq.setState(PaymentRequestState.Paid))
ReactNativeHapticFeedback.trigger("notificationSuccess", {
ignoreAndroidSystemSettings: true,
})
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [lastHash])
Expand Down Expand Up @@ -369,6 +373,34 @@ export const useReceiveBitcoin = () => {
}
}, [pr, LL])

const receiveViaNFC = useCallback(
async (destination: ReceiveDestination) => {
if (pr?.info?.data?.invoiceType !== "Lightning" || !pr.info.data.paymentRequest) {
Alert.alert(LL.RedeemBitcoinScreen.error())
return
}

const { callback, k1 } = destination.validDestination

const url = `${callback}${callback.includes("?") ? "&" : "?"}k1=${k1}&pr=${
pr.info.data.paymentRequest
}`

const result = await fetch(url)
if (result.ok) {
const lnurlResponse = await result.json()
if (lnurlResponse?.status?.toLowerCase() !== "ok") {
console.error(lnurlResponse, "error with redeeming")
Alert.alert(LL.RedeemBitcoinScreen.redeemingError(), lnurlResponse.reason)
}
} else {
console.error(result.text(), "error with submitting withdrawalRequest")
Alert.alert(LL.RedeemBitcoinScreen.submissionError())
}
},
[LL.RedeemBitcoinScreen, pr],
)

if (!prcd) return null

const setType = (type: InvoiceType) => {
Expand Down Expand Up @@ -460,57 +492,6 @@ export const useReceiveBitcoin = () => {
readablePaymentRequest = `${pr.info.data.username}@${lnAddressHostname}`
}

const receiveViaNFC = async (
destination: ReceiveDestination,
settlementAmount: MoneyAmount<"BTC">,
) => {
const { callback, defaultDescription, k1 } = destination.validDestination
const { data } = await lnInvoiceCreate({
variables: {
input: {
walletId: prcd.receivingWalletDescriptor.id,
amount: settlementAmount.amount,
memo: prcd.memo || defaultDescription,
},
},
})

if (!data) {
Alert.alert(LL.RedeemBitcoinScreen.error())
return
}

const {
lnInvoiceCreate: { invoice, errors },
} = data

if ((errors && errors.length !== 0) || !invoice) {
console.error(errors, "error with lnInvoiceCreate")
Alert.alert(LL.RedeemBitcoinScreen.error())
return
}

const url = `${callback}${callback.includes("?") ? "&" : "?"}k1=${k1}&pr=${
invoice.paymentRequest
}`

const result = await fetch(url)

if (result.ok) {
const lnurlResponse = await result.json()
if (lnurlResponse?.status?.toLowerCase() !== "ok") {
console.error(lnurlResponse, "error with redeeming")
Alert.alert(LL.RedeemBitcoinScreen.redeemingError())
if (lnurlResponse?.reason) {
Alert.alert(lnurlResponse.reason)
}
}
} else {
console.error(result.text(), "error with submitting withdrawalRequest")
Alert.alert(LL.RedeemBitcoinScreen.submissionError())
}
}

return {
...prcd,
setType,
Expand Down

0 comments on commit b063518

Please sign in to comment.