diff --git a/mobile-app/app/api/transaction/transfer_domain.ts b/mobile-app/app/api/transaction/transfer_domain.ts index 9abab9e01a..7f9cbe82a2 100644 --- a/mobile-app/app/api/transaction/transfer_domain.ts +++ b/mobile-app/app/api/transaction/transfer_domain.ts @@ -99,10 +99,7 @@ export async function transferDomainSigner( token: stripEvmSuffixFromTokenId(sourceTokenId), amount: amount, }, - data: - convertDirection === ConvertDirection.evmToDvm - ? evmTx - : new Uint8Array([]), + data: isEvmToDvm ? evmTx : new Uint8Array([]), }, dst: { address: dstScript, @@ -111,10 +108,7 @@ export async function transferDomainSigner( token: stripEvmSuffixFromTokenId(targetTokenId), amount: amount, }, - data: - convertDirection === ConvertDirection.dvmToEvm - ? evmTx - : new Uint8Array([]), + data: isEvmToDvm ? new Uint8Array([]) : evmTx, }, }, ], diff --git a/mobile-app/app/components/SummaryTitle.tsx b/mobile-app/app/components/SummaryTitle.tsx index b0fba129c2..c21ad98cd2 100644 --- a/mobile-app/app/components/SummaryTitle.tsx +++ b/mobile-app/app/components/SummaryTitle.tsx @@ -5,6 +5,9 @@ import { getNativeIcon } from "@components/icons/assets"; import { translate } from "@translations"; import { RandomAvatar } from "@screens/AppNavigator/screens/Portfolio/components/RandomAvatar"; import { AddressType } from "@waveshq/walletkit-ui/dist/store"; +import { LocalAddress, WhitelistedAddress } from "@store/userPreferences"; +import { DomainType } from "@contexts/DomainContext"; +import { LinearGradient } from "expo-linear-gradient"; import { View } from "."; import { ThemedTextV2, ThemedViewV2 } from "./themed"; import { EVMLinearGradient } from "./EVMLinearGradient"; @@ -22,6 +25,7 @@ interface ISummaryTitleProps { iconB?: string; addressType?: AddressType; amountTextStyle?: string; + matchedAddress?: LocalAddress | WhitelistedAddress; isEvmToken?: boolean; } @@ -123,39 +127,81 @@ export function SummaryTitle(props: ISummaryTitleProps): JSX.Element { > {props.customToAddressTitle ?? translate("screens/common", "To")} - - {props.addressType === AddressType.WalletAddress && ( - - - - )} - - {props.toAddressLabel != null && props.toAddressLabel.length > 0 - ? props.toAddressLabel - : props.toAddress} - - + {props.addressType === AddressType.WalletAddress && ( + + + + )} + + {props.toAddressLabel != null && + props.toAddressLabel.length > 0 + ? props.toAddressLabel + : props.toAddress} + + + ) : ( + + {props.addressType === AddressType.WalletAddress && ( + + + + )} + + {props.toAddressLabel != null && + props.toAddressLabel.length > 0 + ? props.toAddressLabel + : props.toAddress} + + + )} )} diff --git a/mobile-app/app/hooks/useWalletAddress.ts b/mobile-app/app/hooks/useWalletAddress.ts index 94a613fbf3..8d6a9f2095 100644 --- a/mobile-app/app/hooks/useWalletAddress.ts +++ b/mobile-app/app/hooks/useWalletAddress.ts @@ -18,7 +18,6 @@ export function useWalletAddress(): { for (let i = 0; i <= addressLength; i++) { const account = wallet.get(i); const dvm = await account.getAddress(); - // TODO (Harsh) replace it with getEvmAddress const evm = await account.getEvmAddress(); addresses.push({ dvm, evm }); } diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioNavigator.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioNavigator.tsx index 8eb5fe5918..61b26be88f 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioNavigator.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioNavigator.tsx @@ -9,7 +9,7 @@ import { BarCodeScanner } from "@components/BarCodeScanner"; import { HeaderTitle } from "@components/HeaderTitle"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; -import { WhitelistedAddress } from "@store/userPreferences"; +import { LocalAddress, WhitelistedAddress } from "@store/userPreferences"; import { FutureSwapData } from "@store/futureSwap"; import { TransactionsScreen } from "@screens/AppNavigator/screens/Transactions/TransactionsScreen"; import { TransactionDetailScreen } from "@screens/AppNavigator/screens/Transactions/screens/TransactionDetailScreen"; @@ -78,6 +78,7 @@ export interface PortfolioParamList { toAddressLabel?: string; addressType?: AddressType; originScreen?: ScreenName; + matchedAddress?: WhitelistedAddress | LocalAddress; }; TokenDetailScreen: { token: WalletToken }; ConvertScreen: { diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioScreen.tsx index 8a2fa06ae4..925fec9db0 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioScreen.tsx @@ -367,13 +367,18 @@ export function PortfolioScreen({ navigation }: Props): JSX.Element { return filteredTokens.sort(sortTokensFunc); }, - [filteredTokens, assetSortType, denominationCurrency], + [domain, filteredTokens, assetSortType, denominationCurrency], ); useEffect(() => { setAssetSortType(PortfolioSortType.HighestDenominationValue); // reset sorting state upon denominationCurrency change }, [denominationCurrency]); + // Reset button group in EVM domain + useEffect(() => { + setActiveButtonGroup(ButtonGroupTabKey.AllTokens); + }, [domain]); + // token tab items const [activeButtonGroup, setActiveButtonGroup] = useState( ButtonGroupTabKey.AllTokens, diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/AddressRow.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/AddressRow.tsx index 8ce9d1bf2c..02802c8ae3 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/AddressRow.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/AddressRow.tsx @@ -23,6 +23,13 @@ import { useEffect, useMemo, useState } from "react"; import { useSelector } from "react-redux"; import { RootState } from "@store"; import { WalletAddressI, useWalletAddress } from "@hooks/useWalletAddress"; +import { DomainType, useDomainContext } from "@contexts/DomainContext"; +import { LinearGradient } from "expo-linear-gradient"; +import { + getAddressType, + AddressType as JellyfishAddressType, +} from "@waveshq/walletkit-core"; +import { Text } from "@components"; export function AddressRow({ control, @@ -38,6 +45,8 @@ export function AddressRow({ onAddressType, showQrButton = true, onlyLocalAddress, + matchedAddress, + setMatchedAddress, }: { control: Control; networkName: NetworkName; @@ -54,8 +63,11 @@ export function AddressRow({ onAddressType?: (addressType?: AddressType) => void; showQrButton?: boolean; onlyLocalAddress?: boolean; + matchedAddress?: LocalAddress | WhitelistedAddress | undefined; + setMatchedAddress?: (address?: LocalAddress | WhitelistedAddress) => void; }): JSX.Element { const { fetchWalletAddresses } = useWalletAddress(); + const { domain } = useDomainContext(); const defaultValue = ""; @@ -69,10 +81,9 @@ export function AddressRow({ const [jellyfishWalletAddress, setJellyfishWalletAddresses] = useState< WalletAddressI[] >([]); - const [matchedAddress, setMatchedAddress] = useState< - LocalAddress | WhitelistedAddress - >(); const [addressType, setAddressType] = useState(); + const [validEvmAddress, setValidEvmAddress] = useState(false); + const validLocalAddress = useMemo(() => { if (address === "") { return true; @@ -84,26 +95,28 @@ export function AddressRow({ }, [onlyLocalAddress, addressType, address]); const debounceMatchAddress = debounce(() => { - if ( - address !== undefined && - addressBook !== undefined && - addressBook[address] !== undefined - ) { - setMatchedAddress(addressBook[address]); - setAddressType(AddressType.Whitelisted); - } else if ( - address !== undefined && - walletAddress !== undefined && - walletAddress[address] !== undefined - ) { - setMatchedAddress(walletAddress[address]); - setAddressType(AddressType.WalletAddress); - } else { + // Check if address input field is not empty + if (address !== undefined && setMatchedAddress !== undefined) { + if (addressBook !== undefined && addressBook[address] !== undefined) { + // Whitelisted Addresses + setMatchedAddress(addressBook[address]); + setAddressType(AddressType.Whitelisted); + return; + } + + // Your Address - Labelled + if (walletAddress !== undefined && walletAddress[address] !== undefined) { + setMatchedAddress(walletAddress[address]); + setAddressType(AddressType.WalletAddress); + return; + } + const addressObj = jellyfishWalletAddress.find( (e: WalletAddressI) => e.dvm === address || e.evm === address, ); - if (address !== undefined && addressObj) { - // wallet address that does not have a label + + if (addressObj) { + // Your addresses - Unlabelled setMatchedAddress({ address: addressObj.dvm, evmAddress: addressObj.evm, @@ -111,10 +124,17 @@ export function AddressRow({ }); setAddressType(AddressType.WalletAddress); } else { - setMatchedAddress(undefined); + setMatchedAddress(undefined); // Unsaved valid DVM address if (onlyLocalAddress) { setAddressType(undefined); + } else if ( + getAddressType(address, networkName) === JellyfishAddressType.ETH + ) { + // Unsaved and valid EVM address + setAddressType(AddressType.OthersButValid); + setValidEvmAddress(true); } else { + setValidEvmAddress(false); setAddressType( fromAddress(address, networkName) !== undefined ? AddressType.OthersButValid @@ -236,78 +256,108 @@ export function AddressRow({ required: true, validate: { isValidAddress: (address) => - fromAddress(address, networkName) !== undefined && - (!onlyLocalAddress || - jellyfishWalletAddress.includes(address) || - (walletAddress !== undefined && - walletAddress[address] !== undefined)), + // Check if its either a valid EVM/DVM address && + !!getAddressType(address, networkName) && + // EVM -> EVM domain transfer is not allowed + !( + getAddressType(address, networkName) === + JellyfishAddressType.ETH && domain === DomainType.EVM + ), }, }} /> - {addressType !== undefined && ( - - {addressType === AddressType.OthersButValid ? ( - <> - - - {translate("screens/SendScreen", "Verified")} - - - ) : ( - addressType !== undefined && - validLocalAddress && ( - - {addressType === AddressType.WalletAddress && ( - - - - )} - + + {addressType !== undefined && ( + <> + {/* Verified tag for DVM/EVM address */} + {addressType === AddressType.OthersButValid && ( + <> + - {matchedAddress?.label !== "" - ? matchedAddress?.label - : matchedAddress.address} + {translate("screens/SendScreen", "Verified {{text}}", { + text: validEvmAddress ? "MetaChain (EVM) address" : "", + })} - - ) - )} - - )} + + )} + {addressType !== AddressType.OthersButValid && + validLocalAddress && ( + <> + {/* TODO @chloe cater for selection of evm addr from addr pair */} + {(matchedAddress as WhitelistedAddress)?.addressDomainType === + DomainType.EVM ? ( + // || (matchedAddress as LocalAddress)?.evmAddress ? + + {/* TODO add avatar for after updating address book design */} + + {matchedAddress?.label || matchedAddress?.address} + + + ) : ( + + {addressType === AddressType.WalletAddress && ( + + + + )} + + {matchedAddress?.label || matchedAddress?.address} + + + )} + + )} + + )} + ); } diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/PortfolioCard.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/PortfolioCard.tsx index 85aabe9a43..518bbb5604 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/PortfolioCard.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/PortfolioCard.tsx @@ -122,6 +122,7 @@ function PortfolioItemRow({ displaySymbol={token.displaySymbol} name={token.name} testID={testID} + isEvmDomain={isEvmDomain} /> - {name} + {tokenName} )} diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/AddressBookScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/AddressBookScreen.tsx index 2a8296354c..c1ec623976 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/AddressBookScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/AddressBookScreen.tsx @@ -64,12 +64,8 @@ export enum ButtonGroupTabKey { } export function AddressBookScreen({ route, navigation }: Props): JSX.Element { - const { - selectedAddress, - onAddressSelect, - disabledTab, - addressDomainType = DomainType.DVM, - } = route.params; + const { selectedAddress, onAddressSelect, disabledTab, addressDomainType } = + route.params; const { isLight } = useThemeContext(); const { network } = useNetworkContext(); const dispatch = useAppDispatch(); @@ -284,11 +280,14 @@ export function AddressBookScreen({ route, navigation }: Props): JSX.Element { onAddressSelect?: (address: string) => void; }): JSX.Element => { const { item, index, testIDSuffix } = props; - // to disable address select of non compatible address type const isDisabledToSelect = !!( - enableAddressSelect && - activeButtonGroup === ButtonGroupTabKey.Whitelisted && - (item as WhitelistedAddress).addressDomainType !== addressDomainType + ( + enableAddressSelect && + activeButtonGroup === ButtonGroupTabKey.Whitelisted && + (item as WhitelistedAddress).addressDomainType === + addressDomainType && + addressDomainType === DomainType.EVM + ) // disable address selection if its from the same EVM domain ); const onChangeAddress = ( diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConvertConfirmationScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConvertConfirmationScreen.tsx index 56fddff9d9..b789622eb3 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConvertConfirmationScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConvertConfirmationScreen.tsx @@ -235,7 +235,7 @@ export function ConvertConfirmationScreen({ route }: Props): JSX.Element { fee, }), suffix: ` ${sourceToken.displayTextSymbol}${ - convertDirection === ConvertDirection.dvmToEvm ? "-EVM" : "" + convertDirection === ConvertDirection.dvmToEvm ? "" : "-EVM" }`, testID: "resulting_tokens_value", themedProps: { diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendConfirmationScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendConfirmationScreen.tsx index 4b35a0ed21..26e2c3b0a9 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendConfirmationScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendConfirmationScreen.tsx @@ -62,13 +62,14 @@ export function SendConfirmationScreen({ route }: Props): JSX.Element { toAddressLabel, addressType, originScreen, + matchedAddress, } = route.params; const logger = useLogger(); const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const dispatch = useAppDispatch(); const [isSubmitting, setIsSubmitting] = useState(false); @@ -101,7 +102,7 @@ export function SendConfirmationScreen({ route }: Props): JSX.Element { () => { onTransactionBroadcast(isOnPage, navigation.dispatch); }, - logger + logger, ); setIsSubmitting(false); } @@ -112,7 +113,7 @@ export function SendConfirmationScreen({ route }: Props): JSX.Element { title: translate("screens/Settings", "Cancel transaction"), message: translate( "screens/Settings", - "By cancelling, you will lose any changes you made for your transaction." + "By cancelling, you will lose any changes you made for your transaction.", ), buttons: [ { @@ -126,7 +127,7 @@ export function SendConfirmationScreen({ route }: Props): JSX.Element { navigation.navigate( originScreen === ScreenName.DEX_screen ? ScreenName.DEX_screen - : ScreenName.PORTFOLIO_screen + : ScreenName.PORTFOLIO_screen, ); }, }, @@ -149,6 +150,7 @@ export function SendConfirmationScreen({ route }: Props): JSX.Element { toAddress={destination} toAddressLabel={toAddressLabel} addressType={addressType} + matchedAddress={matchedAddress} /> {conversion?.isConversionRequired === true && ( @@ -164,7 +166,7 @@ export function SendConfirmationScreen({ route }: Props): JSX.Element { lhs={{ value: translate( "screens/SendConfirmationScreen", - "Amount to convert" + "Amount to convert", ), testID: "amount_to_convert", themedProps: { @@ -184,7 +186,7 @@ export function SendConfirmationScreen({ route }: Props): JSX.Element { /> {conversion?.isConverted !== true && ( @@ -221,7 +223,7 @@ export function SendConfirmationScreen({ route }: Props): JSX.Element { containerStyle={{ style: tailwind( "flex-row items-start w-full bg-transparent border-t-0.5 pt-5", - { "mt-8": conversion?.isConversionRequired !== true } + { "mt-8": conversion?.isConversionRequired !== true }, ), light: tailwind("bg-transparent border-mono-light-v2-300"), dark: tailwind("bg-transparent border-mono-dark-v2-300"), @@ -229,7 +231,7 @@ export function SendConfirmationScreen({ route }: Props): JSX.Element { lhs={{ value: translate( "screens/SendConfirmationScreen", - "Transaction fee" + "Transaction fee", ), testID: "transaction_fee", themedProps: { @@ -250,7 +252,7 @@ export function SendConfirmationScreen({ route }: Props): JSX.Element { {translate( "screens/SendConfirmationScreen", - "I acknowledge that sending LP tokens to addresses that are not DeFiChain compatible wallets may result in irreversible loss of funds." + "I acknowledge that sending LP tokens to addresses that are not DeFiChain compatible wallets may result in irreversible loss of funds.", )} @@ -353,13 +355,13 @@ async function send( { address, token, amount, networkName }: SendForm, dispatch: Dispatch, onBroadcast: () => void, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { try { const to = DeFiAddress.from(networkName, address).getScript(); const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const script = await account.getScript(); const builder = account.withTransactionBuilder(); @@ -385,7 +387,7 @@ async function send( }, ], }, - script + script, ); } return new CTransactionSegWit(signed); @@ -401,7 +403,7 @@ async function send( amount: amount.toFixed(8), displaySymbol: token.displaySymbol, toAddress: address, - } + }, ), drawerMessages: { preparing: translate("screens/OceanInterface", "Preparing to send…"), @@ -411,7 +413,7 @@ async function send( { amount: amount.toFixed(8), displaySymbol: token.displaySymbol, - } + }, ), complete: translate( "screens/OceanInterface", @@ -419,11 +421,11 @@ async function send( { amount: amount.toFixed(8), displaySymbol: token.displaySymbol, - } + }, ), }, onBroadcast, - }) + }), ); } catch (e) { logger.error(e); diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendScreen.tsx index 1256a22eda..3621325055 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendScreen.tsx @@ -42,7 +42,7 @@ import { import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { AddressRow } from "@screens/AppNavigator/screens/Portfolio/components/AddressRow"; -import { DomainType } from "@contexts/DomainContext"; +import { useDomainContext } from "@contexts/DomainContext"; import { ConvertDirection } from "@screens/enum"; import { useTokenPrice } from "../hooks/TokenPrice"; import { ActiveUSDValueV2 } from "../../Loans/VaultDetail/components/ActiveUSDValueV2"; @@ -92,6 +92,7 @@ export function SendScreen({ route, navigation }: Props): JSX.Element { const DFIToken = useSelector((state: RootState) => DFITokenSelector(state.wallet), ); + const { domain } = useDomainContext(); const [token, setToken] = useState(route.params?.token); const [matchedAddress, setMatchedAddress] = useState< @@ -264,6 +265,7 @@ export function SendScreen({ route, navigation }: Props): JSX.Element { fee, toAddressLabel: matchedAddress?.label, addressType, + matchedAddress, }; if (isConversionRequired) { @@ -415,7 +417,7 @@ export function SendScreen({ route, navigation }: Props): JSX.Element { name: "AddressBookScreen", params: { selectedAddress: getValues("address"), - addressDomainType: DomainType.DVM, + addressDomainType: domain, onAddressSelect, }, merge: true, @@ -444,6 +446,8 @@ export function SendScreen({ route, navigation }: Props): JSX.Element { address={address} onMatchedAddress={setMatchedAddress} onAddressType={setAddressType} + matchedAddress={matchedAddress} + setMatchedAddress={setMatchedAddress} /> )} diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/TokenSelectionScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/TokenSelectionScreen.tsx index 2fa8b1dfe9..a38e6d64f7 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/TokenSelectionScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/TokenSelectionScreen.tsx @@ -27,6 +27,7 @@ import { SkeletonLoaderScreen, } from "@components/SkeletonLoader"; import { ListRenderItemInfo } from "@shopify/flash-list"; +import { DomainType, useDomainContext } from "@contexts/DomainContext"; import { PortfolioParamList } from "../PortfolioNavigator"; import { ActiveUSDValueV2 } from "../../Loans/VaultDetail/components/ActiveUSDValueV2"; import { TokenIcon } from "../components/TokenIcon"; @@ -51,9 +52,10 @@ export interface BottomSheetToken { export function TokenSelectionScreen(): JSX.Element { const { isLight } = useThemeContext(); + const { domain } = useDomainContext(); const navigation = useNavigation>(); const tokens = useSelector((state: RootState) => - tokensSelector(state.wallet) + tokensSelector(state.wallet), ); const { hasFetchedToken } = useSelector((state: RootState) => state.wallet); const [searchString, setSearchString] = useState(""); @@ -63,7 +65,13 @@ export function TokenSelectionScreen(): JSX.Element { const [isSearchFocus, setIsSearchFocus] = useState(false); const searchRef = useRef(); - const tokensWithBalance = getTokensWithBalance(tokens, getTokenPrice); + const filteredTokensByDomain = + domain === DomainType.EVM ? tokens.filter((t) => !t.isLPS) : tokens; + + const tokensWithBalance = getTokensWithBalance( + filteredTokensByDomain, + getTokenPrice, + ); const filteredTokensWithBalance = useMemo(() => { return filterTokensBySearchTerm(tokensWithBalance, debouncedSearchTerm); }, [tokensWithBalance, debouncedSearchTerm]); @@ -84,11 +92,14 @@ export function TokenSelectionScreen(): JSX.Element { return ( { navigation.navigate({ name: "SendScreen", params: { - token: tokens.find((t) => item.tokenId === t.id), + token: filteredTokensByDomain.find( + (t) => t.id === item.tokenId, + ), }, merge: true, }); @@ -118,7 +129,7 @@ export function TokenSelectionScreen(): JSX.Element { }} placeholder={translate( "screens/TokenSelectionScreen", - "Search token" + "Search token", )} showClearButton={debouncedSearchTerm !== ""} onClearInput={() => { @@ -158,7 +169,7 @@ export function TokenSelectionScreen(): JSX.Element { {translate( "screens/TokenSelectionScreen", "Search results for “{{searchTerm}}”", - { searchTerm: debouncedSearchTerm } + { searchTerm: debouncedSearchTerm }, )} )} @@ -179,11 +190,13 @@ export function TokenSelectionScreen(): JSX.Element { interface TokenSelectionRowProps { item: TokenSelectionItem; onPress: any; + domain: DomainType; } function TokenSelectionRow({ item, onPress, + domain, }: TokenSelectionRowProps): JSX.Element { return ( @@ -209,6 +222,7 @@ function TokenSelectionRow({ displaySymbol={item.token.displaySymbol} name={item.token.name} testID={item.token.displaySymbol} + isEvmDomain={domain === DomainType.EVM} /> @@ -242,7 +256,7 @@ function EmptyAsset({ return ( @@ -268,7 +282,7 @@ function EmptyAsset({ > {translate( "screens/TokenSelectionScreen", - "Add assets to get started" + "Add assets to get started", )} @@ -286,8 +300,8 @@ function getTokensWithBalance( getTokenPrice: ( symbol: string, amount: BigNumber, - isLPS?: boolean | undefined - ) => BigNumber + isLPS?: boolean | undefined, + ) => BigNumber, ): TokenSelectionItem[] { const reservedFees = 0.1; const filteredTokens: TokenSelectionItem[] = []; @@ -296,7 +310,7 @@ function getTokensWithBalance( const available = new BigNumber( t.displaySymbol === "DFI" ? new BigNumber(t.amount).minus(reservedFees).toFixed(8) - : t.amount + : t.amount, ); if (available.isLessThan(0) || t.id === "0" || t.id === "0_utxo") { return; @@ -318,17 +332,17 @@ function getTokensWithBalance( }); return filteredTokens.sort((a, b) => - b.usdAmount.minus(a.usdAmount).toNumber() + b.usdAmount.minus(a.usdAmount).toNumber(), ); } function filterTokensBySearchTerm( tokens: TokenSelectionItem[], - searchTerm: string + searchTerm: string, ): TokenSelectionItem[] { return tokens.filter((t) => [t.token.displaySymbol, t.token.name].some((searchItem) => - searchItem.toLowerCase().includes(searchTerm.trim().toLowerCase()) - ) + searchItem.toLowerCase().includes(searchTerm.trim().toLowerCase()), + ), ); } diff --git a/mobile-app/cypress/e2e/functional/wallet/portfolio/addresses.spec.ts b/mobile-app/cypress/e2e/functional/wallet/portfolio/addresses.spec.ts index ceb45d7770..dc8038ec59 100644 --- a/mobile-app/cypress/e2e/functional/wallet/portfolio/addresses.spec.ts +++ b/mobile-app/cypress/e2e/functional/wallet/portfolio/addresses.spec.ts @@ -19,6 +19,7 @@ function addLocalStorageFeatureFlag(): void { context("Wallet - Addresses", () => { let whale: WhaleApiClient; + let address: string; before(() => { addLocalStorageFeatureFlag(); @@ -92,6 +93,10 @@ context("Wallet - Addresses", () => { cy.getByTestID("bottomsheet-address-header").contains("EVM"); cy.getByTestID("close_bottom_sheet_button").click(); }); + + // Toggled back to DVM for next test + cy.getByTestID("domain_switch_EVM").should("exist"); + cy.getByTestID("domain_switch").click(); }); it("should be able to create new address when all available address are active", () => { @@ -159,10 +164,7 @@ context("Wallet - Addresses", () => { cy.getByTestID("receive_balance_button").click(); cy.getByTestID("address_text").contains(activeAddress); }); - }); - context("Wallet - Addresses transfer dfi between addresses", () => { - let address: string; it("should able to transfer dfi between addresses", () => { cy.getByTestID("bottom_tab_portfolio").click(); cy.getByTestID("switch_account_button") diff --git a/mobile-app/cypress/e2e/functional/wallet/portfolio/portfolio.spec.ts b/mobile-app/cypress/e2e/functional/wallet/portfolio/portfolio.spec.ts index 958e90b821..5f8085aa14 100644 --- a/mobile-app/cypress/e2e/functional/wallet/portfolio/portfolio.spec.ts +++ b/mobile-app/cypress/e2e/functional/wallet/portfolio/portfolio.spec.ts @@ -419,7 +419,7 @@ context("Wallet - Portfolio page", () => { cy.getByTestID("empty_tokens_title").should("have.text", "Empty portfolio"); cy.getByTestID("empty_tokens_subtitle").should( "have.text", - "Add DFI and other tokens to get started" + "Add DFI and other tokens to get started", ); }); }); @@ -598,7 +598,7 @@ context("Wallet - Portfolio - No balance", () => { it("should enabled send button", () => { cy.getByTestID("send_balance_button").should( "not.have.attr", - "aria-disabled" + "aria-disabled", ); }); @@ -650,7 +650,7 @@ context("Wallet - Portfolio - No balance", () => { .invoke("text") .then((price: string) => { expect(price).to.equal( - `$${new BigNumber(response.price.aggregated.amount).toFixed(2)}` + `$${new BigNumber(response.price.aggregated.amount).toFixed(2)}`, ); }); }); @@ -1024,7 +1024,7 @@ context( }); cy.getByTestID("toggle_sorting_assets").should("exist"); cy.getByTestID("portfolio_button_group_ALL_TOKENS_active").should( - "exist" + "exist", ); cy.getByTestID("portfolio_row_1").should("exist"); // dBTC = row 1 cy.getByTestID("portfolio_button_group_CRYPTO").click(); @@ -1034,21 +1034,21 @@ context( cy.getByTestID("portfolio_button_group_LP_TOKENS_active").should("exist"); cy.getByTestID("empty_tokens_title").should( "have.text", - "No LP tokens found" + "No LP tokens found", ); cy.getByTestID("empty_tokens_subtitle").should( "have.text", - "Add liquidity to get started" + "Add liquidity to get started", ); cy.getByTestID("portfolio_button_group_d_TOKENS").click(); cy.getByTestID("portfolio_button_group_d_TOKENS_active").should("exist"); cy.getByTestID("empty_tokens_title").should( "have.text", - "No dTokens found" + "No dTokens found", ); cy.getByTestID("empty_tokens_subtitle").should( "have.text", - "Mint dTokens to get started" + "Mint dTokens to get started", ); }); it("should exist in All tokens and dTokens tabs, should not exist in LP tokens and Crypto tabs", () => { @@ -1072,34 +1072,34 @@ context( cy.getByTestID("toggle_sorting_assets").should("exist"); cy.getByTestID("portfolio_button_group_ALL_TOKENS").click(); cy.getByTestID("portfolio_button_group_ALL_TOKENS_active").should( - "exist" + "exist", ); cy.getByTestID("portfolio_row_14").should("exist"); // DUSD = row 14 cy.getByTestID("portfolio_button_group_LP_TOKENS").click(); cy.getByTestID("portfolio_button_group_LP_TOKENS_active").should("exist"); cy.getByTestID("empty_tokens_title").should( "have.text", - "No LP tokens found" + "No LP tokens found", ); cy.getByTestID("empty_tokens_subtitle").should( "have.text", - "Add liquidity to get started" + "Add liquidity to get started", ); cy.getByTestID("portfolio_button_group_CRYPTO").click(); cy.getByTestID("portfolio_button_group_CRYPTO_active").should("exist"); cy.getByTestID("empty_tokens_title").should( "have.text", - "No crypto found" + "No crypto found", ); cy.getByTestID("empty_tokens_subtitle").should( "have.text", - "Add crypto to get started" + "Add crypto to get started", ); cy.getByTestID("portfolio_button_group_d_TOKENS").click(); cy.getByTestID("portfolio_button_group_d_TOKENS_active").should("exist"); cy.getByTestID("portfolio_row_14").should("exist"); // DUSD = row 14 }); - } + }, ); context("Wallet - Portfolio - Portfolio group tab", () => { @@ -1119,7 +1119,7 @@ context("Wallet - Portfolio - Portfolio group tab", () => { "$100,000.00", "$100,000.00", "$100,000.00", - "$1,000.00" + "$1,000.00", ); }); @@ -1133,7 +1133,7 @@ context("Wallet - Portfolio - Portfolio group tab", () => { "10.00 DFI", "10.00 DFI", "10.00 DFI", - "0.10000000 DFI" + "0.10000000 DFI", ); }); @@ -1147,7 +1147,7 @@ context("Wallet - Portfolio - Portfolio group tab", () => { "10.00 BTC", "10.00 BTC", "10.00 BTC", - "0.10000000 BTC" + "0.10000000 BTC", ); }); }); @@ -1180,7 +1180,7 @@ function checkPortfolioPageDenominationValues( DfiTotalBalUsdAmt: string, DfiAvailableAmt: string, BtcUsdAmt: string, - EthUsdAmt: string + EthUsdAmt: string, ): void { // TotalPortfolio cy.getByTestID("total_usd_amount").contains(totalUsdAmt); @@ -1213,7 +1213,7 @@ function checkPortfolioPageDenominationValues( function checkAssetsSortingOrder( sortedType: string, firstToken: string, - lastToken: string + lastToken: string, ): void { const containerTestID = '[data-testid="card_balance_row_container"]'; const arrowTestID = "your_assets_dropdown_arrow"; @@ -1282,7 +1282,7 @@ context( it("should sort assets based on Lowest value (DFI)", () => { checkAssetsSortingOrder("Lowest value (DFI)", "dLTC", "dBTC"); }); - } + }, ); function interceptTokensForSorting(data: {}): void { @@ -1311,7 +1311,7 @@ context( interceptTokensForSorting(addLPTokens); checkAssetsSortingOrder("Lowest value (DFI)", "dUSDT-DFI", "dBTC-DFI"); }); - } + }, ); context( @@ -1332,7 +1332,7 @@ context( interceptTokensForSorting(addCrypto); checkAssetsSortingOrder("Lowest value (DFI)", "dETH", "dBTC"); }); - } + }, ); context( @@ -1353,7 +1353,7 @@ context( interceptTokensForSorting(addDTokens); checkAssetsSortingOrder("Lowest value (DFI)", "DUSD", "dTD10"); }); - } + }, ); context( @@ -1373,7 +1373,7 @@ context( it("should sort assets based on Lowest value (BTC)", () => { checkAssetsSortingOrder("Lowest value (BTC)", "DUSD", "dBTC"); }); - } + }, ); context("Wallet - Portfolio - Skeleton Loader", () => { @@ -1548,3 +1548,54 @@ context("Wallet - Portfolio - portfolio", () => { }); }); }); + +context( + "Transfer domain - Wallet - Portfolio - Portfolio group tab - DFI currency", + () => { + before(() => { + cy.createEmptyWallet(true); + cy.getByTestID("header_settings").click(); + cy.getByTestID("bottom_tab_portfolio").click(); + + cy.intercept("**/address/**/tokens?size=*", { + body: { + data: [ + { + amount: "5.00000000", + displaySymbol: "dBTC", + id: "1", + isDAT: true, + isLPS: false, + isLoanToken: false, + name: "Playground BTC", + symbol: "BTC", + symbolKey: "BTC", + }, + { + id: "24", + amount: "10.00000000", + symbol: "TU10-DUSD", + symbolKey: "TU10-DUSD", + name: "Decentralized TU10-Decentralized USD", + isDAT: true, + isLPS: true, + isLoanToken: false, + displaySymbol: "dTU10-DUSD", + }, + ], + }, + }); + }); + + it("should display all tokens in dvm domain", () => { + cy.getByTestID("portfolio_row_1").should("exist"); + cy.getByTestID("portfolio_row_24").should("exist"); + }); + + it("should only display non LP tokens in evm domain", () => { + cy.getByTestID("domain_switch").click(); + cy.getByTestID("portfolio_row_1").should("exist"); + cy.getByTestID("portfolio_row_24").should("not.exist"); + }); + }, +); diff --git a/mobile-app/cypress/e2e/functional/wallet/portfolio/send.spec.ts b/mobile-app/cypress/e2e/functional/wallet/portfolio/send.spec.ts index e8831aba2c..cfaffcf72b 100644 --- a/mobile-app/cypress/e2e/functional/wallet/portfolio/send.spec.ts +++ b/mobile-app/cypress/e2e/functional/wallet/portfolio/send.spec.ts @@ -12,7 +12,7 @@ const validateAmountButtonResult = (value: string, usdValue: string): void => { }); cy.getByTestID("amount_input_in_usd").should( "have.text", - `$${usdValueWithThousandSep}` + `$${usdValueWithThousandSep}`, ); }; @@ -21,7 +21,7 @@ const validateInfotext = ( | "insufficient_balance" | "lp_warning" | "utxo_warning" - | "minimal_fee_warning" + | "minimal_fee_warning", ): void => { const infoText = { insufficient_balance: "Insufficient balance", @@ -86,7 +86,7 @@ context("Wallet - Send", () => { cy.getByTestID("amount_input").type("0.1"); cy.getByTestID("button_confirm_send_continue").should( "not.have.attr", - "disabled" + "disabled", ); cy.getByTestID("amount_input").clear(); @@ -94,17 +94,17 @@ context("Wallet - Send", () => { cy.getByTestID("address_input").type("z"); cy.getByTestID("address_error_text").should( "have.text", - "Invalid address. Make sure the address is correct to avoid irrecoverable losses" + "Invalid address. Make sure the address is correct to avoid irrecoverable losses", ); cy.getByTestID("button_confirm_send_continue").should( "have.attr", - "aria-disabled" + "aria-disabled", ); cy.wait(1000); cy.getByTestID("address_input_clear_button").click(); cy.getByTestID("button_confirm_send_continue").should( "have.attr", - "aria-disabled" + "aria-disabled", ); // Invalid amount - Character, over max amount, zero @@ -112,17 +112,17 @@ context("Wallet - Send", () => { cy.getByTestID("amount_input").clear().type("a"); cy.getByTestID("button_confirm_send_continue").should( "have.attr", - "aria-disabled" + "aria-disabled", ); cy.getByTestID("amount_input").clear().type("12"); cy.getByTestID("button_confirm_send_continue").should( "have.attr", - "aria-disabled" + "aria-disabled", ); cy.getByTestID("amount_input").clear().type("0"); cy.getByTestID("button_confirm_send_continue").should( "have.attr", - "aria-disabled" + "aria-disabled", ); }); @@ -133,7 +133,7 @@ context("Wallet - Send", () => { cy.getByTestID("token_search_input").clear().type("xxx").wait(2000); cy.getByTestID("empty_search_result_text").should( "have.text", - "Search results for “xxx”" + "Search results for “xxx”", ); cy.getByTestID("select_DFI").should("not.exist"); cy.getByTestID("select_dBTC-DFI").should("not.exist"); @@ -142,7 +142,7 @@ context("Wallet - Send", () => { cy.getByTestID("token_search_input").clear().type("btc").wait(2000); cy.getByTestID("empty_search_result_text").should( "have.text", - "Search results for “btc”" + "Search results for “btc”", ); cy.getByTestID("select_DFI").should("not.exist"); cy.getByTestID("select_dBTC-DFI").should("exist"); @@ -189,11 +189,11 @@ context("Wallet - Send", () => { cy.getByTestID(`${key}_amount_button`).click(); const availableBalance = new BigNumber(text); const inputAfterButtonPress = availableBalance.multipliedBy( - amountButtons[key] + amountButtons[key], ); validateAmountButtonResult( inputAfterButtonPress.toFixed(8), - inputAfterButtonPress.multipliedBy(10000).toFixed(2) + inputAfterButtonPress.multipliedBy(10000).toFixed(2), ); }); }); @@ -213,7 +213,7 @@ context("Wallet - Send", () => { cy.getByTestID("amount_input").clear().type(sendAmount); cy.getByTestID("button_confirm_send_continue").should( "not.have.attr", - "disabled" + "disabled", ); cy.getByTestID("button_confirm_send_continue").click(); // Check txn value @@ -222,14 +222,14 @@ context("Wallet - Send", () => { .then((textAmount) => { const amount = textAmount.replace(" DFI", ""); expect(new BigNumber(amount).toFixed(8)).eq( - new BigNumber(sendAmount).toFixed(8) + new BigNumber(sendAmount).toFixed(8), ); cy.getByTestID("text_fee") .invoke("text") .then((textFeeValue) => { const textFee = textFeeValue.replace(" DFI", ""); expect(new BigNumber(transactionFee).toFixed(8)).eq( - new BigNumber(textFee).toFixed(8) + new BigNumber(textFee).toFixed(8), ); // Check computed pending balance cy.getByTestID("resulting_DFI") @@ -237,14 +237,14 @@ context("Wallet - Send", () => { .then((pendingBalanceValue) => { const pendingBalance = pendingBalanceValue.replace( " DFI", - "" + "", ); expect( new BigNumber(balance) .plus(slippage) .minus(transactionFee) .minus(sendAmount) - .toFixed(8) + .toFixed(8), ).eq(pendingBalance); cy.getByTestID("button_cancel_send").click(); }); @@ -264,7 +264,7 @@ context("Wallet - Send", () => { cy.getByTestID("amount_input").clear().type("1"); cy.getByTestID("button_confirm_send_continue").should( "not.have.attr", - "disabled" + "disabled", ); cy.getByTestID("button_confirm_send_continue").click(); cy.getByTestID("confirm_title").contains("You are sending"); @@ -301,7 +301,7 @@ context("Wallet - Send", () => { cy.getByTestID("amount_input").clear().type(oldAmount); cy.getByTestID("button_confirm_send_continue").should( "not.have.attr", - "disabled" + "disabled", ); cy.getByTestID("button_confirm_send_continue").click(); @@ -309,7 +309,7 @@ context("Wallet - Send", () => { cy.getByTestID("confirm_title").contains("You are sending"); cy.getByTestID("text_send_amount").should( "have.text", - new BigNumber(oldAmount).toFixed(8) + new BigNumber(oldAmount).toFixed(8), ); // Address @@ -318,26 +318,26 @@ context("Wallet - Send", () => { // Transaction details cy.getByTestID("transaction_fee_label").should( "have.text", - "Transaction fee" + "Transaction fee", ); cy.getByTestID("transaction_fee_value").should("exist"); cy.getByTestID("text_amount_label").should("have.text", "Amount to send"); cy.getByTestID("text_amount").contains(oldAmount); const usdValueWithThousandSep = Number( - new BigNumber(oldAmount).multipliedBy(10000).toFixed(2) + new BigNumber(oldAmount).multipliedBy(10000).toFixed(2), ).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2, }); cy.getByTestID("text_amount_rhsUsdAmount").should( "have.text", - `$${usdValueWithThousandSep}` + `$${usdValueWithThousandSep}`, ); cy.getByTestID("button_confirm_send").click().wait(5000); // Check for authorization page description cy.getByTestID("txn_authorization_title").contains( - `Sending ${new BigNumber(oldAmount).toFixed(8)} DFI to ${oldAddress}` + `Sending ${new BigNumber(oldAmount).toFixed(8)} DFI to ${oldAddress}`, ); // Cancel send on authorisation page cy.getByTestID("cancel_authorization").click(); @@ -354,7 +354,7 @@ context("Wallet - Send", () => { cy.getByTestID("amount_input").clear().type(newAmount); cy.getByTestID("button_confirm_send_continue").should( "not.have.attr", - "disabled" + "disabled", ); cy.getByTestID("button_confirm_send_continue").click(); // Check address and amount in confirm send page @@ -364,7 +364,7 @@ context("Wallet - Send", () => { cy.getByTestID("button_confirm_send").click().wait(3000); // Check for authorization page description cy.getByTestID("txn_authorization_title").contains( - `Sending ${new BigNumber(newAmount).toFixed(8)} DFI to ${newAddress}` + `Sending ${new BigNumber(newAmount).toFixed(8)} DFI to ${newAddress}`, ); cy.closeOceanInterface(); }); @@ -404,7 +404,7 @@ context("Wallet - Send", () => { cy.getByTestID("button_confirm_send_continue").click(); cy.getByTestID("button_confirm_send").should( "have.attr", - "aria-disabled" + "aria-disabled", ); cy.getByTestID("lp_ack_switch").click(); cy.getByTestID("button_confirm_send").click().wait(3000); @@ -452,21 +452,21 @@ context("Wallet - Send - Max Values", () => { cy.getByTestID("MAX_amount_button").click(); cy.getByTestID("button_confirm_send_continue").should( "not.have.attr", - "disabled" + "disabled", ); cy.getByTestID("button_confirm_send_continue").click(); cy.getByTestID("confirm_title").contains("You are sending"); cy.getByTestID("text_send_amount").contains("9.90000000"); cy.getByTestID("text_amount").contains("9.90000000 DFI"); const usdValueWithThousandSep = Number( - new BigNumber(9.9).multipliedBy(10000).toFixed(2) + new BigNumber(9.9).multipliedBy(10000).toFixed(2), ).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2, }); cy.getByTestID("text_amount_rhsUsdAmount").should( "have.text", - `$${usdValueWithThousandSep}` + `$${usdValueWithThousandSep}`, ); cy.getByTestID("button_confirm_send").click().wait(3000); cy.closeOceanInterface(); @@ -516,40 +516,40 @@ context("Wallet - Send - with Conversion", () => { cy.getByTestID("amount_input").type("12"); cy.getByTestID("transaction_details_info_text").should( "contain", - "By continuing, the required amount of DFI will be converted" + "By continuing, the required amount of DFI will be converted", ); cy.getByTestID("button_confirm_send_continue").click(); cy.getByTestID("txn_authorization_title").contains( - `Convert ${new BigNumber("2.1").toFixed(8)} DFI to UTXO` + `Convert ${new BigNumber("2.1").toFixed(8)} DFI to UTXO`, ); cy.closeOceanInterface().wait(3000); cy.getByTestID("amount_to_convert_label").should( "have.text", - "Amount to convert" + "Amount to convert", ); cy.getByTestID("amount_to_convert_value").should( "contain", - "2.10000000 DFI" + "2.10000000 DFI", ); cy.getByTestID("conversion_status").should("have.text", "Converted"); cy.getByTestID("transaction_fee_label").should( "have.text", - "Transaction fee" + "Transaction fee", ); cy.getByTestID("transaction_fee_value").should("exist"); cy.getByTestID("text_amount").should("have.text", "12.00000000 DFI"); const usdValueWithThousandSep = Number( - new BigNumber(12).multipliedBy(10000).toFixed(2) + new BigNumber(12).multipliedBy(10000).toFixed(2), ).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2, }); cy.getByTestID("text_amount_rhsUsdAmount").should( "have.text", - `$${usdValueWithThousandSep}` + `$${usdValueWithThousandSep}`, ); cy.getByTestID("text_send_amount").should("contain", "12.00000000"); @@ -584,7 +584,7 @@ context("Wallet - Send - Switch token", () => { cy.getByTestID("select_DFI").click(); cy.getByTestID("button_confirm_send_continue").should( "have.attr", - "aria-disabled" + "aria-disabled", ); cy.getByTestID("max_value").should("have.text", "19.90000000"); cy.getByTestID("max_value_display_symbol").contains("DFI"); @@ -598,7 +598,7 @@ context("Wallet - Send - Switch token", () => { cy.getByTestID("max_value_display_symbol").contains("dBTC"); cy.getByTestID("button_confirm_send_continue").should( "have.attr", - "aria-disabled" + "aria-disabled", ); }); @@ -661,10 +661,10 @@ context("Wallet - Send - Address book", () => { cy.getByTestID("address_input_clear_button").click(); cy.getByTestID("address_book_button").click(); cy.getByTestID(`address_row_label_${index}_WHITELISTED`).contains( - labels[index] + labels[index], ); cy.getByTestID(`address_row_text_${index}_WHITELISTED`).contains( - addresses[index] + addresses[index], ); // cy.getByTestID('address_book_address_input').clear().type(addresses[index]).blur() }); @@ -704,15 +704,15 @@ context("Wallet - Send - Address book", () => { cy.getByTestID("address_book_address_input").type("fake address"); cy.getByTestID("save_address_label").should("have.attr", "aria-disabled"); cy.getByTestID("address_book_address_input_error").contains( - "Please enter a valid address" + "Please enter a valid address", ); cy.getByTestID("address_book_label_input_clear_button").click(); cy.getByTestID("address_book_label_input_error").contains( - "Required field. Please enter a label. Maximum of 40 characters." + "Required field. Please enter a label. Maximum of 40 characters.", ); cy.getByTestID("address_book_address_input").clear(); cy.getByTestID("address_book_address_input_error").contains( - "Please enter a valid address" + "Please enter a valid address", ); cy.getByTestID("save_address_label").should("have.attr", "aria-disabled"); }); @@ -758,7 +758,7 @@ context("Wallet - Send - Address book", () => { .type(addresses[index]) .blur(); cy.getByTestID("address_book_address_input_error").contains( - "This address already exists in your address book, please enter a different address" + "This address already exists in your address book, please enter a different address", ); cy.go("back"); }); @@ -776,7 +776,7 @@ context("Wallet - Send - Address book", () => { .type(walletAddress) .blur(); cy.getByTestID("address_book_address_input_error").contains( - "This address already exists in your address book, please enter a different address" + "This address already exists in your address book, please enter a different address", ); }); }); @@ -804,7 +804,7 @@ context("Wallet - Send - Address book", () => { .should("exist") .then(() => { const walletUserPreference = JSON.parse( - localStorage.getItem("Local.WALLET.SETTINGS") ?? "{}" + localStorage.getItem("Local.WALLET.SETTINGS") ?? "{}", ); expect(walletUserPreference).to.have.deep.property("addressBook", {}); }); @@ -827,9 +827,207 @@ context("Wallet - Send - Address book", () => { .should("exist") .then(() => { const walletUserPreference = JSON.parse( - localStorage.getItem("Local.WALLET.SETTINGS") ?? "{}" + localStorage.getItem("Local.WALLET.SETTINGS") ?? "{}", ); expect(walletUserPreference).to.have.deep.property("addressBook", {}); }); }); }); + +context.only("(dvm -> dvm) Wallet - Send - Address book", () => { + before(() => { + cy.createEmptyWallet(true); + cy.sendDFItoWallet().sendDFITokentoWallet().wait(6000); + cy.getByTestID("bottom_tab_portfolio").click(); + + // Portfolio -> Send action btn -> Address book + cy.getByTestID("action_button_group").should("exist"); + cy.getByTestID("send_balance_button").click().wait(3000); + cy.getByTestID("select_DFI").click().wait(3000); + cy.getByTestID("address_book_button").click(); + cy.getByTestID("address_row_0_WHITELISTED").should("not.exist"); + cy.getByTestID("button_add_address").should("exist"); + }); + + const labels = ["DVMAddress", "EVMAddress"]; + const addresses = [ + "bcrt1q8rfsfny80jx78cmk4rsa069e2ckp6rn83u6ut9", + "0x2DeC425BF3c289C9B7452aD54E2F9877F21e0316", + ]; + + function validateMatchAddress(address: string, label: string): void { + cy.getByTestID("address_input").contains(address); + if (label === labels[0]) { + cy.getByTestID("address_input_footer").contains(label); + } else { + cy.getByTestID("address_input_footer_evm").contains(label); + } + } + + function populateAddressBook(): void { + cy.createEmptyWallet(true); + cy.sendDFItoWallet().sendDFITokentoWallet().wait(6000); + cy.getByTestID("action_button_group").should("exist"); + cy.getByTestID("send_balance_button").click().wait(3000); + cy.getByTestID("select_DFI").click().wait(3000); + cy.getByTestID("address_book_button").click(); + cy.wrap(labels).each((_v, index: number) => { + if (index === 0) { + cy.getByTestID("button_add_address").click(); + } else { + cy.getByTestID("add_new_address").click(); + } + // Select EVM address type + if (index === 1) { + cy.getByTestID("address_book_address_type_EVM").click(); + } + cy.getByTestID("address_book_label_input").type(labels[index]); + cy.getByTestID("address_book_label_input_error").should("not.exist"); + cy.getByTestID("address_book_address_input") + .clear() + .type(addresses[index]) + .blur(); + cy.getByTestID("address_book_address_input_error").should("not.exist"); + cy.getByTestID("save_address_label").click().wait(1000); + cy.getByTestID("pin_authorize").type("000000").wait(2000); + validateMatchAddress(addresses[index], labels[index]); + cy.wait(1000); + cy.getByTestID("address_input_clear_button").click(); + cy.getByTestID("address_book_button").click(); + cy.getByTestID(`address_row_label_${index}_WHITELISTED`).contains( + labels[index], + ); + cy.getByTestID(`address_row_text_${index}_WHITELISTED`).contains( + addresses[index], + ); + // cy.getByTestID('address_book_address_input').clear().type(addresses[index]).blur() + }); + } + + it("should enable selection for both DVM and EVM whitelisted wallet addresses", () => { + populateAddressBook(); + + // check if cards are enabled + cy.getByTestID("address_row_0_WHITELISTED").should( + "not.have.attr", + "aria-disabled", + ); + cy.getByTestID("address_row_1_WHITELISTED").should( + "not.have.attr", + "aria-disabled", + ); + }); + + it.only("should display evm tag when EVM address is selected in DVM domain", () => { + populateAddressBook(); + cy.getByTestID("address_row_text_1_WHITELISTED").click(); + + // expect to see evm tag in address input + cy.getByTestID("address_input_footer_evm").contains(labels[1]); + + cy.getByTestID("amount_input").type("0.1"); + cy.getByTestID("button_confirm_send_continue").click(); + + // expect to see evm tag in confirm screen + cy.getByTestID("to_address_label_evm_tag").should("exist"); + }); +}); + +context("(evm -> dvm) Wallet - Send - Address book", () => { + const isEvmDomain = true; + before(() => { + cy.createEmptyWallet(true); + cy.sendDFItoWallet().sendDFITokentoWallet().wait(6000); + cy.getByTestID("bottom_tab_portfolio").click(); + + // Portfolio -> Send btn -> Address book + cy.getByTestID("action_button_group").should("exist"); + cy.getByTestID("send_balance_button").click().wait(3000); + cy.getByTestID("select_DFI").click().wait(3000); + cy.getByTestID("address_book_button").click(); + cy.getByTestID("address_row_0_WHITELISTED").should("not.exist"); + cy.getByTestID("button_add_address").should("exist"); + }); + + const labels = ["DVMAddress", "EVMAddress"]; + const addresses = [ + "bcrt1q8rfsfny80jx78cmk4rsa069e2ckp6rn83u6ut9", + "0x2DeC425BF3c289C9B7452aD54E2F9877F21e0316", + ]; + + function validateMatchAddress(address: string, label: string): void { + cy.getByTestID("address_input").contains(address); + if (label === labels[0]) { + cy.getByTestID("address_input_footer").contains(label); + } else { + cy.getByTestID("address_input_footer_evm").contains(label); + } + } + + function populateAddressBook(): void { + cy.createEmptyWallet(true); + cy.getByTestID("domain_switch").click(); // Switch to EVM domain + cy.sendDFItoWallet().sendDFITokentoWallet().wait(6000); + cy.getByTestID("action_button_group").should("exist"); + cy.getByTestID("send_balance_button").click().wait(3000); + cy.getByTestID("select_DFI").click().wait(3000); + cy.getByTestID("address_book_button").click(); + cy.wrap(labels).each((_v, index: number) => { + if (index === 0) { + cy.getByTestID("button_add_address").click(); + } else { + cy.getByTestID("add_new_address").click(); + } + if (isEvmDomain && index === 0) { + cy.getByTestID("address_book_address_type_DVM").click(); + } + cy.getByTestID("address_book_label_input").type(labels[index]); + cy.getByTestID("address_book_label_input_error").should("not.exist"); + cy.getByTestID("address_book_address_input") + .clear() + .type(addresses[index]) + .blur(); + cy.getByTestID("address_book_address_input_error").should("not.exist"); + cy.getByTestID("save_address_label").click().wait(1000); + cy.getByTestID("pin_authorize").type("000000").wait(2000); + validateMatchAddress(addresses[index], labels[index]); + cy.wait(1000); + cy.getByTestID("address_input_clear_button").click(); + cy.getByTestID("address_book_button").click(); + + // Skip test below since the order of address is rearranged + if (isEvmDomain && index === 1) { + return; + } + cy.getByTestID(`address_row_label_${index}_WHITELISTED`).contains( + labels[index], + ); + cy.getByTestID(`address_row_text_${index}_WHITELISTED`).contains( + addresses[index], + ); + + // cy.getByTestID('address_book_address_input').clear().type(addresses[index]).blur() + }); + } + + it("should enable selection only for DVM whitelisted wallet addresses in EVM domain", () => { + populateAddressBook(); + + // EVM address + cy.getByTestID("address_row_label_0_WHITELISTED").contains(labels[1]); + cy.getByTestID("address_row_text_0_WHITELISTED").contains(addresses[1]); + cy.getByTestID("address_row_0_WHITELISTED").should( + "have.attr", + "aria-disabled", + ); + + // DVM address + cy.getByTestID("address_row_label_1_WHITELISTED").contains(labels[0]); + cy.getByTestID("address_row_text_1_WHITELISTED").contains(addresses[0]); + cy.getByTestID("address_row_label_0_WHITELISTED_EVM_tag").should("exist"); + cy.getByTestID("address_row_1_WHITELISTED").should( + "not.have.attr", + "aria-disabled", + ); + }); +}); diff --git a/package-lock.json b/package-lock.json index 8f2b6b32cb..02b9219d15 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "@react-navigation/stack": "^6.3.17", "@reduxjs/toolkit": "^1.9.5", "@shopify/flash-list": "1.4.3", - "@waveshq/standard-defichain-jellyfishsdk": "^2.2.0", + "@waveshq/standard-defichain-jellyfishsdk": "^2.4.1", "@waveshq/walletkit-core": "^1.3.5", "@waveshq/walletkit-ui": "^1.3.5", "bignumber.js": "^9.1.1", diff --git a/package.json b/package.json index 34b145be52..fbadeb6730 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@react-navigation/stack": "^6.3.17", "@reduxjs/toolkit": "^1.9.5", "@shopify/flash-list": "1.4.3", - "@waveshq/standard-defichain-jellyfishsdk": "^2.2.0", + "@waveshq/standard-defichain-jellyfishsdk": "^2.4.1", "@waveshq/walletkit-core": "^1.3.5", "@waveshq/walletkit-ui": "^1.3.5", "bignumber.js": "^9.1.1",