diff --git a/app/assets/social_logos/aqua.png b/app/assets/social_logos/aqua.png
new file mode 100644
index 00000000..b70f2f0a
Binary files /dev/null and b/app/assets/social_logos/aqua.png differ
diff --git a/app/assets/social_logos/blink.png b/app/assets/social_logos/blink.png
new file mode 100644
index 00000000..86ebb2dc
Binary files /dev/null and b/app/assets/social_logos/blink.png differ
diff --git a/app/assets/social_logos/breez.png b/app/assets/social_logos/breez.png
new file mode 100644
index 00000000..01b7f779
Binary files /dev/null and b/app/assets/social_logos/breez.png differ
diff --git a/app/assets/social_logos/cake.png b/app/assets/social_logos/cake.png
new file mode 100644
index 00000000..70844cdf
Binary files /dev/null and b/app/assets/social_logos/cake.png differ
diff --git a/app/assets/social_logos/coinos.png b/app/assets/social_logos/coinos.png
new file mode 100644
index 00000000..4e742261
Binary files /dev/null and b/app/assets/social_logos/coinos.png differ
diff --git a/app/assets/social_logos/manna.png b/app/assets/social_logos/manna.png
new file mode 100644
index 00000000..e817e733
Binary files /dev/null and b/app/assets/social_logos/manna.png differ
diff --git a/app/assets/social_logos/orangePillApp.png b/app/assets/social_logos/orangePillApp.png
new file mode 100644
index 00000000..53c082c5
Binary files /dev/null and b/app/assets/social_logos/orangePillApp.png differ
diff --git a/app/assets/social_logos/strike.png b/app/assets/social_logos/strike.png
new file mode 100644
index 00000000..4b540b40
Binary files /dev/null and b/app/assets/social_logos/strike.png differ
diff --git a/app/assets/social_logos/tether.png b/app/assets/social_logos/tether.png
new file mode 100644
index 00000000..2f6d840d
Binary files /dev/null and b/app/assets/social_logos/tether.png differ
diff --git a/app/assets/social_logos/walletofsatoshi.png b/app/assets/social_logos/walletofsatoshi.png
new file mode 100644
index 00000000..3dd2dfeb
Binary files /dev/null and b/app/assets/social_logos/walletofsatoshi.png differ
diff --git a/app/assets/social_logos/zeus.png b/app/assets/social_logos/zeus.png
new file mode 100644
index 00000000..1811613e
Binary files /dev/null and b/app/assets/social_logos/zeus.png differ
diff --git a/app/components/admin/homeComponents/sendBitcoin/components/invoiceInfo.js b/app/components/admin/homeComponents/sendBitcoin/components/invoiceInfo.js
index 5bb626eb..32f52ab0 100644
--- a/app/components/admin/homeComponents/sendBitcoin/components/invoiceInfo.js
+++ b/app/components/admin/homeComponents/sendBitcoin/components/invoiceInfo.js
@@ -1,6 +1,8 @@
-import { StyleSheet, TouchableOpacity, View } from 'react-native';
+import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
+import { useMemo } from 'react';
+import { Image } from 'expo-image';
import { ThemeText } from '../../../../../functions/CustomElements';
-import { CENTER } from '../../../../../constants';
+import { CENTER, COLORS, FONT, ICONS, SIZES } from '../../../../../constants';
import GetThemeColors from '../../../../../hooks/themeColors';
import formatSparkPaymentAddress from '../functions/formatSparkPaymentAddress';
import { useNavigation } from '@react-navigation/native';
@@ -8,6 +10,25 @@ import { InputTypes } from 'bitcoin-address-parser';
import ContactProfileImage from '../../contacts/internalComponents/profileImage';
import normalizeLNURLAddress from '../../../../../functions/lnurl/normalizeLNURLAddress';
import ProfileImageRow from '../../contacts/internalComponents/profileImageRow';
+import ThemeIcon from '../../../../../functions/CustomElements/themeIcon';
+import { HIDDEN_OPACITY } from '../../../../../constants/theme';
+import { useTranslation } from 'react-i18next';
+
+// LNURL/lightning-address domain → ICONS key for the provider brand logo.
+const LNURL_PROVIDER_ICONS = {
+ 'aqua.net': 'aqua',
+ 'blink.sv': 'blink',
+ 'breez.tips': 'breez',
+ 'cake.cash': 'cake',
+ 'coinos.io': 'coinos',
+ 'mannabitcoin.com': 'mannabitcoin',
+ 'cluborange.org': 'cluborange',
+ 'strike.me': 'strike',
+ 'tether.me': 'tether',
+ 'walletofsatoshi.com': 'walletofsatoshi',
+ 'zeuspay.com': 'zeuspay',
+};
+
export default function InvoiceInfo({
paymentInfo,
fromPage,
@@ -23,11 +44,131 @@ export default function InvoiceInfo({
undefined,
true,
);
+ const { t } = useTranslation();
const { backgroundOffset, backgroundColor } = GetThemeColors();
const navigate = useNavigation();
const splitContacts = splitRecipients?.map(({ contact }) => contact);
+
+ const isLNURLPay = paymentInfo?.type === InputTypes.LNURL_PAY;
+ const paymentType = formmateedSparkPaymentInfo.paymentType;
+
+ // The bitcoin/spark/lrc20 branch renders the full address on screen, so
+ // tapping to "reveal the full address" adds nothing. Only single-row label
+ // variants (branta/contact/LNURL/lightning) stay clickable + get a chevron.
+ const showsFullAddress =
+ !isUsingBranta &&
+ !isSplitPayment &&
+ fromPage !== 'contacts' &&
+ !isLNURLPay &&
+ paymentType !== 'lightning';
+ const isClickable = !isSplitPayment && !showsFullAddress;
+
+ // LNURL: resolve the human-readable "user@host", match the host to a provider
+ // logo, and drop "@host" when we have a logo (the logo conveys the provider).
+ const normalizedLNURL = isLNURLPay
+ ? normalizeLNURLAddress(paymentInfo?.data?.address) ??
+ paymentInfo?.data?.address ??
+ ''
+ : '';
+ const lnurlDomain = normalizedLNURL.includes('@')
+ ? normalizedLNURL.split('@')[1]?.toLowerCase()
+ : '';
+ const providerIconKey = LNURL_PROVIDER_ICONS[lnurlDomain];
+ const lnurlDisplayText = providerIconKey
+ ? normalizedLNURL.split('@')[0]
+ : normalizedLNURL;
+
+ // On-chain / spark addresses: 4-char groups with alternating weight for
+ // easy visual validation (mirrors depositQRView).
+ const addressSegments = useMemo(() => {
+ const addr = formmateedSparkPaymentInfo.address || '';
+ return (addr.match(/.{1,4}/g) || []).map((group, i, all) => (
+
+ {group}
+ {i < all.length - 1 ? ' ' : ''}
+
+ ));
+ }, [formmateedSparkPaymentInfo.address]);
+
+ let paymentContent;
+ if (isLNURLPay) {
+ paymentContent = (
+
+
+ {providerIconKey ? (
+
+ ) : (
+
+ )}
+
+
+
+ );
+ } else if (paymentType === 'lightning') {
+ paymentContent = (
+
+
+
+
+
+
+ );
+ } else {
+ // bitcoin / spark / lrc20
+ paymentContent = (
+
+ );
+ }
+
+ const Container = isClickable ? TouchableOpacity : View;
+
return (
- {
navigate.navigate('ErrorScreen', {
errorMessage: formmateedSparkPaymentInfo.address,
@@ -35,11 +176,12 @@ export default function InvoiceInfo({
}}
style={[
styles.invoiceContainer,
+ isClickable && styles.clickableContainer,
{
backgroundColor: backgroundOffset,
},
]}
- disabled={isSplitPayment}
+ disabled={!isClickable}
>
{isUsingBranta ? (
@@ -94,18 +236,12 @@ export default function InvoiceInfo({
/>
) : (
-
+ paymentContent
)}
-
+ {isClickable && (
+
+ )}
+
);
}
@@ -114,15 +250,23 @@ const styles = StyleSheet.create({
width: '80%',
alignItems: 'center',
justifyContent: 'center',
- padding: 8,
- borderRadius: 8,
+ padding: 12,
+ borderRadius: 16,
...CENTER,
marginTop: 30,
},
+ clickableContainer: {
+ flexDirection: 'row',
+ },
contactRow: {
+ flex: 1,
flexDirection: 'row',
alignItems: 'center',
},
+ chevron: {
+ opacity: 0.8,
+ marginLeft: 8,
+ },
profileImage: {
width: 40,
@@ -133,8 +277,28 @@ const styles = StyleSheet.create({
overflow: 'hidden',
marginRight: 10,
},
+ providerLogoCircle: {
+ backgroundColor: COLORS.white,
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: COLORS.gray,
+ },
+ providerLogo: {
+ width: '100%',
+ height: '100%',
+ },
+ lightningIcon: {
+ width: 24,
+ height: 24,
+ },
addressText: {
includeFontPadding: false,
flexShrink: 1,
},
+ segmentText: {
+ fontSize: SIZES.small,
+ lineHeight: 24,
+ includeFontPadding: false,
+ textAlign: 'center',
+ width: '100%',
+ },
});
diff --git a/app/components/admin/homeComponents/sendBitcoin/stablecoinSendScreen.js b/app/components/admin/homeComponents/sendBitcoin/stablecoinSendScreen.js
index 7b398df8..f7a86cc9 100644
--- a/app/components/admin/homeComponents/sendBitcoin/stablecoinSendScreen.js
+++ b/app/components/admin/homeComponents/sendBitcoin/stablecoinSendScreen.js
@@ -64,6 +64,7 @@ import {
resolveUsdFiatStats,
} from '../../../../functions/displayCurrency';
import CurrencySwitchButton from '../../../../functions/CustomElements/currencySwitchButton';
+import ThemeIcon from '../../../../functions/CustomElements/themeIcon';
import { Image } from 'expo-image';
const QUOTE_TTL_MS = 115_000;
@@ -747,35 +748,42 @@ export default function StablecoinSendScreen() {
}
style={[styles.destinationBox, { backgroundColor: rowBg }]}
>
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
)}
@@ -918,12 +926,21 @@ const styles = StyleSheet.create({
width: '80%',
flexDirection: 'row',
alignItems: 'center',
- justifyContent: 'center',
- padding: 8,
- borderRadius: 8,
+ justifyContent: 'space-between',
+ padding: 12,
+ borderRadius: 16,
...CENTER,
marginTop: 30,
},
+ destinationContent: {
+ flexShrink: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ destinationChevron: {
+ opacity: 0.8,
+ marginLeft: 8,
+ },
receiveAmount: {
opacity: HIDDEN_OPACITY,
...CENTER,
diff --git a/app/constants/icons.js b/app/constants/icons.js
index 9f777442..dd7797af 100644
--- a/app/constants/icons.js
+++ b/app/constants/icons.js
@@ -39,6 +39,17 @@ import ios_maps_dark from '../assets/apple_maps_dark.png';
import android_maps_light from '../assets/google_maps_light.png';
import android_maps_dark from '../assets/google_maps_dark.png';
import bankIcon from '../assets/icons/bank.png';
+import aqua from '../assets/social_logos/aqua.png';
+import blink from '../assets/social_logos/blink.png';
+import breez from '../assets/social_logos/breez.png';
+import cake from '../assets/social_logos/cake.png';
+import coinos from '../assets/social_logos/coinos.png';
+import mannabitcoin from '../assets/social_logos/manna.png';
+import cluborange from '../assets/social_logos/orangePillApp.png';
+import strike from '../assets/social_logos/strike.png';
+import tether from '../assets/social_logos/tether.png';
+import walletofsatoshi from '../assets/social_logos/walletofsatoshi.png';
+import zeuspay from '../assets/social_logos/zeus.png';
export default {
logoIcon,
@@ -100,4 +111,17 @@ export default {
android_maps_dark,
bankIcon,
+
+ // LNURL Providers
+ aqua,
+ blink,
+ breez,
+ cake,
+ coinos,
+ mannabitcoin,
+ cluborange,
+ strike,
+ tether,
+ walletofsatoshi,
+ zeuspay,
};
diff --git a/locales/de-DE/translation.json b/locales/de-DE/translation.json
index a90a3a60..db75b338 100644
--- a/locales/de-DE/translation.json
+++ b/locales/de-DE/translation.json
@@ -1228,7 +1228,8 @@
"swapRatesChangedBody": "Der Wechselkurs für diesen Swap hat sich während Ihrer Prüfung geändert. Bitte geben Sie den Betrag erneut ein, um fortzufahren.",
"swapRatesChangedButton": "Betrag erneut eingeben",
"feeEstimateError": "Gebühr konnte nicht geschätzt werden, bitte versuchen Sie es erneut",
- "brantaVerification": "Diese Zahlung ist von Branta verifiziert."
+ "brantaVerification": "Diese Zahlung ist von Branta verifiziert.",
+ "lightningPayment": "Lightning-Zahlung"
},
"selectPaymentMethod": {
"header": "Wie möchten Sie diese Zahlung senden (BTC oder USD)?"
diff --git a/locales/en/translation.json b/locales/en/translation.json
index 1302a9e3..66d5bed9 100644
--- a/locales/en/translation.json
+++ b/locales/en/translation.json
@@ -1228,7 +1228,8 @@
"swapRatesChangedBody": "The exchange rate for this swap changed while you were reviewing. Please re-enter your amount to continue.",
"swapRatesChangedButton": "Re-enter Amount",
"feeEstimateError": "Unable to estimate fee, please try again",
- "brantaVerification": "This payment has been verified by Branta"
+ "brantaVerification": "This payment has been verified by Branta",
+ "lightningPayment": "Lightning payment"
},
"selectPaymentMethod": {
"header": "How do you want to fund your payment?"
diff --git a/locales/es/translation.json b/locales/es/translation.json
index 323134ce..85c2a1c6 100644
--- a/locales/es/translation.json
+++ b/locales/es/translation.json
@@ -1228,7 +1228,8 @@
"swapRatesChangedBody": "El tipo de cambio para este intercambio cambió mientras lo estabas revisando. Vuelve a ingresar el monto para continuar.",
"swapRatesChangedButton": "Volver a ingresar el monto",
"feeEstimateError": "No se pudo estimar la comisión, inténtalo de nuevo",
- "brantaVerification": "Este pago ha sido verificado por Branta"
+ "brantaVerification": "Este pago ha sido verificado por Branta",
+ "lightningPayment": "Pago Lightning"
},
"selectPaymentMethod": {
"header": "Selecciona cómo deseas financiar tu pago."
diff --git a/locales/fr/translation.json b/locales/fr/translation.json
index 8a60eee2..69f9941c 100644
--- a/locales/fr/translation.json
+++ b/locales/fr/translation.json
@@ -1228,7 +1228,8 @@
"swapRatesChangedBody": "Le taux de change pour cet échange a changé pendant votre vérification. Veuillez saisir à nouveau le montant pour continuer.",
"swapRatesChangedButton": "Ressaisir le montant",
"feeEstimateError": "Impossible d’estimer les frais, veuillez réessayer",
- "brantaVerification": "Ce paiement a été vérifié par Branta"
+ "brantaVerification": "Ce paiement a été vérifié par Branta",
+ "lightningPayment": "Paiement Lightning"
},
"selectPaymentMethod": {
"header": "Veuillez sélectionner comment vous souhaitez financer votre paiement."
diff --git a/locales/it/translation.json b/locales/it/translation.json
index 986f3e86..29bc5a79 100644
--- a/locales/it/translation.json
+++ b/locales/it/translation.json
@@ -1228,7 +1228,8 @@
"swapRatesChangedBody": "Il tasso di cambio per questo scambio è cambiato durante la revisione. Inserisci nuovamente l’importo per continuare.",
"swapRatesChangedButton": "Reinserisci importo",
"feeEstimateError": "Impossibile stimare la commissione, riprova",
- "brantaVerification": "Questo pagamento è stato verificato da Branta"
+ "brantaVerification": "Questo pagamento è stato verificato da Branta",
+ "lightningPayment": "Pagamento Lightning"
},
"selectPaymentMethod": {
"header": "Seleziona come desideri finanziare il pagamento."
diff --git a/locales/pt-BR/translation.json b/locales/pt-BR/translation.json
index d1d5227f..d6c1db21 100644
--- a/locales/pt-BR/translation.json
+++ b/locales/pt-BR/translation.json
@@ -1227,7 +1227,8 @@
"swapRatesChangedBody": "A cotação para esta troca mudou enquanto você estava revisando. Insira o valor novamente para continuar.",
"swapRatesChangedButton": "Inserir valor novamente",
"feeEstimateError": "Não foi possível estimar a taxa, tente novamente",
- "brantaVerification": "Este pagamento foi verificado pela Branta"
+ "brantaVerification": "Este pagamento foi verificado pela Branta",
+ "lightningPayment": "Pagamento Lightning"
},
"selectPaymentMethod": {
"header": "Escolha o saldo para realizar esse pagamento"
diff --git a/locales/ru/translation.json b/locales/ru/translation.json
index 3bf8cc00..d99ed5ff 100644
--- a/locales/ru/translation.json
+++ b/locales/ru/translation.json
@@ -1229,7 +1229,8 @@
"swapRatesChangedBody": "Курс обмена для этой операции изменился во время проверки. Пожалуйста, введите сумму заново, чтобы продолжить.",
"swapRatesChangedButton": "Ввести сумму снова",
"feeEstimateError": "Не удалось оценить комиссию, попробуйте снова",
- "brantaVerification": "Этот платёж был подтверждён Branta"
+ "brantaVerification": "Этот платёж был подтверждён Branta",
+ "lightningPayment": "Платёж Lightning"
},
"selectPaymentMethod": {
"header": "Выберите источник средств."
diff --git a/locales/sv/translation.json b/locales/sv/translation.json
index 967c0f93..1876a122 100644
--- a/locales/sv/translation.json
+++ b/locales/sv/translation.json
@@ -1228,7 +1228,8 @@
"swapRatesChangedBody": "Växelkursen för denna växling ändrades medan du granskade den. Ange beloppet igen för att fortsätta.",
"swapRatesChangedButton": "Ange belopp igen",
"feeEstimateError": "Kunde inte uppskatta avgiften, försök igen",
- "brantaVerification": "Denna betalning har verifierats av Branta"
+ "brantaVerification": "Denna betalning har verifierats av Branta",
+ "lightningPayment": "Lightning-betalning"
},
"selectPaymentMethod": {
"header": "Välj hur du vill finansiera din betalning."