From afcecd81ffa3e655558e634c71213f7a11d11a30 Mon Sep 17 00:00:00 2001 From: Sandipan Dey Date: Fri, 13 Oct 2023 07:30:30 +0530 Subject: [PATCH 1/7] chore: move nfc to receive screen --- app/app.tsx | 25 +++++----- app/config/nfc-context.tsx | 24 ++++++++++ app/navigation/root-navigator.tsx | 46 +++++++++++++------ .../receive-bitcoin-screen/receive-screen.tsx | 21 +++------ .../settings-screen/settings-screen.tsx | 12 ----- 5 files changed, 76 insertions(+), 52 deletions(-) create mode 100644 app/config/nfc-context.tsx diff --git a/app/app.tsx b/app/app.tsx index 29d45ace02..73c4568b89 100644 --- a/app/app.tsx +++ b/app/app.tsx @@ -29,6 +29,7 @@ import { ThemeSyncGraphql } from "./utils/theme-sync" import { NetworkErrorComponent } from "./graphql/network-error-component" import { FeatureFlagContextProvider } from "./config/feature-flags-context" import "./utils/logs" +import { NfcContextProvider } from "./config/nfc-context" // FIXME should we only load the currently used local? // this would help to make the app load faster @@ -47,17 +48,19 @@ export const App = () => ( - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/app/config/nfc-context.tsx b/app/config/nfc-context.tsx new file mode 100644 index 0000000000..1bde6d4473 --- /dev/null +++ b/app/config/nfc-context.tsx @@ -0,0 +1,24 @@ +import { Dispatch, SetStateAction, createContext, useState } from "react" + +type Nfc = { + displayReceiveNfc: boolean + setDisplayReceiveNfc: Dispatch> +} + +const defaultValue = { + displayReceiveNfc: false, + setDisplayReceiveNfc: () => null, +} + +export const NfcContext = createContext(defaultValue) + +export const NfcContextProvider: React.FC = ({ children }) => { + const [displayReceiveNfc, setDisplayReceiveNfc] = useState(false) + + const value = { + displayReceiveNfc, + setDisplayReceiveNfc, + } + + return {children} +} diff --git a/app/navigation/root-navigator.tsx b/app/navigation/root-navigator.tsx index bd800ca42e..c9405b9be9 100644 --- a/app/navigation/root-navigator.tsx +++ b/app/navigation/root-navigator.tsx @@ -80,21 +80,9 @@ import { RootStackParamList, } from "./stack-param-lists" import { NotificationSettingsScreen } from "@app/screens/settings-screen/notifications-screen" - -const useStyles = makeStyles(({ colors }) => ({ - bottomNavigatorStyle: { - height: "10%", - paddingTop: 4, - backgroundColor: colors.white, - borderTopColor: colors.grey4, - }, - headerStyle: { - backgroundColor: colors.white, - }, - title: { - color: colors.black, - }, -})) +import Icon from "react-native-vector-icons/Ionicons" +import { View } from "react-native" +import { NfcContext } from "@app/config/nfc-context" const RootNavigator = createStackNavigator() @@ -106,6 +94,8 @@ export const RootStack = () => { const isAuthed = useIsAuthed() const { LL } = useI18nContext() + const { setDisplayReceiveNfc } = React.useContext(NfcContext) + return ( { component={ReceiveScreen} options={{ title: LL.ReceiveScreen.title(), + headerRight: () => ( + + setDisplayReceiveNfc(true)} + /> + + ), }} /> { ) } + +const useStyles = makeStyles(({ colors }) => ({ + bottomNavigatorStyle: { + height: "10%", + paddingTop: 4, + backgroundColor: colors.white, + borderTopColor: colors.grey4, + }, + headerStyle: { + backgroundColor: colors.white, + }, + title: { + color: colors.black, + }, + rotateIconHeaderRight: { transform: [{ rotate: "90deg" }], marginRight: 10 }, +})) diff --git a/app/screens/receive-bitcoin-screen/receive-screen.tsx b/app/screens/receive-bitcoin-screen/receive-screen.tsx index fc20704e4d..965a21bb7e 100644 --- a/app/screens/receive-bitcoin-screen/receive-screen.tsx +++ b/app/screens/receive-bitcoin-screen/receive-screen.tsx @@ -4,7 +4,7 @@ import { useIsAuthed } from "@app/graphql/is-authed-context" import { useI18nContext } from "@app/i18n/i18n-react" import { requestNotificationPermission } from "@app/utils/notifications" import { useIsFocused, useNavigation } from "@react-navigation/native" -import React, { useEffect } from "react" +import React, { useContext, useEffect } from "react" import { TouchableOpacity, View } from "react-native" import { testProps } from "../../utils/testProps" import { withMyLnUpdateSub } from "./my-ln-updates-sub" @@ -18,6 +18,8 @@ import { NoteInput } from "@app/components/note-input" import Icon from "react-native-vector-icons/Ionicons" import { SetLightningAddressModal } from "@app/components/set-lightning-address-modal" import { GaloyCurrencyBubble } from "@app/components/atomic/galoy-currency-bubble" +import { ModalNfc } from "@app/components/modal-nfc" +import { NfcContext } from "@app/config/nfc-context" const ReceiveScreen = () => { const { @@ -32,6 +34,8 @@ const ReceiveScreen = () => { const request = useReceiveBitcoin() + const { displayReceiveNfc, setDisplayReceiveNfc } = useContext(NfcContext) + // notification permission useEffect(() => { let timeout: NodeJS.Timeout @@ -45,19 +49,6 @@ const ReceiveScreen = () => { return () => timeout && clearTimeout(timeout) }, [isAuthed, isFocused]) - useEffect(() => { - switch (request?.type) { - case Invoice.OnChain: - navigation.setOptions({ title: LL.ReceiveScreen.receiveViaOnchain() }) - break - case Invoice.Lightning: - navigation.setOptions({ title: LL.ReceiveScreen.receiveViaInvoice() }) - break - case Invoice.PayCode: - navigation.setOptions({ title: LL.ReceiveScreen.receiveViaPaycode() }) - } - }, [request?.type, LL.ReceiveScreen, navigation]) - useEffect(() => { if (request?.state === PaymentRequestState.Paid) { const id = setTimeout(() => navigation.goBack(), 5000) @@ -246,6 +237,8 @@ const ReceiveScreen = () => { isVisible={request.isSetLightningAddressModalVisible} toggleModal={request.toggleIsSetLightningAddressModalVisible} /> + + ) diff --git a/app/screens/settings-screen/settings-screen.tsx b/app/screens/settings-screen/settings-screen.tsx index 9ee53b63c9..3f96e6eade 100644 --- a/app/screens/settings-screen/settings-screen.tsx +++ b/app/screens/settings-screen/settings-screen.tsx @@ -13,7 +13,6 @@ import ContactModal, { import crashlytics from "@react-native-firebase/crashlytics" import { gql } from "@apollo/client" -import { ModalNfc } from "@app/components/modal-nfc" import { ratingOptions } from "@app/config" import { useSettingsScreenQuery, @@ -162,8 +161,6 @@ export const SettingsScreen: React.FC = () => { setIsSetLightningAddressModalVisible(!isSetLightningAddressModalVisible) } - const [isNFCActive, setIsNFCActive] = React.useState(false) - const rateUs = () => { Rate.rate(ratingOptions, (success, errorMessage) => { if (success) { @@ -243,14 +240,6 @@ export const SettingsScreen: React.FC = () => { enabled: isAtLeastLevelZero && Boolean(lightningAddress), greyed: !isAtLeastLevelZero || !lightningAddress, }, - { - category: `${LL.SettingsScreen.nfc()} - beta`, - icon: "radio-outline", - id: "nfc", - action: () => setIsNFCActive(true), - enabled: isAtLeastLevelZero, - greyed: !isAtLeastLevelZero, - }, { category: LL.common.language(), icon: "ios-language", @@ -370,7 +359,6 @@ export const SettingsScreen: React.FC = () => { isVisible={isSetLightningAddressModalVisible} toggleModal={toggleIsSetLightningAddressModalVisible} /> - ) } From d6630355727a60eabebbe042049a87d36f2753eb Mon Sep 17 00:00:00 2001 From: sandipndev Date: Wed, 18 Oct 2023 16:53:14 +0530 Subject: [PATCH 2/7] feat: input amount before nfc tag is read --- app/app.tsx | 25 +++++++--------- app/components/modal-nfc/modal-nfc.tsx | 30 +++++++++++++++++-- app/config/nfc-context.tsx | 24 --------------- app/i18n/en/index.ts | 1 + app/i18n/i18n-types.ts | 8 +++++ app/i18n/raw-i18n/source/en.json | 1 + app/navigation/root-navigator.tsx | 16 ---------- .../receive-bitcoin-screen/receive-screen.tsx | 29 +++++++++++++++--- 8 files changed, 74 insertions(+), 60 deletions(-) delete mode 100644 app/config/nfc-context.tsx diff --git a/app/app.tsx b/app/app.tsx index 73c4568b89..29d45ace02 100644 --- a/app/app.tsx +++ b/app/app.tsx @@ -29,7 +29,6 @@ import { ThemeSyncGraphql } from "./utils/theme-sync" import { NetworkErrorComponent } from "./graphql/network-error-component" import { FeatureFlagContextProvider } from "./config/feature-flags-context" import "./utils/logs" -import { NfcContextProvider } from "./config/nfc-context" // FIXME should we only load the currently used local? // this would help to make the app load faster @@ -48,19 +47,17 @@ export const App = () => ( - - - - - - - - - - - - - + + + + + + + + + + + diff --git a/app/components/modal-nfc/modal-nfc.tsx b/app/components/modal-nfc/modal-nfc.tsx index 7ce43837c3..6b4024ec10 100644 --- a/app/components/modal-nfc/modal-nfc.tsx +++ b/app/components/modal-nfc/modal-nfc.tsx @@ -14,17 +14,21 @@ import { StackNavigationProp } from "@react-navigation/stack" import { RootStackParamList } from "@app/navigation/stack-param-lists" import { DestinationDirection } from "@app/screens/send-bitcoin-screen/payment-destination/index.types" import { + WalletCurrency, useAccountDefaultWalletLazyQuery, useScanningQrCodeScreenQuery, } from "@app/graphql/generated" import { useIsAuthed } from "@app/graphql/is-authed-context" import { LNURL_DOMAINS } from "@app/config" import { isIOS } from "@rneui/base" +import { WalletAmount, toUsdMoneyAmount } from "@app/types/amounts" +import { usePriceConversion } from "@app/hooks" export const ModalNfc: React.FC<{ isActive: boolean setIsActive: (arg: boolean) => void -}> = ({ isActive, setIsActive }) => { + settlementAmount?: WalletAmount +}> = ({ isActive, setIsActive, settlementAmount }) => { const { data } = useScanningQrCodeScreenQuery({ skip: !useIsAuthed() }) const wallets = data?.me?.defaultAccount.wallets const bitcoinNetwork = data?.globals?.network @@ -49,11 +53,19 @@ export const ModalNfc: React.FC<{ NfcManager.cancelTechnologyRequest() }, [setIsActive]) + const { convertMoneyAmount } = usePriceConversion() + React.useEffect(() => { if (!LL || !wallets || !bitcoinNetwork || !isActive) { return } + if (isActive && !settlementAmount) { + Alert.alert(LL.ReceiveScreen.enterAmountFirst()) + setIsActive(false) + return + } + const init = async () => { let result: NdefRecord | undefined let lnurl: string @@ -122,10 +134,21 @@ export const ModalNfc: React.FC<{ }) logParseDestinationResult(destination) - if (destination.valid) { + if (destination.valid && settlementAmount && convertMoneyAmount) { if (destination.destinationDirection === DestinationDirection.Send) { Alert.alert(LL.SettingsScreen.nfcOnlyReceive()) } else { + let amount = settlementAmount.amount + if (settlementAmount.currency === WalletCurrency.Usd) { + amount = convertMoneyAmount( + toUsdMoneyAmount(settlementAmount.amount), + WalletCurrency.Btc, + ).amount + } + + destination.validDestination.minWithdrawable = amount * 1000 // coz msats + destination.validDestination.maxWithdrawable = amount * 1000 // coz msats + navigation.reset({ routes: [ { @@ -154,6 +177,9 @@ export const ModalNfc: React.FC<{ navigation, isActive, dismiss, + settlementAmount, + setIsActive, + convertMoneyAmount, ]) return ( diff --git a/app/config/nfc-context.tsx b/app/config/nfc-context.tsx deleted file mode 100644 index 1bde6d4473..0000000000 --- a/app/config/nfc-context.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { Dispatch, SetStateAction, createContext, useState } from "react" - -type Nfc = { - displayReceiveNfc: boolean - setDisplayReceiveNfc: Dispatch> -} - -const defaultValue = { - displayReceiveNfc: false, - setDisplayReceiveNfc: () => null, -} - -export const NfcContext = createContext(defaultValue) - -export const NfcContextProvider: React.FC = ({ children }) => { - const [displayReceiveNfc, setDisplayReceiveNfc] = useState(false) - - const value = { - displayReceiveNfc, - setDisplayReceiveNfc, - } - - return {children} -} diff --git a/app/i18n/en/index.ts b/app/i18n/en/index.ts index 44a5fd4a75..8256abea18 100644 --- a/app/i18n/en/index.ts +++ b/app/i18n/en/index.ts @@ -524,6 +524,7 @@ const en: BaseTranslation = { title: "Home", }, ReceiveScreen: { + enterAmountFirst: "Please enter an amount first", activateNotifications: "Do you want to activate notifications to be notified when the payment has arrived?", copyClipboard: "Invoice has been copied in the clipboard", diff --git a/app/i18n/i18n-types.ts b/app/i18n/i18n-types.ts index ed4c7db8a5..66bf4a077c 100644 --- a/app/i18n/i18n-types.ts +++ b/app/i18n/i18n-types.ts @@ -1616,6 +1616,10 @@ type RootTranslation = { title: string } ReceiveScreen: { + /** + * P​l​e​a​s​e​ ​e​n​t​e​r​ ​a​n​ ​a​m​o​u​n​t​ ​f​i​r​s​t + */ + enterAmountFirst: string /** * D​o​ ​y​o​u​ ​w​a​n​t​ ​t​o​ ​a​c​t​i​v​a​t​e​ ​n​o​t​i​f​i​c​a​t​i​o​n​s​ ​t​o​ ​b​e​ ​n​o​t​i​f​i​e​d​ ​w​h​e​n​ ​t​h​e​ ​p​a​y​m​e​n​t​ ​h​a​s​ ​a​r​r​i​v​e​d​? */ @@ -5381,6 +5385,10 @@ export type TranslationFunctions = { title: () => LocalizedString } ReceiveScreen: { + /** + * Please enter an amount first + */ + enterAmountFirst: () => LocalizedString /** * Do you want to activate notifications to be notified when the payment has arrived? */ diff --git a/app/i18n/raw-i18n/source/en.json b/app/i18n/raw-i18n/source/en.json index 20524ef5ba..00b03642d8 100644 --- a/app/i18n/raw-i18n/source/en.json +++ b/app/i18n/raw-i18n/source/en.json @@ -495,6 +495,7 @@ "title": "Home" }, "ReceiveScreen": { + "enterAmountFirst": "Please enter an amount first", "activateNotifications": "Do you want to activate notifications to be notified when the payment has arrived?", "copyClipboard": "Invoice has been copied in the clipboard", "copyClipboardBitcoin": "Bitcoin address has been copied in the clipboard", diff --git a/app/navigation/root-navigator.tsx b/app/navigation/root-navigator.tsx index c9405b9be9..b43d45ef95 100644 --- a/app/navigation/root-navigator.tsx +++ b/app/navigation/root-navigator.tsx @@ -80,9 +80,6 @@ import { RootStackParamList, } from "./stack-param-lists" import { NotificationSettingsScreen } from "@app/screens/settings-screen/notifications-screen" -import Icon from "react-native-vector-icons/Ionicons" -import { View } from "react-native" -import { NfcContext } from "@app/config/nfc-context" const RootNavigator = createStackNavigator() @@ -94,8 +91,6 @@ export const RootStack = () => { const isAuthed = useIsAuthed() const { LL } = useI18nContext() - const { setDisplayReceiveNfc } = React.useContext(NfcContext) - return ( { component={ReceiveScreen} options={{ title: LL.ReceiveScreen.title(), - headerRight: () => ( - - setDisplayReceiveNfc(true)} - /> - - ), }} /> ({ title: { color: colors.black, }, - rotateIconHeaderRight: { transform: [{ rotate: "90deg" }], marginRight: 10 }, })) diff --git a/app/screens/receive-bitcoin-screen/receive-screen.tsx b/app/screens/receive-bitcoin-screen/receive-screen.tsx index 965a21bb7e..25fabac998 100644 --- a/app/screens/receive-bitcoin-screen/receive-screen.tsx +++ b/app/screens/receive-bitcoin-screen/receive-screen.tsx @@ -4,7 +4,7 @@ import { useIsAuthed } from "@app/graphql/is-authed-context" import { useI18nContext } from "@app/i18n/i18n-react" import { requestNotificationPermission } from "@app/utils/notifications" import { useIsFocused, useNavigation } from "@react-navigation/native" -import React, { useContext, useEffect } from "react" +import React, { useEffect, useState } from "react" import { TouchableOpacity, View } from "react-native" import { testProps } from "../../utils/testProps" import { withMyLnUpdateSub } from "./my-ln-updates-sub" @@ -19,7 +19,6 @@ import Icon from "react-native-vector-icons/Ionicons" import { SetLightningAddressModal } from "@app/components/set-lightning-address-modal" import { GaloyCurrencyBubble } from "@app/components/atomic/galoy-currency-bubble" import { ModalNfc } from "@app/components/modal-nfc" -import { NfcContext } from "@app/config/nfc-context" const ReceiveScreen = () => { const { @@ -34,7 +33,20 @@ const ReceiveScreen = () => { const request = useReceiveBitcoin() - const { displayReceiveNfc, setDisplayReceiveNfc } = useContext(NfcContext) + const [displayReceiveNfc, setDisplayReceiveNfc] = useState(false) + + useEffect(() => { + navigation.setOptions({ + headerRight: () => ( + setDisplayReceiveNfc(true)} + > + + + ), + }) + }) // notification permission useEffect(() => { @@ -238,7 +250,11 @@ const ReceiveScreen = () => { toggleModal={request.toggleIsSetLightningAddressModalVisible} /> - + ) @@ -327,6 +343,11 @@ const useStyles = makeStyles(({ colors }) => ({ fontWeight: "700", }, btcLow: {}, + rotateIconHeaderRight: { + transform: [{ rotate: "90deg" }], + marginRight: 2, + padding: 8, + }, })) export default withMyLnUpdateSub(ReceiveScreen) From 816fcaa0929bedd49efe3c81aa73a12071444ea2 Mon Sep 17 00:00:00 2001 From: sandipndev Date: Wed, 18 Oct 2023 17:02:30 +0530 Subject: [PATCH 3/7] test: added mock to receive bitcoin --- __tests__/screens/receive.spec.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/__tests__/screens/receive.spec.tsx b/__tests__/screens/receive.spec.tsx index 118474a726..2e1d579671 100644 --- a/__tests__/screens/receive.spec.tsx +++ b/__tests__/screens/receive.spec.tsx @@ -4,6 +4,15 @@ import { act, render } from "@testing-library/react-native" import { ContextForScreen } from "./helper" import ReceiveScreen from "@app/screens/receive-bitcoin-screen/receive-screen" +jest.mock("react-native-nfc-manager", () => { + return { + NfcManager: { + start: jest.fn(), + stop: jest.fn(), + }, + } +}) + it("Receive", async () => { render( From aa2511931b3b248e6d92261886ccc9fcd2807ed0 Mon Sep 17 00:00:00 2001 From: sandipndev Date: Wed, 18 Oct 2023 21:34:03 +0530 Subject: [PATCH 4/7] fix: remove lnrul withdraw intermediary page --- app/components/modal-nfc/modal-nfc.tsx | 58 ++++++++++--------- .../receive-bitcoin-screen/receive-screen.tsx | 1 + .../use-receive-bitcoin.ts | 53 +++++++++++++++++ 3 files changed, 84 insertions(+), 28 deletions(-) diff --git a/app/components/modal-nfc/modal-nfc.tsx b/app/components/modal-nfc/modal-nfc.tsx index 6b4024ec10..f2d2313145 100644 --- a/app/components/modal-nfc/modal-nfc.tsx +++ b/app/components/modal-nfc/modal-nfc.tsx @@ -9,10 +9,10 @@ import Icon from "react-native-vector-icons/Ionicons" import { GaloySecondaryButton } from "../atomic/galoy-secondary-button" import { parseDestination } from "@app/screens/send-bitcoin-screen/payment-destination" import { logParseDestinationResult } from "@app/utils/analytics" -import { useNavigation } from "@react-navigation/native" -import { StackNavigationProp } from "@react-navigation/stack" -import { RootStackParamList } from "@app/navigation/stack-param-lists" -import { DestinationDirection } from "@app/screens/send-bitcoin-screen/payment-destination/index.types" +import { + DestinationDirection, + ReceiveDestination, +} from "@app/screens/send-bitcoin-screen/payment-destination/index.types" import { WalletCurrency, useAccountDefaultWalletLazyQuery, @@ -21,14 +21,23 @@ import { import { useIsAuthed } from "@app/graphql/is-authed-context" import { LNURL_DOMAINS } from "@app/config" import { isIOS } from "@rneui/base" -import { WalletAmount, toUsdMoneyAmount } from "@app/types/amounts" +import { + MoneyAmount, + WalletAmount, + toBtcMoneyAmount, + toUsdMoneyAmount, +} from "@app/types/amounts" import { usePriceConversion } from "@app/hooks" export const ModalNfc: React.FC<{ isActive: boolean setIsActive: (arg: boolean) => void settlementAmount?: WalletAmount -}> = ({ isActive, setIsActive, settlementAmount }) => { + receiveViaNFC: ( + destination: ReceiveDestination, + settlementAmount: MoneyAmount<"BTC">, + ) => Promise +}> = ({ isActive, setIsActive, settlementAmount, receiveViaNFC }) => { const { data } = useScanningQrCodeScreenQuery({ skip: !useIsAuthed() }) const wallets = data?.me?.defaultAccount.wallets const bitcoinNetwork = data?.globals?.network @@ -37,10 +46,6 @@ export const ModalNfc: React.FC<{ fetchPolicy: "no-cache", }) - // FIXME: navigation destination? - const navigation = - useNavigation>() - const styles = useStyles() const { theme: { colors }, @@ -56,16 +61,23 @@ export const ModalNfc: React.FC<{ const { convertMoneyAmount } = usePriceConversion() React.useEffect(() => { - if (!LL || !wallets || !bitcoinNetwork || !isActive) { - return - } - if (isActive && !settlementAmount) { Alert.alert(LL.ReceiveScreen.enterAmountFirst()) setIsActive(false) return } + if ( + !LL || + !wallets || + !bitcoinNetwork || + !isActive || + !receiveViaNFC || + !settlementAmount + ) { + return + } + const init = async () => { let result: NdefRecord | undefined let lnurl: string @@ -149,19 +161,9 @@ export const ModalNfc: React.FC<{ destination.validDestination.minWithdrawable = amount * 1000 // coz msats destination.validDestination.maxWithdrawable = amount * 1000 // coz msats - navigation.reset({ - routes: [ - { - name: "Primary", - }, - { - name: "redeemBitcoinDetail", - params: { - receiveDestination: destination, - }, - }, - ], - }) + console.log(destination) + + receiveViaNFC(destination, toBtcMoneyAmount(settlementAmount.amount)) } } @@ -169,12 +171,12 @@ export const ModalNfc: React.FC<{ } init() + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ LL, wallets, bitcoinNetwork, accountDefaultWalletQuery, - navigation, isActive, dismiss, settlementAmount, diff --git a/app/screens/receive-bitcoin-screen/receive-screen.tsx b/app/screens/receive-bitcoin-screen/receive-screen.tsx index 25fabac998..5e0563a036 100644 --- a/app/screens/receive-bitcoin-screen/receive-screen.tsx +++ b/app/screens/receive-bitcoin-screen/receive-screen.tsx @@ -254,6 +254,7 @@ const ReceiveScreen = () => { isActive={displayReceiveNfc} setIsActive={setDisplayReceiveNfc} settlementAmount={request.settlementAmount} + receiveViaNFC={request.receiveViaNFC} /> diff --git a/app/screens/receive-bitcoin-screen/use-receive-bitcoin.ts b/app/screens/receive-bitcoin-screen/use-receive-bitcoin.ts index 0c2ec3ee54..cc387784ab 100644 --- a/app/screens/receive-bitcoin-screen/use-receive-bitcoin.ts +++ b/app/screens/receive-bitcoin-screen/use-receive-bitcoin.ts @@ -29,11 +29,13 @@ import { useLnUpdateHashPaid } from "@app/graphql/ln-update-context" import { generateFutureLocalTime, secondsToH, secondsToHMS } from "./payment/helpers" import { toastShow } from "@app/utils/toast" import { useI18nContext } from "@app/i18n/i18n-react" +import fetch from "cross-fetch" import crashlytics from "@react-native-firebase/crashlytics" import { Alert, Share } from "react-native" import { TranslationFunctions } from "@app/i18n/i18n-types" import { BtcWalletDescriptor } from "@app/types/wallets" +import { ReceiveDestination } from "../send-bitcoin-screen/payment-destination/index.types" gql` query paymentRequest { @@ -455,6 +457,56 @@ 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) { + throw new Error("No data returned from lnInvoiceCreate") + } + + 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, @@ -472,5 +524,6 @@ export const useReceiveBitcoin = () => { isSetLightningAddressModalVisible, toggleIsSetLightningAddressModalVisible, readablePaymentRequest, + receiveViaNFC, } } From 1bf7fb4613b10fc11fc8434f677e69c302718c5f Mon Sep 17 00:00:00 2001 From: sandipndev Date: Thu, 19 Oct 2023 13:38:48 +0530 Subject: [PATCH 5/7] chode: dev codegen --- app/graphql/generated.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/graphql/generated.ts b/app/graphql/generated.ts index 03961a6c4a..fc4aa11b63 100644 --- a/app/graphql/generated.ts +++ b/app/graphql/generated.ts @@ -1262,8 +1262,6 @@ export type Query = { readonly __typename: 'Query'; readonly accountDefaultWallet: PublicWallet; readonly beta: Scalars['Boolean']['output']; - /** @deprecated Deprecated in favor of realtimePrice */ - readonly btcPrice?: Maybe; readonly btcPriceList?: Maybe>>; readonly businessMapMarkers?: Maybe>>; readonly colorScheme: Scalars['String']['output']; @@ -1299,11 +1297,6 @@ export type QueryAccountDefaultWalletArgs = { }; -export type QueryBtcPriceArgs = { - currency?: Scalars['DisplayCurrency']['input']; -}; - - export type QueryBtcPriceListArgs = { range: PriceGraphRange; }; @@ -7619,7 +7612,6 @@ export type PublicWalletResolvers = { accountDefaultWallet?: Resolver>; beta?: Resolver; - btcPrice?: Resolver, ParentType, ContextType, RequireFields>; btcPriceList?: Resolver>>, ParentType, ContextType, RequireFields>; businessMapMarkers?: Resolver>>, ParentType, ContextType>; colorScheme?: Resolver; From df747e0b2e5f0ff26f8b09a003dddbb9948c5c62 Mon Sep 17 00:00:00 2001 From: sandipndev Date: Fri, 20 Oct 2023 01:15:20 +0530 Subject: [PATCH 6/7] chore: comment on exhaustive deps --- app/components/modal-nfc/modal-nfc.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/modal-nfc/modal-nfc.tsx b/app/components/modal-nfc/modal-nfc.tsx index f2d2313145..f4efb61204 100644 --- a/app/components/modal-nfc/modal-nfc.tsx +++ b/app/components/modal-nfc/modal-nfc.tsx @@ -161,8 +161,6 @@ export const ModalNfc: React.FC<{ destination.validDestination.minWithdrawable = amount * 1000 // coz msats destination.validDestination.maxWithdrawable = amount * 1000 // coz msats - console.log(destination) - receiveViaNFC(destination, toBtcMoneyAmount(settlementAmount.amount)) } } @@ -171,6 +169,8 @@ export const ModalNfc: React.FC<{ } init() + // Necessary because receiveViaNFC gets rerendered at useReceiveBitcoin + // And rerendering that shouldn't cause this useEffect to retrigger // eslint-disable-next-line react-hooks/exhaustive-deps }, [ LL, From 51627c74e6be5231e503d793f1040b09dabdf6be Mon Sep 17 00:00:00 2001 From: sandipndev Date: Fri, 20 Oct 2023 01:16:52 +0530 Subject: [PATCH 7/7] fix: dont throw error --- app/screens/receive-bitcoin-screen/use-receive-bitcoin.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/screens/receive-bitcoin-screen/use-receive-bitcoin.ts b/app/screens/receive-bitcoin-screen/use-receive-bitcoin.ts index cc387784ab..1d2a52ad2b 100644 --- a/app/screens/receive-bitcoin-screen/use-receive-bitcoin.ts +++ b/app/screens/receive-bitcoin-screen/use-receive-bitcoin.ts @@ -473,7 +473,8 @@ export const useReceiveBitcoin = () => { }) if (!data) { - throw new Error("No data returned from lnInvoiceCreate") + Alert.alert(LL.RedeemBitcoinScreen.error()) + return } const {