diff --git a/src/lib/i18n.ts b/src/lib/i18n.ts
index 5f894bb4b..173a30c54 100644
--- a/src/lib/i18n.ts
+++ b/src/lib/i18n.ts
@@ -219,6 +219,9 @@ const resources = {
transaction_summary_plus_fees_capitalcase: '+ Fees',
transaction_summary_insufficient_funds: 'Insufficient funds',
transaction_summary_address_text: 'Address',
+ transaction_summary_add_non_existent_contact_title: 'Do you wish to add',
+ transaction_summary_add_non_existent_contact_title_2: 'as your contact?',
+ transaction_summary_add_non_existent_contact_action: 'Yes, sure',
profile_screen_title: 'Profile',
profile_contact_details_subtitle: 'Contact Details',
profile_phone_label: 'Phone Number',
diff --git a/src/screens/contacts/ContactFormScreen.tsx b/src/screens/contacts/ContactFormScreen.tsx
index c7fceaa89..8b5118ee3 100644
--- a/src/screens/contacts/ContactFormScreen.tsx
+++ b/src/screens/contacts/ContactFormScreen.tsx
@@ -50,6 +50,10 @@ export const checkIfContactExists = (
name: string,
searchArray: Contact[],
) => {
+ if (!address || !name) {
+ return false
+ }
+
const index = searchArray.findIndex(c => {
return (
c.displayAddress === address.toLowerCase() ||
@@ -166,6 +170,7 @@ export const ContactFormScreen = ({
address: lAddress,
displayAddress,
}
+
const contactExists = checkIfContactExists(
displayAddress && lAddress,
trimmedName,
diff --git a/src/screens/send/SendScreen.tsx b/src/screens/send/SendScreen.tsx
index 891518bac..cbe9598bd 100644
--- a/src/screens/send/SendScreen.tsx
+++ b/src/screens/send/SendScreen.tsx
@@ -21,14 +21,15 @@ import {
selectBalances,
selectTotalUsdValue,
} from 'store/slices/balancesSlice/selectors'
-import { sharedColors, sharedStyles } from 'shared/constants'
import { TokenBalanceObject } from 'store/slices/balancesSlice/types'
import { selectChainId } from 'store/slices/settingsSlice'
+import { TransactionStatus } from 'store/shared/types'
+import { selectRecentRskTransactions } from 'store/slices/transactionsSlice'
+import { getContactsAsArrayAndSelected } from 'store/slices/contactsSlice'
import { FullScreenSpinner } from 'components/fullScreenSpinner'
import { SuccessIcon } from 'components/icons/SuccessIcon'
import { FeedbackModal } from 'components/feedbackModal'
-import { getContactsAsArrayAndSelected } from 'store/slices/contactsSlice'
-import { selectRecentRskTransactions } from 'store/slices/transactionsSlice'
+import { sharedColors, sharedStyles } from 'shared/constants'
import { useWalletState } from 'shared/wallet'
import { TransactionForm } from './TransactionForm'
@@ -177,15 +178,15 @@ export const SendScreen = ({
status = error.toString()
} else if (
currentTransaction?.status &&
- currentTransaction.status === 'USER_CONFIRM'
+ currentTransaction.status === TransactionStatus.USER_CONFIRM
) {
status = t('send_screen_sending_transaction')
}
useEffect(() => {
if (
- currentTransaction?.status === 'SUCCESS' ||
- currentTransaction?.status === 'FAILED'
+ currentTransaction?.status === TransactionStatus.SUCCESS ||
+ currentTransaction?.status === TransactionStatus.FAILED
) {
navigation.navigate(rootTabsRouteNames.Home, {
screen: homeStackRouteNames.Main,
@@ -239,7 +240,7 @@ export const SendScreen = ({
status={status}
bitcoinBalance={bitcoinBalance}
/>
- {currentTransaction?.status === 'USER_CONFIRM' && (
+ {currentTransaction?.status === TransactionStatus.USER_CONFIRM && (
)}
diff --git a/src/screens/transactionSummary/TransactionSummaryComponent.tsx b/src/screens/transactionSummary/TransactionSummaryComponent.tsx
index f71e0c585..16b01f58d 100644
--- a/src/screens/transactionSummary/TransactionSummaryComponent.tsx
+++ b/src/screens/transactionSummary/TransactionSummaryComponent.tsx
@@ -15,10 +15,8 @@ import {
import { castStyle, formatTokenValues } from 'shared/utils'
import { AppButton, AppTouchable, Typography } from 'components/index'
import { useAppSelector } from 'store/storeUtils'
-import { isMyAddress } from 'components/address/lib'
import { DollarIcon } from 'components/icons/DollarIcon'
import { FullScreenSpinner } from 'components/fullScreenSpinner'
-import { getContactByAddress } from 'store/slices/contactsSlice'
import { getWalletSetting } from 'core/config'
import { SETTINGS } from 'core/types'
import { selectChainId } from 'store/slices/settingsSlice'
@@ -44,13 +42,13 @@ type TransactionSummaryComponentProps = Omit<
Props
export const TransactionSummaryComponent = ({
- address,
transaction,
buttons,
functionName,
goBack,
isLoaded,
FeeComponent,
+ contact,
}: TransactionSummaryComponentProps) => {
const [confirmed, setConfirmed] = useState(false)
const chainId = useAppSelector(selectChainId)
@@ -64,21 +62,14 @@ export const TransactionSummaryComponent = ({
time,
hashId,
to,
- from,
totalToken,
totalUsd,
+ amIReceiver,
} = transaction
const iconObject = transactionStatusToIconPropsMap.get(status)
const transactionStatusText = transactionStatusDisplayText.get(status)
- const amIReceiver = transaction.amIReceiver ?? isMyAddress(address, to)
- const contactAddress = amIReceiver ? from || '' : to
- const contact = useAppSelector(
- getContactByAddress(contactAddress.toLowerCase()),
- )
- const contactToUse = contact || { address: contactAddress }
-
const title = useMemo(() => {
if (amIReceiver) {
if (status === TransactionStatus.SUCCESS) {
@@ -121,7 +112,7 @@ export const TransactionSummaryComponent = ({
{functionName && (
@@ -247,7 +238,7 @@ export const TransactionSummaryComponent = ({
{/* separator */}
{/* address value */}
- {contactToUse?.name && (
+ {contact?.name && (
- {contactToUse.address}
+ {contact.address}
)}
diff --git a/src/screens/transactionSummary/index.tsx b/src/screens/transactionSummary/index.tsx
index f3745f6d3..0fcde0003 100644
--- a/src/screens/transactionSummary/index.tsx
+++ b/src/screens/transactionSummary/index.tsx
@@ -1,20 +1,29 @@
import { useFocusEffect, useIsFocused } from '@react-navigation/native'
import { ReactNode, useCallback, useEffect, useMemo } from 'react'
import { BackHandler } from 'react-native'
+import { showMessage } from 'react-native-flash-message'
+import { useTranslation } from 'react-i18next'
+
+import { shortAddress } from 'lib/utils'
import { AppButtonProps } from 'components/button'
import { CurrencyValue } from 'components/token'
import { sharedHeaderLeftOptions } from 'navigation/index'
+import { contactsStackRouteNames } from 'navigation/contactsNavigator'
import {
RootTabsScreenProps,
rootTabsRouteNames,
} from 'navigation/rootNavigator'
+import { isMyAddress } from 'components/index'
import { TransactionSummaryComponent } from 'screens/transactionSummary/TransactionSummaryComponent'
import { setFullscreen } from 'store/slices/settingsSlice'
import { TokenFeeValueObject } from 'store/slices/transactionsSlice'
-import { useAppDispatch } from 'store/storeUtils'
+import { useAppDispatch, useAppSelector } from 'store/storeUtils'
import { useWallet } from 'shared/wallet'
+import { getPopupMessage } from 'shared/popupMessage'
+import { ContactWithAddressRequired } from 'shared/types'
import { TransactionStatus } from 'store/shared/types'
+import { getContactByAddress } from 'store/slices/contactsSlice'
export interface TransactionSummaryScreenProps {
transaction: {
@@ -30,6 +39,7 @@ export interface TransactionSummaryScreenProps {
amIReceiver?: boolean
from?: string
}
+ contact: ContactWithAddressRequired
buttons?: [AppButtonProps, AppButtonProps]
functionName?: string
backScreen?: rootTabsRouteNames
@@ -41,10 +51,19 @@ export const TransactionSummaryScreen = ({
route,
navigation,
}: RootTabsScreenProps) => {
+ const { t } = useTranslation()
+ const { transaction, backScreen } = route.params
+ const { to, from } = transaction
+
const { address } = useWallet()
const dispatch = useAppDispatch()
const isFocused = useIsFocused()
- const { backScreen } = route.params
+ const amIReceiver = transaction.amIReceiver ?? isMyAddress(address, to)
+ const contactAddress = amIReceiver ? from || '' : to
+ const contact = useAppSelector(
+ getContactByAddress(contactAddress.toLowerCase()),
+ )
+ const contactToUse = contact || { address: contactAddress }
const goBack = useMemo(() => {
if (backScreen) {
@@ -77,9 +96,41 @@ export const TransactionSummaryScreen = ({
})
}, [goBack, navigation])
+ const moveToCreateContact = useCallback(() => {
+ navigation.navigate(rootTabsRouteNames.Contacts, {
+ screen: contactsStackRouteNames.ContactForm,
+ params: {
+ initialValue: {
+ address: contactAddress,
+ name: '',
+ displayAddress: '',
+ },
+ proposed: true,
+ },
+ })
+ }, [navigation, contactAddress])
+
+ useEffect(() => {
+ if (!contact) {
+ showMessage(
+ getPopupMessage(
+ `${t(
+ 'transaction_summary_add_non_existent_contact_title',
+ )} ${shortAddress(contactAddress)} ${t(
+ 'transaction_summary_add_non_existent_contact_title_2',
+ )}`,
+ t('transaction_summary_add_non_existent_contact_action'),
+ moveToCreateContact,
+ ),
+ )
+ }
+ }, [contact, contactAddress, moveToCreateContact, t])
+
return (
diff --git a/src/ux/requestsModal/ReviewBitcoinTransactionContainer.tsx b/src/ux/requestsModal/ReviewBitcoinTransactionContainer.tsx
index 9d7f9627c..f2a834896 100644
--- a/src/ux/requestsModal/ReviewBitcoinTransactionContainer.tsx
+++ b/src/ux/requestsModal/ReviewBitcoinTransactionContainer.tsx
@@ -14,10 +14,11 @@ import { TransactionSummaryComponent } from 'screens/transactionSummary/Transact
import { TokenSymbol } from 'screens/home/TokenImage'
import { selectUsdPrices } from 'store/slices/usdPricesSlice'
import { useAppSelector } from 'store/storeUtils'
-import { sharedColors } from 'shared/constants'
+import { getContactByAddress } from 'store/slices/contactsSlice'
import { AppButtonBackgroundVarietyEnum, Input } from 'components/index'
import { TransactionSummaryScreenProps } from 'screens/transactionSummary'
import { formatTokenValues } from 'shared/utils'
+import { sharedColors } from 'shared/constants'
import {
BitcoinMiningFeeContainer,
@@ -44,6 +45,8 @@ export const ReviewBitcoinTransactionContainer = ({
payload: { addressToPay, payment, ...payload },
} = request
+ const contact = useAppSelector(getContactByAddress(addressToPay))
+
const [miningFeeState, setMiningFeeState] = useState(payload.miningFee)
const onMiningFeeChange = useCallback(
@@ -85,6 +88,7 @@ export const ReviewBitcoinTransactionContainer = ({
const feeUsd = convertToUSD(miningFee)
const isAmountSmall = !Number(amountToPayUsd) && !!Number(amountToPay)
const totalSent = Number(amountToPay) + Number(miningFee)
+ const contactToUse = contact || { address: addressToPay }
return {
transaction: {
@@ -114,6 +118,7 @@ export const ReviewBitcoinTransactionContainer = ({
),
to: addressToPay,
},
+ contact: contactToUse,
buttons: [
{
title: t('transaction_summary_title_confirm_button_title'),
diff --git a/src/ux/requestsModal/ReviewRelayTransaction/ReviewTransactionContainer.tsx b/src/ux/requestsModal/ReviewRelayTransaction/ReviewTransactionContainer.tsx
index 736add9e6..8ceca2f04 100644
--- a/src/ux/requestsModal/ReviewRelayTransaction/ReviewTransactionContainer.tsx
+++ b/src/ux/requestsModal/ReviewRelayTransaction/ReviewTransactionContainer.tsx
@@ -25,7 +25,10 @@ import {
} from 'shared/utils'
import { selectUsdPrices } from 'store/slices/usdPricesSlice'
import { useAppDispatch, useAppSelector } from 'store/storeUtils'
-import { addRecentContact } from 'store/slices/contactsSlice'
+import {
+ addRecentContact,
+ getContactByAddress,
+} from 'store/slices/contactsSlice'
import { selectBalances } from 'store/slices/balancesSlice'
import { selectRecentRskTransactions } from 'store/slices/transactionsSlice'
import { Wallet } from 'shared/wallet'
@@ -82,6 +85,8 @@ export const ReviewTransactionContainer = ({
gasLimit,
} = enhancedTransactionRequest
+ const contact = useAppSelector(getContactByAddress(to))
+
const getTokenBySymbol = useCallback(
(symb: string) => {
const result = Object.values(balances).find(
@@ -239,6 +244,7 @@ export const ReviewTransactionContainer = ({
time: 'approx 1 min',
to,
},
+ contact: contact || { address: to },
buttons: [
{
title: t('transaction_summary_title_confirm_button_title'),
@@ -272,6 +278,7 @@ export const ReviewTransactionContainer = ({
cancelTransaction,
functionName,
wallet,
+ contact,
])
return (