Skip to content

Commit

Permalink
feat: username validation (GaloyMoney#618)
Browse files Browse the repository at this point in the history
  • Loading branch information
UncleSamtoshi authored Sep 13, 2022
1 parent 5b291dc commit 8067b26
Show file tree
Hide file tree
Showing 19 changed files with 1,368 additions and 159 deletions.
1 change: 1 addition & 0 deletions __tests__/screens/global-error.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jest.mock("@react-native-community/push-notification-ios", () => ({}))
jest.mock("react-native-walkthrough-tooltip", () => ({}))
jest.mock("react-native-fingerprint-scanner", () => ({}))
jest.mock("react-native-snap-carousel", () => ({}))
jest.mock("react-native-markdown-display", () => ({}))
jest.mock("react-native-maps", () => ({}))
jest.mock("react-native-phone-number-input", () => ({}))
jest.mock("victory-native", () => ({}))
Expand Down
87 changes: 87 additions & 0 deletions app/components/floor-tooltip/floor-tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { useI18nContext } from "@app/i18n/i18n-react"
import { bankName } from "@app/screens/send-bitcoin-screen/send-bitcoin-destination-screen"
import { palette } from "@app/theme"
import * as React from "react"
import { Text, View, TouchableOpacity, ScrollView } from "react-native"
import { Icon } from "react-native-elements"
import EStyleSheet from "react-native-extended-stylesheet"
import Markdown from "react-native-markdown-display"
import Modal from "react-native-modal"

const styles = EStyleSheet.create({
modalStyle: { margin: 0, flexDirection: "column", justifyContent: "flex-end" },
fillerOpacity: { flex: 3 },
modalCard: {
backgroundColor: palette.white,
flex: 2,
borderTopLeftRadius: 40,
borderTopRightRadius: 40,
padding: 24,
},
modalTitleContainer: { flexDirection: "row", alignItems: "center", marginBottom: 10 },
modalTitleText: { fontSize: 24 },
iconContainer: { marginRight: 12 },
markdownText: { fontSize: 20, marginBottom: 20 },
})

type FloorTooltipProps = {
size?: number
type: "info" | "advice"
title?: string
text: string
}

export const FloorTooltip: React.FC<FloorTooltipProps> = ({
size,
type,
title,
text,
}) => {
const { LL } = useI18nContext()
const [isVisible, setIsVisible] = React.useState(false)
const toggleModal = () => setIsVisible(!isVisible)

let iconParams
let defaultTitle
switch (type) {
case "info":
iconParams = {
name: "info",
type: "fontisto",
}
defaultTitle = LL.common.bankInfo({ bankName })
break
case "advice":
iconParams = {
name: "lightbulb",
type: "foundation",
}
defaultTitle = LL.common.bankAdvice({ bankName })
break
}
const modalTitle = title || defaultTitle

return (
<View>
<Icon raised {...(size ? { size } : {})} {...iconParams} onPress={toggleModal} />
<Modal
isVisible={isVisible}
onBackdropPress={() => toggleModal}
coverScreen
style={styles.modalStyle}
backdropOpacity={0.2}
>
<TouchableOpacity style={styles.fillerOpacity} onPress={toggleModal} />
<View style={styles.modalCard}>
<View style={styles.modalTitleContainer}>
<Icon size={24} {...iconParams} containerStyle={styles.iconContainer} />
<Text style={styles.modalTitleText}>{modalTitle}</Text>
</View>
<ScrollView>
<Markdown style={{ body: styles.markdownText }}>{text}</Markdown>
</ScrollView>
</View>
</Modal>
</View>
)
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { lnDomain } from "@app/screens/send-bitcoin-screen/send-bitcoin-destination-screen"
import { palette } from "@app/theme"
import React from "react"
import { ActivityIndicator, Text } from "react-native"
Expand All @@ -11,15 +12,24 @@ const styles = EStyleSheet.create({
},
})

export const PaymentDestinationDisplay = ({ destination }: { destination?: string }) => {
export const PaymentDestinationDisplay = ({
destination,
paymentType,
}: {
destination?: string
paymentType?: string
}) => {
if (!destination) {
return <ActivityIndicator />
}

if (destination.length < 40) {
return (
<Text numberOfLines={1} ellipsizeMode={"middle"}>
<Text>{destination}</Text>
<Text>
{destination}
{paymentType === "intraledger" ? `@${lnDomain}` : ""}
</Text>
</Text>
)
}
Expand Down
1 change: 1 addition & 0 deletions app/hooks/use-app-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const useAppConfig = () => {
...state,
isUsdDisabled: !state.isUsdDisabled,
}))
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [persistentStateContext.updateState])

return { appConfig, toggleUsdDisabled }
Expand Down
30 changes: 27 additions & 3 deletions app/i18n/en/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,31 @@ const en: BaseTranslation = {
"This is the maximum fee you will be charged for this transaction. It may end up being less once the payment has been made.",
feeError: "Failed to calculate fee",
},
SendBitcoinDestinationScreen: {
usernameNowAddress: "{bankName: string} usernames are now {bankName: string} addresses.",
usernameNowAddressInfo: "When you enter a {bankName: string} username, we will add \"@{lnDomain: string}\" to it (e.g maria@{lnDomain: string}) to make it an address. Your username is now a {bankName: string} address too.\n\nGo to your {bankName: string} address page from your Settings to learn how to use it or to share it to receive payments.",
enterValidDestination: "Please enter a valid destination",
destinationOptions: "You can send to a {bankName: string} address, LN address, LN invoice, or BTC address.",
expiredInvoice: "This invoice has expired. Please generate a new invoice.",
wrongNetwork: "This invoice is for a different network. Please generate a new invoice.",
invalidAmount: "This contains an invalid amount. Please regenerate with a valid amount.",
usernameDoesNotExist: "{lnAddress: string} doesn't seem to be a {bankName: string} address that exists.",
usernameDoesNotExistAdvice: "Either make sure the spelling is right or ask the recipient for an LN invoice or BTC address instead.",
selfPaymentError: "{lnAddress: string} is your {bankName: string} address.",
selfPaymentAdvice: "If you want to send money to another account that you own, you can use an invoice, LN or BTC address instead.",
lnAddressError: "We can't reach this Lightning address. If you are sure it exists, you can try again later.",
lnAddressAdvice: "Either make sure the spelling is right or ask the recipient for an invoice or BTC address instead.",
unknownLightning: "We can't parse this Lightning address. Please try again.",
unknownOnchain: "We can't parse this Bitcoin address. Please try again.",
newBankAddressUsername: "{lnAddress: string} exists as a {bankName: string} address, but you've never sent money to it.",
confirmModal: {
title: "You've never sent money to \"{lnAddress: string}\" before.",
body: "Please make sure the recipient gave you a {bankName: string} address, **not a username from another wallet**. Otherwise, the money will go to a {bankName: string} Account that has the “{lnAddress: string}” address.\n\nCheck the spelling of the first part of the address as well. e.g. jackie and jack1e are 2 different addresses",
warning: "If the {bankName: string} address is entered incorrectly, {bankName: string} can't undo the transaction.",
checkBox: "{lnAddress: string} is the right address.",
confirmButton: "I'm 100% sure",
}
},
SendBitcoinScreen: {
amount: "Amount",
amountExceed: "Amount exceeds your balance of {balance: string}",
Expand All @@ -571,10 +596,7 @@ const en: BaseTranslation = {
note: "Note or label",
success: "Payment has been sent successfully",
title: "Send Bitcoin",
usernameNotFound: "A user matching the entered username could not be found.",
failedToFetchLnurlParams: "Failed to fetch lnurl params",
failedToFetchLnurlInvoice: "Failed to fetch lnurl invoice",
youCantSendAPaymentToYourself: "You can't send a payment to yourself",
},
SettingsScreen: {
activated: "Activated",
Expand Down Expand Up @@ -666,6 +688,8 @@ const en: BaseTranslation = {
backHome: "Back home",
bank: "Bank",
bankAccount: "Cash Account",
bankAdvice: "{bankName: string} Advice",
bankInfo: "{bankName: string} Info",
bitcoin: "Bitcoin",
bitcoinPrice: "Bitcoin Price",
btcAccount: "BTC Account",
Expand Down
32 changes: 29 additions & 3 deletions app/i18n/es/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -594,10 +594,32 @@ const es: Translation = {
note: "Nota",
success: "El pago se ha enviado correctamente.",
title: "Enviar Bitcoin",
usernameNotFound: "El usuario no fue encontrado.",
failedToFetchLnurlParams: "No se pudieron recuperar los parámetros de lnurl",
failedToFetchLnurlInvoice: "Error al obtener la factura de lnurl",
youCantSendAPaymentToYourself: "No puedes enviar un pago a ti mismo",
},
SendBitcoinDestinationScreen: {
usernameNowAddress: "Los nombres de usuario de {bankName} ahora son direcciones de {bankName}.",
usernameNowAddressInfo: "Cuando ingrese un nombre de usuario de {bankName}, le agregaremos \"@{lnDomain}\" (por ejemplo, maria@{lnDomain}) para convertirlo en una dirección. Tu nombre de usuario ahora también es una dirección de {bankName}.\n\nLos nombres de usuario de {bankName} solo permitían transacciones dentro de {bankName}, mientras que las direcciones de {bankName} permiten realizar pagos con personas que usan diferentes billeteras.",
enterValidDestination: "Introduzca un destino válido.",
destinationOptions: "Puedes enviar a una dirección {bankName}, una dirección LN, una factura LN o una dirección {bankName}.",
expiredInvoice: "Esta factura ha caducado. Por favor, genere una nueva factura.",
wrongNetwork: "Esta factura es para una red diferente. Por favor, genere una nueva factura.",
invalidAmount: "Esto contiene un monto inválido. Por favor, ingrese nuevamente con un monto válido.",
usernameDoesNotExist: "{lnAddress} no parece ser una dirección de {bankName} que exista.",
usernameDoesNotExistAdvice: "En su lugar, puede pedirle al destinatario una factura o una dirección BTC.",
selfPaymentError: "{lnAddress} es su dirección de {bankName}.",
selfPaymentAdvice: "Si desea enviar dinero a otra billetera de su propiedad, puede usar una factura, una dirección LN o BTC en su lugar.",
lnAddressError: "No podemos comunicarnos con esta dirección Lightning. Si está seguro de que existe, puede volver a intentarlo más tarde.",
lnAddressAdvice: "En su lugar, puede pedirle al destinatario una factura o una dirección BTC.",
unknownLightning: "No podemos verificar esta dirección Lightning. Por favor, inténtalo de nuevo con una dirección diferente.",
unknownOnchain: "No podemos verificar esta dirección Bitcoin. Por favor, inténtelo de nuevo con una dirección diferente.",
newBankAddressUsername: "{lnAddress} existe como dirección de {bankName}, pero nunca has enviado dinero a esta dirección.",
confirmModal: {
title: "Nunca antes ha enviado dinero a \"{lnAddress}\".",
body: "Asegúrate que tu destinatario te haya dado una dirección de {bankName}, **no un nombre de usuario de otra billetera**. De lo contrario, el dinero irá a una {bankName} que tenga la dirección “{lnAddress}”.\n\nRevisa también la ortografía de la primera parte de la dirección por ejemplo: “jackie” y “jack1e” ya que son 2 direcciones diferentes.",
warning: "Si la dirección de {bankName} se ingresa incorrectamente, {bankName} no puede deshacer la transacción.",
checkBox: "{lnAddress} si es la dirección correcta.",
confirmButton: "Estoy 100% seguro",
}
},
SettingsScreen: {
activated: "Activada",
Expand Down Expand Up @@ -691,6 +713,10 @@ const es: Translation = {
bank: "Banco",
backHome: "Atrás",
bankAccount: "Cuenta de efectivo",
// TO DO: Translate
bankAdvice: "{bankName} Tip",
// TO DO: Translate
bankInfo: "{bankName} Info",
bitcoin: "Bitcoin",
bitcoinPrice: "Precio de Bitcoin",
btcAccount: "Cuenta BTC",
Expand Down
33 changes: 30 additions & 3 deletions app/i18n/fr-CA/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,32 @@ const frCA: Translation = {
"Il s'agit des frais maximum qui vous seront facturés pour cette transaction. Il peut finir par être inférieur une fois le paiement effectué.",
feeError: "Échec du calcul des frais",
},
// TODO translate the below section
SendBitcoinDestinationScreen: {
usernameNowAddress: "{bankName} usernames are now {bankName} addresses.",
usernameNowAddressInfo: "When you enter a {bankName} username, we will add “@{lnDomain}” to it (e.g maria@{lnDomain}) to make it an address. Your username is now a {bankName} address too.\n\nGo to your {bankName} address page from your Settings to learn how to use it or to share it to receive payments.",
enterValidDestination: "Please enter a valid destination",
destinationOptions: "You can send to a {bankName} address, LN address, LN invoice, or BTC address.",
expiredInvoice: "This invoice has expired. Please generate a new invoice.",
wrongNetwork: "This invoice is for a different network. Please generate a new invoice.",
invalidAmount: "This contains an invalid amount. Please regenerate with a valid amount.",
usernameDoesNotExist: "{lnAddress} doesn't seem to be a {bankName} address that exists.",
usernameDoesNotExistAdvice: "Either make sure the spelling is right or ask the recipient for an LN invoice or BTC address instead.",
selfPaymentError: "{lnAddress} is your {bankName} address.",
selfPaymentAdvice: "If you want to send money to another account that you own, you can use an invoice, LN or BTC address instead.",
lnAddressError: "We can't reach this Lightning address. If you are sure it exists, you can try again later.",
lnAddressAdvice: "Either make sure the spelling is right or ask the recipient for an invoice or BTC address instead.",
unknownLightning: "We can't parse this Lightning address. Please try again.",
unknownOnchain: "We can't parse this Bitcoin address. Please try again.",
newBankAddressUsername: "{lnAddress} exists as a {bankName} address, but you've never sent money to it.",
confirmModal: {
title: "You've never sent money to \"{lnAddress}\" before.",
body: "Please make sure the recipient gave you a {bankName} address, **not a username from another wallet**. Otherwise, the money will go to a {bankName} Account that has the “{lnAddress}” address.\n\nCheck the spelling of the first part of the address as well. e.g. jackie and jack1e are 2 different addresses",
warning: "If the {bankName} address is entered incorrectly, {bankName} can't undo the transaction.",
checkBox: "{lnAddress} is the right address.",
confirmButton: "I'm 100% sure",
}
},
SendBitcoinScreen: {
amount: "Montant",
amountExceed: "Le montant excède votre solde de {balance}",
Expand All @@ -582,10 +608,7 @@ const frCA: Translation = {
note: "note optionnelle",
success: "Le paiement a été envoyé avec succès",
title: "Envoyer des bitcoins",
usernameNotFound: "Un usager correspondant au nom saisi est introuvable.",
failedToFetchLnurlParams: "Impossible de récupérer les paramètres lnurl",
failedToFetchLnurlInvoice: "Échec de la récupération de la facture lnurl",
youCantSendAPaymentToYourself: "Vous ne pouvez pas envoyer de paiement à vous-même",
},
SettingsScreen: {
activated: "Activé",
Expand Down Expand Up @@ -680,6 +703,10 @@ const frCA: Translation = {
bankAccount: "Compte comptant",
bitcoin: "Bitcoin",
bitcoinPrice: "Prix Bitcoin",
// TO DO: Translate
bankAdvice: "{bankName} Advice",
// TO DO: Translate
bankInfo: "{bankName} Info",
cancel: "Annuler",
close: "Fermer",
confirm: "Confirmer",
Expand Down
Loading

0 comments on commit 8067b26

Please sign in to comment.