diff --git a/.github/workflows/e2e-main.yml b/.github/workflows/e2e-main.yml
index 4ab61e54324..be9edc6721b 100644
--- a/.github/workflows/e2e-main.yml
+++ b/.github/workflows/e2e-main.yml
@@ -22,24 +22,21 @@ concurrency:
cancel-in-progress: true
jobs:
- # TODO: enable once we have at least one android-api-level below
- # android:
- # name: Android
- # strategy:
- # max-parallel: 2
- # fail-fast: false
- # matrix:
- # # TODO if/when more CI machines: enable Android sdk 21, 23, 29 and 31
- # # 21 is failing 9 specs
- # # 23 is failing ? spec(s)
- # # 31 is failing ? spec(s)
- # # 24 is currently failing all the time, disabling it for now
- # # 30 is not included as it runs on the merge queue
- # android-api-level: []
- # uses: ./.github/workflows/e2e-android.yml
- # with:
- # android-api-level: ${{ matrix.android-api-level }}
- # secrets: inherit
+ android:
+ name: Android
+ strategy:
+ max-parallel: 2
+ fail-fast: false
+ matrix:
+ # min supported API level is 24
+ # 24 is failing due to Let's Encrypt root certificate expiration
+ # 25 is failing (RET-1274)
+ # 26 is failing (RET-1275)
+ android-api-level: ['27']
+ uses: ./.github/workflows/e2e-android.yml
+ with:
+ android-api-level: ${{ matrix.android-api-level }}
+ secrets: inherit
ios:
name: iOS
strategy:
diff --git a/__mocks__/@react-native-firebase/dynamic-links.ts b/__mocks__/@react-native-firebase/dynamic-links.ts
index 2e6ee39ecc0..bdf511dfe44 100644
--- a/__mocks__/@react-native-firebase/dynamic-links.ts
+++ b/__mocks__/@react-native-firebase/dynamic-links.ts
@@ -1,11 +1,13 @@
const getInitialLink = jest.fn()
const buildShortLink = jest.fn()
const buildLink = jest.fn()
+const onLink = jest.fn()
export default function links() {
return {
getInitialLink,
buildShortLink,
buildLink,
+ onLink,
}
}
diff --git a/__mocks__/clevertap-react-native.ts b/__mocks__/clevertap-react-native.ts
index 4f8dbca1a2f..e26530fd0c5 100644
--- a/__mocks__/clevertap-react-native.ts
+++ b/__mocks__/clevertap-react-native.ts
@@ -2,4 +2,7 @@ export default {
setPushToken: jest.fn(),
createNotificationChannel: jest.fn(),
registerForPush: jest.fn(),
+ getInitialUrl: jest.fn(),
+ addListener: jest.fn(),
+ removeListener: jest.fn(),
}
diff --git a/android/app/build.gradle b/android/app/build.gradle
index ea1ae915662..9e28af28d2c 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -150,7 +150,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode appVersionCode
- versionName "1.100.0"
+ versionName "1.101.0"
multiDexEnabled true
testBuildType System.getProperty('testBuildType', 'debug')
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
diff --git a/android/gradle.properties b/android/gradle.properties
index 47b5778c8e5..4e41130e3f0 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -25,7 +25,7 @@ RELEASE_KEY_ALIAS=mobilestack-key-alias
# Setting this manually based on version number until we have this deploying via Cloud Build
# Example: v1.5.1 deployment number 1 = 1005001001 (1 005 001 001)
-VERSION_CODE=1021071684
+VERSION_CODE=1021071685
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
diff --git a/e2e/src/Discover.spec.js b/e2e/src/Discover.spec.js
index 59d2f94c7ac..7c7565bf931 100644
--- a/e2e/src/Discover.spec.js
+++ b/e2e/src/Discover.spec.js
@@ -1,6 +1,6 @@
import DappListDisplay from './usecases/DappListDisplay'
import { launchApp } from './utils/retries'
-import { quickOnboarding, scrollIntoView, waitForElementByIdAndTap } from './utils/utils'
+import { quickOnboarding, scrollIntoView, waitForElementById } from './utils/utils'
describe('Discover tab', () => {
beforeAll(async () => {
@@ -8,7 +8,7 @@ describe('Discover tab', () => {
// Relaunch app to ensure dapp list loads
// Needed for e2e tests otherwise dapp list is not loaded on first pass
await launchApp()
- await waitForElementByIdAndTap('Tab/Discover')
+ await waitForElementById('Tab/Discover', { tap: true })
await scrollIntoView('View All', 'DiscoverScrollView')
await element(by.text('View All')).tap()
diff --git a/e2e/src/QRScanner.spec.js b/e2e/src/QRScanner.spec.js
index bae0a69b825..a63e27858a0 100644
--- a/e2e/src/QRScanner.spec.js
+++ b/e2e/src/QRScanner.spec.js
@@ -1,5 +1,5 @@
import { reloadReactNative } from './utils/retries'
-import { quickOnboarding, waitForElementId } from './utils/utils'
+import { quickOnboarding, waitForElementById } from './utils/utils'
describe('Given QR Scanner', () => {
beforeAll(async () => {
@@ -9,30 +9,30 @@ describe('Given QR Scanner', () => {
describe('When opening QR scanner', () => {
it('Then should display QR code', async () => {
await reloadReactNative()
- await waitForElementId('HomeAction-Receive')
+ await waitForElementById('HomeAction-Receive')
await element(by.id('HomeAction-Receive')).tap()
- await waitForElementId('QRCode')
+ await waitForElementById('QRCode')
await expect(element(by.id('QRCode'))).toBeVisible()
})
it('Then should be able to toggle camera', async () => {
- await waitForElementId('Scan')
+ await waitForElementById('Scan')
await element(by.id('Scan')).tap()
- await waitForElementId('CameraScanInfo')
+ await waitForElementById('CameraScanInfo')
await expect(element(by.id('CameraScanInfo'))).toBeVisible()
})
it('Then should be able to toggle to QR code', async () => {
- await waitForElementId('My Code')
+ await waitForElementById('My Code')
await element(by.id('My Code')).tap()
- await waitForElementId('QRCode')
+ await waitForElementById('QRCode')
await expect(element(by.id('QRCode'))).toBeVisible()
})
it('Then should be able to close QR code scanner', async () => {
- await waitForElementId('Times')
+ await waitForElementById('Times')
await element(by.id('Times')).tap()
- await waitForElementId('HomeAction-Send')
+ await waitForElementById('HomeAction-Send')
await expect(element(by.id('HomeAction-Send'))).toBeVisible()
})
})
@@ -40,34 +40,34 @@ describe('Given QR Scanner', () => {
describe("When 'scanning' QR", () => {
beforeEach(async () => {
await reloadReactNative()
- await waitForElementId('HomeAction-Receive')
+ await waitForElementById('HomeAction-Receive')
await element(by.id('HomeAction-Receive')).tap()
- await waitForElementId('Scan')
+ await waitForElementById('Scan')
await element(by.id('Scan')).tap()
- await waitForElementId('CameraScanInfo')
+ await waitForElementById('CameraScanInfo')
await element(by.id('CameraScanInfo')).tap()
})
it('Then should be able to handle Celo pay QR', async () => {
- await waitForElementId('ManualInput')
+ await waitForElementById('ManualInput')
await element(by.id('ManualInput')).replaceText(
'celo://wallet/pay?address=0xe5F5363e31351C38ac82DBAdeaD91Fd5a7B08846'
)
- await waitForElementId('ManualSubmit')
+ await waitForElementById('ManualSubmit')
await element(by.id('ManualSubmit')).tap()
- await waitForElementId('SendEnterAmount/AmountOptions')
+ await waitForElementById('SendEnterAmount/AmountOptions')
await element(by.text('Done')).tap() // dismiss the keyboard to reveal the proceed button
await expect(element(by.id('SendEnterAmount/ReviewButton'))).toBeVisible()
})
it('Then should handle address only QR', async () => {
- await waitForElementId('ManualInput')
+ await waitForElementById('ManualInput')
await element(by.id('ManualInput')).replaceText('0xe5F5363e31351C38ac82DBAdeaD91Fd5a7B08846')
- await waitForElementId('ManualSubmit')
+ await waitForElementById('ManualSubmit')
await element(by.id('ManualSubmit')).tap()
- await waitForElementId('SendEnterAmount/AmountOptions')
+ await waitForElementById('SendEnterAmount/AmountOptions')
await element(by.text('Done')).tap() // dismiss the keyboard to reveal the proceed button
await expect(element(by.id('SendEnterAmount/ReviewButton'))).toBeVisible()
})
diff --git a/e2e/src/usecases/Assets.js b/e2e/src/usecases/Assets.js
index 14ed6c5d22e..9c8c952b978 100644
--- a/e2e/src/usecases/Assets.js
+++ b/e2e/src/usecases/Assets.js
@@ -6,19 +6,18 @@ import {
getDisplayAddress,
quickOnboarding,
scrollIntoViewByTestId,
- waitForElementByIdAndTap,
- waitForElementId,
+ waitForElementById,
} from '../utils/utils'
async function validateSendFlow(tokenSymbol) {
const recipientAddressDisplay = getDisplayAddress(DEFAULT_RECIPIENT_ADDRESS)
// navigate to send amount screen to ensure the expected token symbol is pre-selected
- await waitForElementByIdAndTap('SendSelectRecipientSearchInput')
+ await waitForElementById('SendSelectRecipientSearchInput', { tap: true })
await element(by.id('SendSelectRecipientSearchInput')).replaceText(DEFAULT_RECIPIENT_ADDRESS)
await element(by.id('SendSelectRecipientSearchInput')).tapReturnKey()
await expect(element(by.text(recipientAddressDisplay)).atIndex(0)).toBeVisible()
await element(by.text(recipientAddressDisplay)).atIndex(0).tap()
- await waitForElementByIdAndTap('SendOrInviteButton')
+ await waitForElementById('SendOrInviteButton', { tap: true })
await expect(
element(by.text(`${tokenSymbol} on Celo`).withAncestor(by.id('SendEnterAmount/TokenSelect')))
).toBeVisible()
@@ -89,29 +88,29 @@ export default Assets = () => {
})
it('navigates to wallet tab from home', async () => {
- await waitForElementByIdAndTap('Tab/Wallet')
- await waitForElementId('Assets/TabBar')
+ await waitForElementById('Tab/Wallet', { tap: true })
+ await waitForElementById('Assets/TabBar')
})
it('switching tabs displays corresponding assets', async () => {
await expect(element(by.id('TokenBalanceItem')).atIndex(0)).toBeVisible()
await element(by.id('Assets/TabBarItem')).atIndex(1).tap()
- await waitForElementId('Assets/NoNfts')
+ await waitForElementById('Assets/NoNfts')
await element(by.id('Assets/TabBarItem')).atIndex(0).tap()
await expect(element(by.id('TokenBalanceItem')).atIndex(0)).toBeVisible()
})
describe.each(tokens)('For $symbol', ({ symbol, tokenId, learnMore, actions, moreActions }) => {
it('navigates to asset details on tapping asset', async () => {
- await waitForElementByIdAndTap(`TokenBalanceItemTouchable/${tokenId}`)
- await waitForElementId('TokenDetails/AssetValue')
+ await waitForElementById(`TokenBalanceItemTouchable/${tokenId}`, { tap: true })
+ await waitForElementById('TokenDetails/AssetValue')
})
if (actions.includes('Send')) {
it('send action navigates to send flow', async () => {
await element(by.id('TokenDetails/Action/Send')).tap()
await validateSendFlow(symbol)
- await waitForElementId('TokenDetails/AssetValue')
+ await waitForElementById('TokenDetails/AssetValue')
})
}
@@ -119,54 +118,54 @@ export default Assets = () => {
it('add action navigates to add cico flow', async () => {
await element(by.id('TokenDetails/Action/Add')).tap()
await validateAddFlow(symbol)
- await waitForElementId('TokenDetails/AssetValue')
+ await waitForElementById('TokenDetails/AssetValue')
})
}
if (moreActions.includes('Send')) {
it('send action under more actions navigates to send flow', async () => {
await element(by.id('TokenDetails/Action/More')).tap()
- await waitForElementByIdAndTap('TokenDetailsMoreActions/Send')
+ await waitForElementById('TokenDetailsMoreActions/Send', { tap: true })
await validateSendFlow(symbol)
- await waitForElementId('TokenDetails/AssetValue')
+ await waitForElementById('TokenDetails/AssetValue')
})
}
if (moreActions.includes('Add')) {
it('add action under more actions navigates to add cico flow', async () => {
await element(by.id('TokenDetails/Action/More')).tap()
- await waitForElementByIdAndTap('TokenDetailsMoreActions/Add')
+ await waitForElementById('TokenDetailsMoreActions/Add', { tap: true })
await validateAddFlow(symbol)
- await waitForElementId('TokenDetails/AssetValue')
+ await waitForElementById('TokenDetails/AssetValue')
})
}
if (moreActions.includes('Withdraw')) {
it('withdraw action under more actions navigates to withdraw spend screen', async () => {
await element(by.id('TokenDetails/Action/More')).tap()
- await waitForElementByIdAndTap('TokenDetailsMoreActions/Withdraw')
- await waitForElementId('FiatExchangeTokenBalance')
+ await waitForElementById('TokenDetailsMoreActions/Withdraw', { tap: true })
+ await waitForElementById('FiatExchangeTokenBalance')
await element(by.id('BackChevron')).tap()
- await waitForElementId('TokenDetails/AssetValue')
+ await waitForElementById('TokenDetails/AssetValue')
})
}
if (learnMore) {
it('learn more navigates to coingecko page', async () => {
await scrollIntoViewByTestId('TokenDetails/LearnMore', 'TokenDetailsScrollView')
- await waitForElementByIdAndTap('TokenDetails/LearnMore')
- await waitForElementId('RNWebView')
+ await waitForElementById('TokenDetails/LearnMore', { tap: true })
+ await waitForElementById('RNWebView')
await waitFor(element(by.text('www.coingecko.com')))
.toBeVisible()
.withTimeout(10 * 1000)
await element(by.id('WebViewScreen/CloseButton')).tap()
- await waitForElementId('TokenBalanceItem')
+ await waitForElementById('TokenBalanceItem')
})
}
it('navigates back to Assets page', async () => {
await element(by.id('BackChevron')).tap()
- await waitForElementId('Assets/TabBar')
+ await waitForElementById('Assets/TabBar')
})
})
})
diff --git a/e2e/src/usecases/CeloEducation.js b/e2e/src/usecases/CeloEducation.js
index 612b85c74a2..3e436d10c8e 100644
--- a/e2e/src/usecases/CeloEducation.js
+++ b/e2e/src/usecases/CeloEducation.js
@@ -1,5 +1,5 @@
import { celoEducation } from '../utils/celoEducation'
-import { waitForElementByIdAndTap, waitForElementId } from '../utils/utils'
+import { waitForElementById } from '../utils/utils'
const swipeThrough = async (direction = 'left', swipes = 3) => {
for (let i = 0; i < swipes; i++) {
@@ -10,11 +10,11 @@ const swipeThrough = async (direction = 'left', swipes = 3) => {
const tapThrough = async (direction = 'forward', steps = 3) => {
if (direction === 'forward') {
for (let i = 0; i < steps; i++) {
- await waitForElementByIdAndTap('Education/progressButton')
+ await waitForElementById('Education/progressButton', { tap: true })
}
} else {
for (let i = 0; i < steps; i++) {
- await waitForElementByIdAndTap('Education/BackIcon')
+ await waitForElementById('Education/BackIcon', { tap: true })
}
}
}
@@ -27,8 +27,8 @@ const progressButtonCheck = async (text = 'Next', timeout = 10 * 1000) => {
export default CeloEducation = () => {
beforeAll(async () => {
- await waitForElementByIdAndTap('WalletHome/NotificationBell')
- await waitForElementId('NotificationView/celo_asset_education')
+ await waitForElementById('WalletHome/NotificationBell', { tap: true })
+ await waitForElementById('NotificationView/celo_asset_education')
await element(
by.text('Learn More').withAncestor(by.id('NotificationView/celo_asset_education'))
).tap()
@@ -36,10 +36,10 @@ export default CeloEducation = () => {
it('should be able to navigate with swipes', async () => {
await swipeThrough()
- await waitForElementId('Education/BackIcon')
+ await waitForElementById('Education/BackIcon')
await progressButtonCheck('Done')
await swipeThrough('right')
- await waitForElementId('Education/CloseIcon')
+ await waitForElementById('Education/CloseIcon')
await progressButtonCheck('Next')
})
@@ -47,13 +47,13 @@ export default CeloEducation = () => {
await tapThrough()
await progressButtonCheck('Done')
await tapThrough('back')
- await waitForElementId('Education/CloseIcon')
+ await waitForElementById('Education/CloseIcon')
await progressButtonCheck('Next')
})
it('should be able to close CELO education carousel', async () => {
- await waitForElementByIdAndTap('Education/CloseIcon')
- await waitForElementId('NotificationView/celo_asset_education')
+ await waitForElementById('Education/CloseIcon', { tap: true })
+ await waitForElementById('NotificationView/celo_asset_education')
})
it('should be able to complete CELO education carousel', async () => {
@@ -61,6 +61,6 @@ export default CeloEducation = () => {
by.text('Learn More').withAncestor(by.id('NotificationView/celo_asset_education'))
).tap()
await celoEducation()
- await waitForElementId('Tab/Home')
+ await waitForElementById('Tab/Home')
})
}
diff --git a/e2e/src/usecases/ChooseYourAdventure.js b/e2e/src/usecases/ChooseYourAdventure.js
index db0c4b9cb59..3dde31a5a3f 100644
--- a/e2e/src/usecases/ChooseYourAdventure.js
+++ b/e2e/src/usecases/ChooseYourAdventure.js
@@ -1,5 +1,5 @@
import { launchApp } from '../utils/retries'
-import { quickOnboarding, waitForElementByText, waitForElementId } from '../utils/utils'
+import { quickOnboarding, waitForElementById, waitForElementByText } from '../utils/utils'
export default ChooseYourAdventure = () => {
beforeEach(async () => {
@@ -20,36 +20,36 @@ export default ChooseYourAdventure = () => {
// Back should go to the home screen
await element(by.id('BackChevron')).tap()
- await waitForElementId('HomeAction-Send')
+ await waitForElementById('HomeAction-Send')
})
it('build your profile navigates to profile page', async () => {
await waitForElementByText({ text: 'Build your profile', tap: true })
// Check that we are on the profile page
- await waitForElementId('ProfileEditName')
+ await waitForElementById('ProfileEditName')
// Back should go to the home screen
await element(by.id('BackButton')).tap()
- await waitForElementId('HomeAction-Send')
+ await waitForElementById('HomeAction-Send')
})
it('add funds to your wallet navigates to home and opens the token bottom sheet', async () => {
await waitForElementByText({ text: 'Add funds to your wallet', tap: true })
// Check that we are on the bottom sheet
- await waitForElementId('TokenBottomSheet')
+ await waitForElementById('TokenBottomSheet')
// dismissing the bottom sheet should show home screen
await element(by.id('TokenBottomSheet')).swipe('down')
- await waitForElementId('HomeAction-Send')
+ await waitForElementById('HomeAction-Send')
})
it('explore earning opportunities navigates to stablecoins info page', async () => {
await waitForElementByText({ text: 'Explore earning opportunities', tap: true })
// Check that we are on the Earn On Your Stablecoins page
- await waitForElementId('EarnInfoScreen/Title')
+ await waitForElementById('EarnInfoScreen/Title')
await waitForElementByText({ text: 'Earn on your\ncrypto' })
})
}
diff --git a/e2e/src/usecases/HandleDeepLinkSend.js b/e2e/src/usecases/HandleDeepLinkSend.js
index 518d7732cd0..a84eb684d83 100644
--- a/e2e/src/usecases/HandleDeepLinkSend.js
+++ b/e2e/src/usecases/HandleDeepLinkSend.js
@@ -1,7 +1,7 @@
import jestExpect from 'expect'
import { E2E_TEST_FAUCET } from '../../scripts/consts'
import { launchApp, reloadReactNative } from '../utils/retries'
-import { enterPinUiIfNecessary, waitForElementByIdAndTap, waitForElementId } from '../utils/utils'
+import { enterPinUiIfNecessary, waitForElementById } from '../utils/utils'
const deepLinks = {
withoutAddress:
@@ -63,11 +63,14 @@ export default HandleDeepLinkSend = () => {
await launchDeepLink({
url: `celo://wallet/pay?address=${E2E_TEST_FAUCET}¤cyCode=USD&token=cUSD&displayName=TestFaucet`,
})
- await waitForElementId('SendEnterAmount/TokenSelect', 10_000)
+ await waitForElementById('SendEnterAmount/TokenSelect')
await expect(element(by.text('cUSD on Celo')).atIndex(0)).toBeVisible()
await element(by.id('SendEnterAmount/TokenAmountInput')).replaceText('0.01')
await element(by.id('SendEnterAmount/TokenAmountInput')).tapReturnKey()
- await waitForElementByIdAndTap('SendEnterAmount/ReviewButton', 30_000)
+ await waitForElementById('SendEnterAmount/ReviewButton', {
+ timeout: 30_000,
+ tap: true,
+ })
// Send Transaction
await element(by.id('ConfirmButton')).tap()
diff --git a/e2e/src/usecases/HomeFeed.js b/e2e/src/usecases/HomeFeed.js
index 33a7592ac72..4398e795fc6 100644
--- a/e2e/src/usecases/HomeFeed.js
+++ b/e2e/src/usecases/HomeFeed.js
@@ -1,11 +1,11 @@
import jestExpect from 'expect'
-import { waitForElementId } from '../utils/utils'
+import { waitForElementById } from '../utils/utils'
import { sleep } from '../../../src/utils/sleep'
export default HomeFeed = () => {
it('should show correct information on tap of feed item', async () => {
// Load Wallet Home
- await waitForElementId('WalletHome')
+ await waitForElementById('WalletHome')
const items = await element(by.id('TransferFeedItem')).getAttributes()
// Tap top TransferFeedItem
@@ -27,7 +27,7 @@ export default HomeFeed = () => {
} catch {}
// Load Wallet Home
- await waitForElementId('WalletHome')
+ await waitForElementById('WalletHome')
const startingItems = await element(by.id('TransferFeedItem')).getAttributes()
// Scroll to bottom - Android will scroll forever so we set a static value
diff --git a/e2e/src/usecases/NewAccountOnboarding.js b/e2e/src/usecases/NewAccountOnboarding.js
index 354fe5d61e7..e9fdb0cc754 100644
--- a/e2e/src/usecases/NewAccountOnboarding.js
+++ b/e2e/src/usecases/NewAccountOnboarding.js
@@ -5,8 +5,7 @@ import {
enterPinUi,
navigateToSecurity,
quickOnboarding,
- waitForElementByIdAndTap,
- waitForElementId,
+ waitForElementById,
} from '../utils/utils'
import jestExpect from 'expect'
@@ -15,8 +14,8 @@ const startBackupFromNotifications = async () => {
await element(by.id('WalletHome/NotificationBell')).tap()
await element(by.text('Back up now')).tap()
await enterPinUi()
- await waitForElementByIdAndTap('WalletSecurityPrimer/GetStarted')
- await waitForElementByIdAndTap('keylessBackupIntro/RecoveryPhrase')
+ await waitForElementById('WalletSecurityPrimer/GetStarted', { tap: true })
+ await waitForElementById('keylessBackupIntro/RecoveryPhrase', { tap: true })
await element(by.id('SetUpAccountKey')).tap()
// Go through education
@@ -65,13 +64,13 @@ export default NewAccountOnboarding = () => {
await element(by.id('PhoneVerificationSkipHeader')).tap()
// Choose your own adventure (CYA screen)
- await waitForElementByIdAndTap('ChooseYourAdventure/Later')
+ await waitForElementById('ChooseYourAdventure/Later', { tap: true })
// Arrived to Home screen
await arriveAtHomeScreen()
// Able to open settings
- await waitForElementByIdAndTap('WalletHome/SettingsGearButton')
+ await waitForElementById('WalletHome/SettingsGearButton', { tap: true })
await element(by.id('Times')).tap()
})
@@ -117,15 +116,15 @@ export default NewAccountOnboarding = () => {
})
it('Account Address shown in profile / menu', async () => {
- await waitForElementByIdAndTap('WalletHome/SettingsGearButton')
- await waitForElementByIdAndTap('SettingsMenu/Address')
+ await waitForElementById('WalletHome/SettingsGearButton', { tap: true })
+ await waitForElementById('SettingsMenu/Address', { tap: true })
const accountAddressElement = await element(by.id('address')).getAttributes()
const accountAddressText = accountAddressElement.text.replace(/\s/g, '')
testAccountAddress = accountAddressText
jestExpect(testAccountAddress).toMatch(/0x[0-9a-fA-F]{40}/)
await element(by.id('BackChevron')).tap()
- await waitForElementByIdAndTap('Times')
+ await waitForElementById('Times', { tap: true })
})
// After quiz completion recovery phrase should only be shown in settings and
@@ -135,10 +134,10 @@ export default NewAccountOnboarding = () => {
await expect(element(by.text('Back up now'))).not.toExist()
await element(by.id('BackChevron')).tap()
await navigateToSecurity()
- await waitForElementId('RecoveryPhrase')
+ await waitForElementById('RecoveryPhrase')
await element(by.id('RecoveryPhrase')).tap()
await enterPinUi()
- await waitForElementId('AccountKeyWordsContainer')
+ await waitForElementById('AccountKeyWordsContainer')
})
// Based off the flag set in src/firebase/remoteConfigValuesDefaults.e2e.ts
@@ -158,8 +157,8 @@ export default NewAccountOnboarding = () => {
},
})
await quickOnboarding({ mnemonic: testRecoveryPhrase, cloudBackupEnabled: true })
- await waitForElementByIdAndTap('WalletHome/SettingsGearButton')
- await waitForElementByIdAndTap('SettingsMenu/Address')
+ await waitForElementById('WalletHome/SettingsGearButton', { tap: true })
+ await waitForElementById('SettingsMenu/Address', { tap: true })
await expect(element(by.text(testAccountAddress))).toBeVisible()
})
diff --git a/e2e/src/usecases/OffRamps.js b/e2e/src/usecases/OffRamps.js
index b1d998a07c7..9061cc2908a 100644
--- a/e2e/src/usecases/OffRamps.js
+++ b/e2e/src/usecases/OffRamps.js
@@ -1,5 +1,5 @@
import { launchApp, reloadReactNative } from '../utils/retries'
-import { waitForElementId } from '../utils/utils'
+import { waitForElementById } from '../utils/utils'
export default offRamps = () => {
beforeAll(async () => {
@@ -7,9 +7,9 @@ export default offRamps = () => {
})
beforeEach(async () => {
await reloadReactNative()
- await waitForElementId('HomeActionsCarousel')
+ await waitForElementById('HomeActionsCarousel')
await element(by.id('HomeActionsCarousel')).scrollTo('right')
- await waitForElementId('HomeAction-Withdraw')
+ await waitForElementById('HomeAction-Withdraw')
await element(by.id('HomeAction-Withdraw')).tap()
})
@@ -20,7 +20,7 @@ export default offRamps = () => {
})
it('Then should display total balance', async () => {
- await waitForElementId('ViewBalances')
+ await waitForElementById('ViewBalances')
await element(by.id('ViewBalances')).tap()
await expect(element(by.id('AssetsTokenBalance'))).toBeVisible()
})
@@ -28,30 +28,30 @@ export default offRamps = () => {
describe('When Spend selected', () => {
beforeEach(async () => {
- await waitForElementId('spend')
+ await waitForElementById('spend')
await element(by.id('spend')).tap()
})
it('Then should be able to spend cUSD', async () => {
- await waitForElementId(`cUSDSymbol`)
+ await waitForElementById('cUSDSymbol')
await element(by.id(`cUSDSymbol`)).tap()
- await waitForElementId('RNWebView')
+ await waitForElementById('RNWebView')
await expect(element(by.text('Bidali'))).toBeVisible()
})
it('Then should be able to spend cEUR', async () => {
- await waitForElementId(`cEURSymbol`)
- await element(by.id(`cEURSymbol`)).tap()
+ await waitForElementById('cEURSymbol')
+ await element(by.id('cEURSymbol')).tap()
- await waitForElementId('RNWebView')
+ await waitForElementById('RNWebView')
await expect(element(by.text('Bidali'))).toBeVisible()
})
})
describe('When Withdraw Selected', () => {
beforeEach(async () => {
- await waitForElementId('cashOut')
+ await waitForElementById('cashOut')
await element(by.id('cashOut')).tap()
})
@@ -65,30 +65,30 @@ export default offRamps = () => {
`(
'Then should display at least $exchanges.minExpected $token exchange(s)',
async ({ token, exchanges }) => {
- await waitForElementId(`${token}Symbol`)
+ await waitForElementById(`${token}Symbol`)
await element(by.id(`${token}Symbol`)).tap()
- await waitForElementId('FiatExchangeInput')
+ await waitForElementById('FiatExchangeInput')
await element(by.id('FiatExchangeInput')).replaceText('2')
await element(by.id('FiatExchangeNextButton')).tap()
await expect(element(by.text('Select Withdraw Method'))).toBeVisible()
- await waitForElementId('Exchanges')
+ await waitForElementById('Exchanges')
await element(by.id('Exchanges')).tap()
- await waitForElementId('SendBar')
+ await waitForElementById('SendBar')
// Exchanges start at index 0
- await waitForElementId(`provider-${exchanges.minExpected - 1}`)
+ await waitForElementById(`provider-${exchanges.minExpected - 1}`)
}
)
it('Then Send To Address', async () => {
const randomAmount = `${(Math.random() * 10 ** -1).toFixed(3)}`
- await waitForElementId(`CELOSymbol`)
+ await waitForElementById('CELOSymbol')
await element(by.id(`CELOSymbol`)).tap()
- await waitForElementId('FiatExchangeInput')
+ await waitForElementById('FiatExchangeInput')
await element(by.id('FiatExchangeInput')).replaceText(`${randomAmount}`)
await element(by.id('FiatExchangeNextButton')).tap()
- await waitForElementId('Exchanges')
+ await waitForElementById('Exchanges')
await element(by.id('Exchanges')).tap()
await element(by.id('SendBar')).tap()
await waitFor(element(by.id('SendSelectRecipientSearchInput')))
diff --git a/e2e/src/usecases/OnRamps.js b/e2e/src/usecases/OnRamps.js
index bdb9a1a9203..22ceffa41c6 100644
--- a/e2e/src/usecases/OnRamps.js
+++ b/e2e/src/usecases/OnRamps.js
@@ -1,5 +1,5 @@
import { launchApp, reloadReactNative } from '../utils/retries'
-import { isElementVisible, waitForElementId } from '../utils/utils'
+import { isElementVisible, waitForElementById } from '../utils/utils'
export default onRamps = () => {
beforeAll(async () => {
@@ -7,7 +7,7 @@ export default onRamps = () => {
})
beforeEach(async () => {
await reloadReactNative()
- await waitForElementId('HomeAction-Add')
+ await waitForElementById('HomeAction-Add')
await element(by.id('HomeAction-Add')).tap()
})
@@ -21,10 +21,10 @@ export default onRamps = () => {
${'CELO'} | ${'20'}
${'CELO'} | ${'2'}
`('Then should display $token provider(s) for $$amount', async ({ token, amount }) => {
- await waitForElementId(`${token}Symbol`)
+ await waitForElementById(`${token}Symbol`)
await element(by.id(`${token}Symbol`)).tap()
- await waitForElementId('FiatExchangeInput')
+ await waitForElementById('FiatExchangeInput')
await element(by.id('FiatExchangeInput')).replaceText(`${amount}`)
await element(by.id('FiatExchangeNextButton')).tap()
await expect(element(by.text('Select Payment Method'))).toBeVisible()
diff --git a/e2e/src/usecases/PINChange.js b/e2e/src/usecases/PINChange.js
index aa73bdb6b23..c6f049a5280 100644
--- a/e2e/src/usecases/PINChange.js
+++ b/e2e/src/usecases/PINChange.js
@@ -1,13 +1,13 @@
import { sleep } from '../../../src/utils/sleep'
import { ALTERNATIVE_PIN, DEFAULT_PIN } from '../utils/consts'
import { reloadReactNative } from '../utils/retries'
-import { enterPinUi, navigateToSecurity, waitForElementId } from '../utils/utils'
+import { enterPinUi, navigateToSecurity, waitForElementById } from '../utils/utils'
export default ChangePIN = () => {
it('Then should be retain changed PIN', async () => {
await navigateToSecurity()
- await waitForElementId('ChangePIN')
+ await waitForElementById('ChangePIN')
await element(by.id('ChangePIN')).tap()
// Existing PIN is needed first
await sleep(500)
diff --git a/e2e/src/usecases/ResetAccount.js b/e2e/src/usecases/ResetAccount.js
index b4256e3ad01..525256ed6b4 100644
--- a/e2e/src/usecases/ResetAccount.js
+++ b/e2e/src/usecases/ResetAccount.js
@@ -1,6 +1,6 @@
import { E2E_WALLET_MNEMONIC } from 'react-native-dotenv'
import { reloadReactNative } from '../utils/retries'
-import { enterPinUiIfNecessary, navigateToSecurity, waitForElementId } from '../utils/utils'
+import { enterPinUiIfNecessary, navigateToSecurity, waitForElementById } from '../utils/utils'
export default ResetAccount = () => {
beforeEach(async () => {
@@ -32,7 +32,7 @@ export default ResetAccount = () => {
await element(by.id('backupKeySavedSwitch')).longPress()
await element(by.id('backupKeyContinue')).tap()
const mnemonic = E2E_WALLET_MNEMONIC.split(' ')
- await waitForElementId(`backupQuiz/${mnemonic[0]}`)
+ await waitForElementById(`backupQuiz/${mnemonic[0]}`)
for (const word of mnemonic) {
await element(by.id(`backupQuiz/${word}`)).tap()
}
@@ -42,7 +42,7 @@ export default ResetAccount = () => {
// TODO: Figure out a way to confirm and test that the app goes to the onboarding
// screen on next open.
// await element(by.id('ConfirmAccountRemovalModal/PrimaryAction')).tap()
- await waitForElementId('ConfirmAccountRemovalModal/PrimaryAction')
+ await waitForElementById('ConfirmAccountRemovalModal/PrimaryAction')
await expect(element(by.id('ConfirmAccountRemovalModal/PrimaryAction'))).toBeVisible()
})
}
diff --git a/e2e/src/usecases/RestoreAccountOnboarding.js b/e2e/src/usecases/RestoreAccountOnboarding.js
index 9efc9ac3560..21254fa8fbe 100644
--- a/e2e/src/usecases/RestoreAccountOnboarding.js
+++ b/e2e/src/usecases/RestoreAccountOnboarding.js
@@ -1,7 +1,7 @@
import { E2E_WALLET_12_WORDS_MNEMONIC, E2E_WALLET_MNEMONIC } from 'react-native-dotenv'
import { WALLET_12_WORDS_ADDRESS, WALLET_ADDRESS } from '../utils/consts'
import { launchApp } from '../utils/retries'
-import { enterPinUi, scrollIntoView, waitForElementByIdAndTap } from '../utils/utils'
+import { enterPinUi, scrollIntoView, waitForElementById } from '../utils/utils'
export default RestoreAccountOnboarding = () => {
beforeEach(async () => {
@@ -51,23 +51,23 @@ export default RestoreAccountOnboarding = () => {
if (!walletFunded) {
// case where account not funded yet. dismiss zero balance modal to continue with onboarding.
- await waitForElementByIdAndTap('ConfirmUseAccountDialog/PrimaryAction')
+ await waitForElementById('ConfirmUseAccountDialog/PrimaryAction', { tap: true })
}
if (!verifiedPhoneNumber) {
// case where phone verification is required. skip it.
- await waitForElementByIdAndTap('PhoneVerificationSkipHeader')
+ await waitForElementById('PhoneVerificationSkipHeader', { tap: true })
}
// Choose your own adventure (CYA screen)
- await waitForElementByIdAndTap('ChooseYourAdventure/Later')
+ await waitForElementById('ChooseYourAdventure/Later', { tap: true })
// verify that we land on the home screen
await expect(element(by.id('HomeAction-Send'))).toBeVisible()
// verify that the correct account was restored
- await waitForElementByIdAndTap('WalletHome/SettingsGearButton')
- await waitForElementByIdAndTap('SettingsMenu/Address')
+ await waitForElementById('WalletHome/SettingsGearButton', { tap: true })
+ await waitForElementById('SettingsMenu/Address', { tap: true })
await expect(element(by.text(walletAddress))).toBeVisible()
}
diff --git a/e2e/src/usecases/SecureSend.js b/e2e/src/usecases/SecureSend.js
index 4fd7207b7b9..5669a4f12ca 100644
--- a/e2e/src/usecases/SecureSend.js
+++ b/e2e/src/usecases/SecureSend.js
@@ -10,8 +10,7 @@ import {
fundWallet,
quickOnboarding,
scrollIntoView,
- waitForElementByIdAndTap,
- waitForElementId,
+ waitForElementById,
} from '../utils/utils'
const AMOUNT_TO_SEND = '0.01'
@@ -32,17 +31,20 @@ export default SecureSend = () => {
})
it('Send cUSD to phone number with multiple mappings', async () => {
- await waitForElementByIdAndTap('HomeAction-Send', 30_000)
- await waitForElementByIdAndTap('SendSelectRecipientSearchInput', 3000)
+ await waitForElementById('HomeAction-Send', { timeout: 30_000, tap: true })
+ await waitForElementById('SendSelectRecipientSearchInput', {
+ timeout: 3000,
+ tap: true,
+ })
await element(by.id('SendSelectRecipientSearchInput')).replaceText(
WALLET_MULTIPLE_VERIFIED_PHONE_NUMBER
)
await element(by.id('RecipientItem')).tap()
- await waitForElementByIdAndTap('SendOrInviteButton', 30_000)
+ await waitForElementById('SendOrInviteButton', { timeout: 30_000, tap: true })
// Use the last digits of the account to confirm the sender.
- await waitForElementByIdAndTap('confirmAccountButton', 30_000)
+ await waitForElementById('confirmAccountButton', { timeout: 30_000, tap: true })
for (let index = 0; index < 4; index++) {
const character = WALLET_MULTIPLE_VERIFIED_ADDRESS.charAt(
WALLET_MULTIPLE_VERIFIED_ADDRESS.length - (4 - index)
@@ -55,8 +57,11 @@ export default SecureSend = () => {
await element(by.id('ConfirmAccountButton')).tap()
// Select the currency
- await waitForElementByIdAndTap('SendEnterAmount/TokenSelect', 30_000)
- await waitForElementByIdAndTap('cUSDSymbol', 30_000)
+ await waitForElementById('SendEnterAmount/TokenSelect', {
+ timeout: 30_000,
+ tap: true,
+ })
+ await waitForElementById('cUSDSymbol', { timeout: 30_000, tap: true })
// Enter the amount and review
await element(by.id('SendEnterAmount/TokenAmountInput')).tap()
@@ -69,7 +74,7 @@ export default SecureSend = () => {
await enterPinUiIfNecessary()
// Return to home screen.
- await waitForElementId('HomeAction-Send', 30_000)
+ await waitForElementById('HomeAction-Send', { timeout: 30_000 })
})
})
}
diff --git a/e2e/src/usecases/Send.js b/e2e/src/usecases/Send.js
index d4afa9b7b45..c529210d56b 100644
--- a/e2e/src/usecases/Send.js
+++ b/e2e/src/usecases/Send.js
@@ -10,8 +10,7 @@ import {
getDisplayAddress,
isElementVisible,
quickOnboarding,
- waitForElementByIdAndTap,
- waitForElementId,
+ waitForElementById,
} from '../utils/utils'
export default Send = () => {
@@ -26,12 +25,15 @@ export default Send = () => {
})
it('Then should navigate to send search input from home action', async () => {
- await waitForElementByIdAndTap('HomeAction-Send', 30_000)
- await waitForElementId('SendSelectRecipientSearchInput', 30_000)
+ await waitForElementById('HomeAction-Send', { timeout: 30_000, tap: true })
+ await waitForElementById('SendSelectRecipientSearchInput', { timeout: 30_000 })
})
it('Then should be able to enter an address', async () => {
- await waitForElementByIdAndTap('SendSelectRecipientSearchInput', 30_000)
+ await waitForElementById('SendSelectRecipientSearchInput', {
+ timeout: 30_000,
+ tap: true,
+ })
await element(by.id('SendSelectRecipientSearchInput')).replaceText(DEFAULT_RECIPIENT_ADDRESS)
await element(by.id('SendSelectRecipientSearchInput')).tapReturnKey()
await expect(element(by.text(recipientAddressDisplay)).atIndex(0)).toBeVisible()
@@ -39,12 +41,12 @@ export default Send = () => {
it('Then tapping a recipient should show send button', async () => {
await element(by.text(recipientAddressDisplay)).atIndex(0).tap()
- await waitForElementId('SendOrInviteButton', 30_000)
+ await waitForElementById('SendOrInviteButton', { timeout: 30_000 })
})
it('Then tapping send button should navigate to Send Enter Amount screen', async () => {
await element(by.id('SendOrInviteButton')).tap()
- await waitForElementId('SendEnterAmount/TokenAmountInput', 30_000)
+ await waitForElementById('SendEnterAmount/TokenAmountInput', { timeout: 30_000 })
})
it('Then should be able to change token', async () => {
@@ -60,10 +62,16 @@ export default Send = () => {
})
it('Then should be able to enter amount and navigate to review screen', async () => {
- await waitForElementByIdAndTap('SendEnterAmount/TokenAmountInput', 30_000)
+ await waitForElementById('SendEnterAmount/TokenAmountInput', {
+ timeout: 30_000,
+ tap: true,
+ })
await element(by.id('SendEnterAmount/TokenAmountInput')).replaceText('0.02')
await element(by.id('SendEnterAmount/TokenAmountInput')).tapReturnKey()
- await waitForElementByIdAndTap('SendEnterAmount/ReviewButton', 30_000)
+ await waitForElementById('SendEnterAmount/ReviewButton', {
+ timeout: 30_000,
+ tap: true,
+ })
await isElementVisible('ConfirmButton')
})
@@ -75,19 +83,25 @@ export default Send = () => {
await element(by.id('BackChevron')).tap()
await isElementVisible('SendEnterAmount/ReviewButton')
await element(by.id('SendEnterAmount/TokenAmountInput')).tap()
- await waitForElementByIdAndTap('SendEnterAmount/TokenAmountInput', 30_000)
+ await waitForElementById('SendEnterAmount/TokenAmountInput', {
+ timeout: 30_000,
+ tap: true,
+ })
await element(by.id('SendEnterAmount/TokenAmountInput')).replaceText('0.01')
await element(by.id('SendEnterAmount/TokenAmountInput')).tapReturnKey()
- await waitForElementByIdAndTap('SendEnterAmount/ReviewButton', 30_000)
+ await waitForElementById('SendEnterAmount/ReviewButton', {
+ timeout: 30_000,
+ tap: true,
+ })
let amount = await element(by.id('SendAmount')).getAttributes()
jestExpect(amount.text).toEqual('0.01 cEUR')
})
it('Then should be able to send', async () => {
- await waitForElementByIdAndTap('ConfirmButton', 30_000)
+ await waitForElementById('ConfirmButton', { timeout: 30_000, tap: true })
await enterPinUiIfNecessary()
await expect(element(by.text('Transaction failed, please retry'))).not.toBeVisible()
- await waitForElementId('HomeAction-Send', 30_000)
+ await waitForElementById('HomeAction-Send', { timeout: 30_000 })
})
})
@@ -97,7 +111,7 @@ export default Send = () => {
})
it('Then should navigate to send search input from home action', async () => {
- await waitForElementByIdAndTap('HomeAction-Send', 30_000)
+ await waitForElementById('HomeAction-Send', { timeout: 30_000, tap: true })
await waitFor(element(by.text(recipientAddressDisplay)))
.toBeVisible()
.withTimeout(10_000)
@@ -105,7 +119,7 @@ export default Send = () => {
it('Then should be able to click on recent recipient', async () => {
await element(by.text(recipientAddressDisplay)).atIndex(0).tap()
- await waitForElementId('SendEnterAmount/TokenAmountInput', 30_000)
+ await waitForElementById('SendEnterAmount/TokenAmountInput', { timeout: 30_000 })
})
it('Then should be able to choose token', async () => {
@@ -115,10 +129,16 @@ export default Send = () => {
})
it('Then should be able to enter amount and navigate to review screen', async () => {
- await waitForElementByIdAndTap('SendEnterAmount/TokenAmountInput', 30_000)
+ await waitForElementById('SendEnterAmount/TokenAmountInput', {
+ timeout: 30_000,
+ tap: true,
+ })
await element(by.id('SendEnterAmount/TokenAmountInput')).replaceText('0.01')
await element(by.id('SendEnterAmount/TokenAmountInput')).tapReturnKey()
- await waitForElementByIdAndTap('SendEnterAmount/ReviewButton', 30_000)
+ await waitForElementById('SendEnterAmount/ReviewButton', {
+ timeout: 30_000,
+ tap: true,
+ })
await isElementVisible('ConfirmButton')
})
@@ -130,7 +150,7 @@ export default Send = () => {
await element(by.id('ConfirmButton')).tap()
await enterPinUiIfNecessary()
await expect(element(by.text('Transaction failed, please retry'))).not.toBeVisible()
- await waitForElementId('HomeAction-Send', 30_000)
+ await waitForElementById('HomeAction-Send', { timeout: 30_000 })
})
})
@@ -141,12 +161,15 @@ export default Send = () => {
})
it('Then should navigate to send search input from home action', async () => {
- await waitForElementByIdAndTap('HomeAction-Send', 30_000)
- await waitForElementId('SendSelectRecipientSearchInput', 10_000)
+ await waitForElementById('HomeAction-Send', { timeout: 30_000, tap: true })
+ await waitForElementById('SendSelectRecipientSearchInput', { timeout: 30_000 })
})
it('Then should be able to enter a phone number', async () => {
- await waitForElementByIdAndTap('SendSelectRecipientSearchInput', 30_000)
+ await waitForElementById('SendSelectRecipientSearchInput', {
+ timeout: 30_000,
+ tap: true,
+ })
await element(by.id('SendSelectRecipientSearchInput')).typeText(
WALLET_SINGLE_VERIFIED_PHONE_NUMBER
)
@@ -156,12 +179,12 @@ export default Send = () => {
it('Then tapping a recipient should show send button', async () => {
await element(by.id('RecipientItem')).atIndex(0).tap()
- await waitForElementId('SendOrInviteButton', 30_000)
+ await waitForElementById('SendOrInviteButton', { timeout: 30_000 })
})
it('Then tapping send button should navigate to Send Enter Amount screen', async () => {
await element(by.id('SendOrInviteButton')).tap()
- await waitForElementId('SendEnterAmount/TokenAmountInput', 30_000)
+ await waitForElementById('SendEnterAmount/TokenAmountInput', { timeout: 30_000 })
})
it('Then should be able to select token', async () => {
@@ -171,10 +194,16 @@ export default Send = () => {
})
it('Then should be able to enter amount and navigate to review screen', async () => {
- await waitForElementByIdAndTap('SendEnterAmount/TokenAmountInput', 30_000)
+ await waitForElementById('SendEnterAmount/TokenAmountInput', {
+ timeout: 30_000,
+ tap: true,
+ })
await element(by.id('SendEnterAmount/TokenAmountInput')).replaceText('0.01')
await element(by.id('SendEnterAmount/TokenAmountInput')).tapReturnKey()
- await waitForElementByIdAndTap('SendEnterAmount/ReviewButton', 30_000)
+ await waitForElementById('SendEnterAmount/ReviewButton', {
+ timeout: 30_000,
+ tap: true,
+ })
await isElementVisible('ConfirmButton')
})
@@ -186,7 +215,7 @@ export default Send = () => {
await element(by.id('ConfirmButton')).tap()
await enterPinUiIfNecessary()
await expect(element(by.text('Transaction failed, please retry'))).not.toBeVisible()
- await waitForElementId('HomeAction-Send', 30_000)
+ await waitForElementById('HomeAction-Send', { timeout: 30_000 })
})
})
}
diff --git a/e2e/src/usecases/Settings.js b/e2e/src/usecases/Settings.js
index ade5313a4e3..9b23b94f426 100644
--- a/e2e/src/usecases/Settings.js
+++ b/e2e/src/usecases/Settings.js
@@ -5,7 +5,7 @@ import {
navigateToPreferences,
navigateToProfile,
scrollIntoView,
- waitForElementByIdAndTap,
+ waitForElementById,
} from '../utils/utils'
const faker = require('@faker-js/faker')
@@ -29,7 +29,7 @@ export default Settings = () => {
.toBeVisible()
.withTimeout(1000 * 10)
await dismissBanners()
- await waitForElementByIdAndTap('BackChevron')
+ await waitForElementById('BackChevron', { tap: true })
// TODO replace this with an ID selector
await expect(element(by.text(`${randomName}`))).toBeVisible()
})
diff --git a/e2e/src/usecases/Support.js b/e2e/src/usecases/Support.js
index dd8ce1dfbd0..00fb0553b84 100644
--- a/e2e/src/usecases/Support.js
+++ b/e2e/src/usecases/Support.js
@@ -1,5 +1,5 @@
import { reloadReactNative } from '../utils/retries'
-import { waitForElementByIdAndTap } from '../utils/utils'
+import { waitForElementById } from '../utils/utils'
export default Support = () => {
beforeEach(async () => {
@@ -32,8 +32,8 @@ export default Support = () => {
}
it('Send Message to Support', async () => {
- await waitForElementByIdAndTap('WalletHome/SettingsGearButton')
- await waitForElementByIdAndTap('SettingsMenu/Help')
+ await waitForElementById('WalletHome/SettingsGearButton', { tap: true })
+ await waitForElementById('SettingsMenu/Help', { tap: true })
await waitFor(element(by.id('SupportContactLink')))
.toBeVisible()
.withTimeout(10000)
diff --git a/e2e/src/usecases/WalletConnectV2.js b/e2e/src/usecases/WalletConnectV2.js
index 82049e852a2..9a21853fc5e 100644
--- a/e2e/src/usecases/WalletConnectV2.js
+++ b/e2e/src/usecases/WalletConnectV2.js
@@ -15,7 +15,7 @@ import { sleep } from '../../../src/utils/sleep'
import WALLET_ADDRESS from '../utils/consts'
import { formatUri, utf8ToHex } from '../utils/encoding'
import { launchApp } from '../utils/retries'
-import { enterPinUiIfNecessary, waitForElementByIdAndTap } from '../utils/utils'
+import { enterPinUiIfNecessary, waitForElementById } from '../utils/utils'
import jestExpect from 'expect'
@@ -357,7 +357,7 @@ export default WalletConnect = () => {
})
it('Then should be able to disconnect a session', async () => {
- await waitForElementByIdAndTap('WalletHome/SettingsGearButton')
+ await waitForElementById('WalletHome/SettingsGearButton', { tap: true })
await element(by.id('SettingsMenu/ConnectedDapps')).tap()
await element(by.text('Tap to Disconnect')).tap()
await element(by.text('Disconnect')).tap()
diff --git a/e2e/src/utils/dappList.js b/e2e/src/utils/dappList.js
index 69e047e133b..c4677d0a3e6 100644
--- a/e2e/src/utils/dappList.js
+++ b/e2e/src/utils/dappList.js
@@ -1,5 +1,5 @@
import fetch from 'node-fetch'
-import { waitForElementId } from './utils'
+import { waitForElementById } from './utils'
/**
* From the home screen, navigate to the dapp explorer screen
@@ -8,13 +8,9 @@ import { waitForElementId } from './utils'
*/
export async function navigateToDappList() {
await device.disableSynchronization()
- await waitForElementId('Hamburger')
- await element(by.id('Hamburger')).tap()
- await waitForElementId('dapps-explorer-icon')
- await element(by.id('dapps-explorer-icon')).tap()
- await waitFor(element(by.id('DAppsExplorerScreen/DappsList')))
- .toExist()
- .withTimeout(10 * 1000)
+ await waitForElementById('Hamburger', { tap: true })
+ await waitForElementById('dapps-explorer-icon', { tap: true })
+ await waitForElementById('DAppsExplorerScreen/DappsList')
await device.enableSynchronization()
}
@@ -22,10 +18,8 @@ export async function navigateToDappList() {
* From the drawer navigate to home screen
*/
export async function navigateToHome() {
- await waitForElementId('Hamburger')
- await element(by.id('Hamburger')).tap()
- await waitForElementId('Home')
- await element(by.id('Home')).tap()
+ await waitForElementById('Hamburger', { tap: true })
+ await waitForElementById('Home', { tap: true })
}
/**
diff --git a/e2e/src/utils/utils.js b/e2e/src/utils/utils.js
index 2a573711ae4..d0791147c45 100644
--- a/e2e/src/utils/utils.js
+++ b/e2e/src/utils/utils.js
@@ -120,34 +120,24 @@ export async function isElementVisible(elementId, index) {
return false
}
}
-/**
- * Wait for an element to be visible for at least set amount of time
- * @param {string} elementId testID of the element to wait for
- * @param {number} timeout timeout in milliseconds
- */
-export async function waitForElementId(elementId, timeout = 10 * 1000) {
+
+export async function waitForElementById(testID, { timeout = 10000, index = 0, tap = false } = {}) {
try {
- await waitFor(element(by.id(elementId)))
- .toBeVisible()
- .withTimeout(timeout)
+ const elementMatcher =
+ index === 0 ? element(by.id(testID)) : element(by.id(testID)).atIndex(index)
+
+ await waitFor(elementMatcher).toBeVisible().withTimeout(timeout)
+
+ if (tap) {
+ index === 0
+ ? await element(by.id(testID)).tap()
+ : await element(by.id(testID)).atIndex(index).tap()
+ }
} catch {
- throw new Error(`Element with testID '${elementId}' not found`)
+ throw new Error(`Element with testID '${testID}' not found`)
}
}
-/**
- * Wait for an element to be visible and then tap it
- * @param {string} elementId testID of the element to wait for
- * @param {number} timeout timeout in milliseconds
- * @param {number} index index of the element to tap
- */
-export async function waitForElementByIdAndTap(elementId, timeout = 10 * 1000, index = 0) {
- await waitForElementId(elementId, timeout)
- index === 0
- ? await element(by.id(elementId)).tap()
- : await element(by.id(elementId)).atIndex(index).tap()
-}
-
export async function quickOnboarding({
mnemonic = E2E_WALLET_MNEMONIC,
cloudBackupEnabled = false,
@@ -169,7 +159,12 @@ export async function quickOnboarding({
// Verify pin
await enterPinUi()
- if (cloudBackupEnabled) await waitForElementByIdAndTap('ImportSelect/Mnemonic')
+ if (cloudBackupEnabled) {
+ await waitForElementByText({
+ text: 'From recovery phrase',
+ tap: true,
+ })
+ }
// Restore existing wallet
await waitFor(element(by.id('connectingToCelo')))
@@ -177,7 +172,10 @@ export async function quickOnboarding({
.withTimeout(20000)
// Input Wallet Backup Key
- await waitForElementByIdAndTap('ImportWalletBackupKeyInputField')
+ await waitForElementById('ImportWalletBackupKeyInputField', {
+ tap: true,
+ })
+
await element(by.id('ImportWalletBackupKeyInputField')).replaceText(mnemonic)
if (device.getPlatform() === 'ios') {
// On iOS, type one more space to workaround onChangeText not being triggered with replaceText above
@@ -189,21 +187,25 @@ export async function quickOnboarding({
}
await scrollIntoView('Restore', 'ImportWalletKeyboardAwareScrollView')
- await waitForElementByIdAndTap('ImportWalletButton')
+ await waitForElementById('ImportWalletButton', {
+ tap: true,
+ })
// Wait for the wallet to restored
await sleep(5 * 1000)
try {
// case where account not funded yet. continue with onboarding.
- await waitForElementByIdAndTap('ConfirmUseAccountDialog/PrimaryAction')
+ await waitForElementById('ConfirmUseAccountDialog/PrimaryAction', {
+ tap: true,
+ })
} catch {}
// this onboarding step is bypassed for already verified wallets
try {
- // Verify Education
- await waitForElementId('PhoneVerificationSkipHeader')
- // Skip
- await element(by.id('PhoneVerificationSkipHeader')).tap()
+ // Skip Phone Verification
+ await waitForElementById('PhoneVerificationSkipHeader', {
+ tap: true,
+ })
} catch {
console.log(
'Error trying to skip phone verification step during onboarding, likely due to wallet already being verified'
@@ -212,10 +214,12 @@ export async function quickOnboarding({
// Choose your own adventure (CYA screen)
if (stopOnCYA) {
- await waitForElementId('ChooseYourAdventure/Later')
+ await waitForElementById('ChooseYourAdventure/Later')
return
}
- await waitForElementByIdAndTap('ChooseYourAdventure/Later')
+ await waitForElementById('ChooseYourAdventure/Later', {
+ tap: true,
+ })
// Assert on Wallet Home Screen
await expect(element(by.id('HomeAction-Send'))).toBeVisible()
@@ -412,18 +416,30 @@ export async function fundWallet(senderPrivateKey, recipientAddress, stableToken
}
export async function navigateToSecurity() {
- await waitForElementByIdAndTap('WalletHome/SettingsGearButton')
- await waitForElementByIdAndTap('SettingsMenu/Security')
+ await waitForElementById('WalletHome/SettingsGearButton', {
+ tap: true,
+ })
+ await waitForElementById('SettingsMenu/Security', {
+ tap: true,
+ })
}
export async function navigateToProfile() {
- await waitForElementByIdAndTap('WalletHome/SettingsGearButton')
- await waitForElementByIdAndTap('SettingsMenu/Profile')
+ await waitForElementById('WalletHome/SettingsGearButton', {
+ tap: true,
+ })
+ await waitForElementById('SettingsMenu/Profile', {
+ tap: true,
+ })
}
export async function navigateToPreferences() {
- await waitForElementByIdAndTap('WalletHome/SettingsGearButton')
- await waitForElementByIdAndTap('SettingsMenu/Preferences')
+ await waitForElementById('WalletHome/SettingsGearButton', {
+ tap: true,
+ })
+ await waitForElementById('SettingsMenu/Preferences', {
+ tap: true,
+ })
}
export const getDisplayAddress = (address) => {
diff --git a/ios/MobileStack.xcodeproj/project.pbxproj b/ios/MobileStack.xcodeproj/project.pbxproj
index 08c7890edce..1d26139c50b 100644
--- a/ios/MobileStack.xcodeproj/project.pbxproj
+++ b/ios/MobileStack.xcodeproj/project.pbxproj
@@ -767,7 +767,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 165;
+ CURRENT_PROJECT_VERSION = 166;
ENABLE_BITCODE = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 ";
@@ -794,7 +794,7 @@
"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios",
);
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
- MARKETING_VERSION = 1.100.0;
+ MARKETING_VERSION = 1.101.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "$(inherited)";
@@ -828,7 +828,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 165;
+ CURRENT_PROJECT_VERSION = 166;
ENABLE_BITCODE = NO;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -853,7 +853,7 @@
"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios",
);
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
- MARKETING_VERSION = 1.100.0;
+ MARKETING_VERSION = 1.101.0;
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 1e8c8a7a994..2f44bc4f100 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -563,7 +563,7 @@ PODS:
- React-jsinspector (0.72.15)
- React-logger (0.72.15):
- glog
- - react-native-adjust (5.0.2):
+ - react-native-adjust (5.0.3):
- Adjust (= 5.0.1)
- React-Core
- react-native-camera (4.2.1):
@@ -596,7 +596,7 @@ PODS:
- react-native-pager-view (6.4.1):
- RCT-Folly (= 2021.07.22.00)
- React-Core
- - react-native-quick-crypto (0.7.7):
+ - react-native-quick-crypto (0.7.10):
- OpenSSL-Universal
- RCT-Folly (= 2021.07.22.00)
- React
@@ -1268,7 +1268,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: d3eef5ddc78eeb9f0d02bed657a7f41d4910b966
React-jsinspector: b86a8abae760c28d69366bbc1d991561e51341ed
React-logger: ed7c9e01e58529065e7da6bf8318baf15024283e
- react-native-adjust: 6a73063a62fb0f21dd2220f15b315c1e323268b0
+ react-native-adjust: 59b523d8ef1dc2c0516fb7120ed04cdfc5510a90
react-native-camera: 3eae183c1d111103963f3dd913b65d01aef8110f
react-native-compat: 24dedfbd7faba258560048606bc0fe9e73f7d2a3
react-native-config: 8f7283449bbb048902f4e764affbbf24504454af
@@ -1279,7 +1279,7 @@ SPEC CHECKSUMS:
react-native-launch-arguments: 5f41e0abf88a15e3c5309b8875d6fd5ac43df49d
react-native-netinfo: f0a9899081c185db1de5bb2fdc1c88c202a059ac
react-native-pager-view: c65514a81a384c3ce244b5bd87167761740308d3
- react-native-quick-crypto: e254783f9681542c182f9439f91139137e3b9e48
+ react-native-quick-crypto: e7ca8ccd138d8e54b9be3bc686fcc4e8c53866d7
react-native-restart: 7595693413fe3ca15893702f2c8306c62a708162
react-native-safe-area-context: 141eca0fd4e4191288dfc8b96a7c7e1c2983447a
react-native-shake: 0c36371dd63019afa68890ccc65a442ee21b4dde
diff --git a/locales/base/translation.json b/locales/base/translation.json
index 0fc566eac61..d489b8bbf93 100644
--- a/locales/base/translation.json
+++ b/locales/base/translation.json
@@ -2783,9 +2783,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "You Need {{tokenSymbol}} on {{tokenNetwork}} to Deposit",
+ "depositTitle": "Deposit to pool",
"crossChainAlternativeDescription": "If you don’t want to use your tokens on {{tokenNetwork}}, choose an option below. You’ll need to return to complete your pool deposit later.",
"beforeYouCanDepositTitle": "Before you can deposit...",
"beforeYouCanDepositDescription": "You’ll need to add one of the pool tokens. Once added, you’ll need to return to complete your pool deposit.",
+ "beforeYouCanDepositDescriptionV1_101": "You’ll need to add {{tokenSymbol}} on {{tokenNetwork}}. Once added, you’ll need to return to complete your pool deposit.",
"action": {
"swapAndDeposit": "Swap & Deposit",
"swapAndDepositDescription": "Choose any token on {{tokenNetwork}}. We’ll swap and deposit it simultaneously for you.",
@@ -2796,7 +2798,10 @@
"add": "Buy",
"addDescription": "Buy {{tokenSymbol}} on {{tokenNetwork}} using one of our trusted providers",
"transfer": "Transfer",
- "transferDescription": "Use any {{tokenNetwork}} compatible wallet or exchange to deposit {{tokenSymbol}}"
+ "transferDescription": "Use any {{tokenNetwork}} compatible wallet or exchange to deposit {{tokenSymbol}}",
+ "addMore": "Buy more {{tokenSymbol}}",
+ "deposit": "Deposit your {{tokenSymbol}}",
+ "depositDescription": "You have {{amount}} {{tokenSymbol}}"
}
}
},
diff --git a/locales/de/translation.json b/locales/de/translation.json
index 819aa16e044..de0b030853b 100644
--- a/locales/de/translation.json
+++ b/locales/de/translation.json
@@ -2781,9 +2781,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "Du brauchst {{tokenSymbol}} auf {{tokenNetwork}} zum Einzahlen",
+ "depositTitle": "Einzahlung in den Pool",
"crossChainAlternativeDescription": "Wenn du deine Token nicht auf {{tokenNetwork}} verwenden möchtest, wähle eine der untenstehenden Optionen. Du musst später zurückkehren, um deine Pool-Einzahlung abzuschließen.",
"beforeYouCanDepositTitle": "Bevor du eine Einzahlung vornehmen kannst ...",
"beforeYouCanDepositDescription": "Du musst einen der Pool-Token hinzufügen. Sobald du es hinzugefügt hast, musst du zurückkehren, um deine Pool-Einzahlung abzuschließen.",
+ "beforeYouCanDepositDescriptionV1_101": "Du musst {{tokenSymbol}} auf {{tokenNetwork}}hinzufügen. Sobald du sie hinzugefügt hast, musst du zurückkehren, um deine Pool-Einzahlung abzuschließen.",
"action": {
"swapAndDeposit": "Tausch und Einzahlung",
"swapAndDepositDescription": "Wähle einen beliebigen Token auf {{tokenNetwork}}. Wir tauschen und hinterlegen ihn gleichzeitig für dich.",
@@ -2794,7 +2796,10 @@
"add": "Kaufen",
"addDescription": "Kaufe {{tokenSymbol}} auf {{tokenNetwork}} über einen unserer vertrauenswürdigen Anbieter",
"transfer": "Überweisung",
- "transferDescription": "Verwende jede {{tokenNetwork}} kompatible Wallet oder Börse, um {{tokenSymbol}} einzuzahlen"
+ "transferDescription": "Verwende jede {{tokenNetwork}} kompatible Wallet oder Börse, um {{tokenSymbol}} einzuzahlen",
+ "addMore": "Mehr kaufen {{tokenSymbol}}",
+ "deposit": "Hinterlege deine {{tokenSymbol}}",
+ "depositDescription": "Du hast {{amount}} {{tokenSymbol}}"
}
}
},
diff --git a/locales/en-US/translation.json b/locales/en-US/translation.json
index 3e8c91818b8..a8bb76585b6 100644
--- a/locales/en-US/translation.json
+++ b/locales/en-US/translation.json
@@ -2781,9 +2781,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "You Need {{tokenSymbol}} on {{tokenNetwork}} to Deposit",
+ "depositTitle": "Deposit to pool",
"crossChainAlternativeDescription": "If you don’t want to use your tokens on {{tokenNetwork}}, choose an option below. You’ll need to return to complete your pool deposit later.",
"beforeYouCanDepositTitle": "Before you can deposit...",
"beforeYouCanDepositDescription": "You’ll need to add one of the pool tokens. Once added, you’ll need to return to complete your pool deposit.",
+ "beforeYouCanDepositDescriptionV1_101": "You’ll need to add {{tokenSymbol}} on {{tokenNetwork}}. Once added, you’ll need to return to complete your pool deposit.",
"action": {
"swapAndDeposit": "Swap & Deposit",
"swapAndDepositDescription": "Choose any token on {{tokenNetwork}}. We’ll swap and deposit it simultaneously for you.",
@@ -2794,7 +2796,10 @@
"add": "Buy",
"addDescription": "Buy {{tokenSymbol}} on {{tokenNetwork}} using one of our trusted providers",
"transfer": "Transfer",
- "transferDescription": "Use any {{tokenNetwork}} compatible wallet or exchange to deposit {{tokenSymbol}}"
+ "transferDescription": "Use any {{tokenNetwork}} compatible wallet or exchange to deposit {{tokenSymbol}}",
+ "addMore": "Buy more {{tokenSymbol}}",
+ "deposit": "Deposit your {{tokenSymbol}}",
+ "depositDescription": "You have {{amount}} {{tokenSymbol}}"
}
}
},
diff --git a/locales/es-419/translation.json b/locales/es-419/translation.json
index 53419d9ea51..a10dd37d5b4 100644
--- a/locales/es-419/translation.json
+++ b/locales/es-419/translation.json
@@ -2781,9 +2781,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "Necesitas {{tokenSymbol}} en {{tokenNetwork}} para depositar",
+ "depositTitle": "Depósito a la piscina",
"crossChainAlternativeDescription": "Si no quieres usar tus tokens en {{tokenNetwork}}, elige una opción a continuación. Tendrás que volver para completar tu depósito en el pool más tarde.",
"beforeYouCanDepositTitle": "Antes de que puedas depositar...",
"beforeYouCanDepositDescription": "Tendrás que agregarr uno de los tokens del pool. Una vez agregado, tendrás que volver para completar el depósito en el pool.",
+ "beforeYouCanDepositDescriptionV1_101": "Tendrás que añadir {{tokenSymbol}} en {{tokenNetwork}}. Una vez añadido, tendrás que volver para completar el depósito de tu piscina.",
"action": {
"swapAndDeposit": "Intercambiar y depositar",
"swapAndDepositDescription": "Elige cualquier token en {{tokenNetwork}}. Lo cambiaremos y lo depositaremos simultáneamente por ti.",
@@ -2794,7 +2796,10 @@
"add": "Comprar",
"addDescription": "Compra {{tokenSymbol}} en {{tokenNetwork}} a uno de nuestros proveedores de confianza.",
"transfer": "Transferir",
- "transferDescription": "Usa cualquier wallet o exchange compatible con {{tokenNetwork}} para depositar {{tokenSymbol}}."
+ "transferDescription": "Usa cualquier wallet o exchange compatible con {{tokenNetwork}} para depositar {{tokenSymbol}}.",
+ "addMore": "Compra más {{tokenSymbol}}",
+ "deposit": "Deposita tu {{tokenSymbol}}",
+ "depositDescription": "Tienes {{amount}} {{tokenSymbol}}"
}
}
},
diff --git a/locales/fr-FR/translation.json b/locales/fr-FR/translation.json
index f905d6751fa..cb4e133295f 100644
--- a/locales/fr-FR/translation.json
+++ b/locales/fr-FR/translation.json
@@ -2781,9 +2781,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "Vous avez besoin de {{tokenSymbol}} sur {{tokenNetwork}} pour faire un dépôt",
+ "depositTitle": "Dépôt à la piscine",
"crossChainAlternativeDescription": "Si vous ne voulez pas utiliser vos jetons sur {{tokenNetwork}}, choisissez une option ci-dessous. Vous devrez revenir pour compléter votre dépôt de pool plus tard.",
"beforeYouCanDepositTitle": "Avant de pouvoir effectuer un dépôt...",
"beforeYouCanDepositDescription": "Vous devrez ajouter un des jetons du pool. Une fois ajouté, vous devrez revenir pour compléter votre dépôt de pool.",
+ "beforeYouCanDepositDescriptionV1_101": "Tu devras ajouter {{tokenSymbol}} sur {{tokenNetwork}}. Une fois ajouté, tu devras revenir pour compléter ton dépôt de piscine.",
"action": {
"swapAndDeposit": "Échange et dépôt",
"swapAndDepositDescription": "Choisissez n'importe quel jeton sur {{tokenNetwork}}. Nous le changerons et le déposerons simultanément pour vous.",
@@ -2794,7 +2796,10 @@
"add": "Acheter",
"addDescription": "Achetez des {{tokenSymbol}} sur {{tokenNetwork}} en utilisant un de nos fournisseurs de confiance",
"transfer": "Transférer",
- "transferDescription": "Utilisez n'importe quel portefeuille compatible {{tokenNetwork}} ou échangez pour déposer des {{tokenSymbol}}"
+ "transferDescription": "Utilisez n'importe quel portefeuille compatible {{tokenNetwork}} ou échangez pour déposer des {{tokenSymbol}}",
+ "addMore": "Acheter plus de {{tokenSymbol}}",
+ "deposit": "Dépose ton {{tokenSymbol}}",
+ "depositDescription": "Tu as {{amount}} {{tokenSymbol}}"
}
}
},
diff --git a/locales/it-IT/translation.json b/locales/it-IT/translation.json
index d5536461f59..2a003bed3c1 100644
--- a/locales/it-IT/translation.json
+++ b/locales/it-IT/translation.json
@@ -2781,9 +2781,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "Hai bisogno di {{tokenSymbol}} su {{tokenNetwork}} per depositare",
+ "depositTitle": "Deposito in piscina",
"crossChainAlternativeDescription": "Se non vuoi usare i tuoi token su {{tokenNetwork}}, scegli un'opzione qui sotto. Devi tornare per completare il deposito nel pool in un secondo momento.",
"beforeYouCanDepositTitle": "Prima di poter depositare...",
"beforeYouCanDepositDescription": "Devi aggiungere uno dei token del pool. Una volta aggiunto, devi tornare per completare il deposito nel pool.",
+ "beforeYouCanDepositDescriptionV1_101": "Dovrai aggiungere {{tokenSymbol}} su {{tokenNetwork}}. Una volta aggiunto, dovrai tornare per completare il deposito della piscina.",
"action": {
"swapAndDeposit": "Scambio e deposito",
"swapAndDepositDescription": "Scegli qualsiasi token su {{tokenNetwork}}. Lo scambieremo e lo depositeremo simultaneamente per te.",
@@ -2794,7 +2796,10 @@
"add": "Acquista",
"addDescription": "Acquista {{tokenSymbol}} su {{tokenNetwork}} utilizzando uno dei nostri fornitori di fiducia",
"transfer": "Trasferisci",
- "transferDescription": "Utilizza qualsiasi wallet o exchange compatibile con {{tokenNetwork}} per depositare {{tokenSymbol}}"
+ "transferDescription": "Utilizza qualsiasi wallet o exchange compatibile con {{tokenNetwork}} per depositare {{tokenSymbol}}",
+ "addMore": "Acquista più {{tokenSymbol}}",
+ "deposit": "Deposita il tuo {{tokenSymbol}}",
+ "depositDescription": "Hai {{amount}} {{tokenSymbol}}"
}
}
},
diff --git a/locales/pl-PL/translation.json b/locales/pl-PL/translation.json
index 93edf92f7d6..b53667797d2 100644
--- a/locales/pl-PL/translation.json
+++ b/locales/pl-PL/translation.json
@@ -2785,9 +2785,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "Aby dokonać wpłaty, potrzebny jest {{tokenSymbol}} w {{tokenNetwork}}",
+ "depositTitle": "Depozyt do puli",
"crossChainAlternativeDescription": "Jeśli nie chcesz użyć swoich tokenów w {{tokenNetwork}}, wybierz poniższą opcję. Trzeba będzie tu wrócić, aby później sfinalizować wpłatę do puli.",
"beforeYouCanDepositTitle": "Zanim będzie można dokonać wpłaty...",
"beforeYouCanDepositDescription": "Musisz dodać jeden z tokenów puli. Po dodaniu musisz tu wrócić, aby sfinalizować wpłatę do puli.",
+ "beforeYouCanDepositDescriptionV1_101": "Musisz dodać stronę {{tokenSymbol}} na {{tokenNetwork}}. Po dodaniu musisz wrócić, aby uzupełnić depozyt za basen.",
"action": {
"swapAndDeposit": "Wymiana i wpłata",
"swapAndDepositDescription": "Wybierz dowolny token w {{tokenNetwork}}. Wymienimy go i jednocześnie wpłacimy za Ciebie.",
@@ -2798,7 +2800,10 @@
"add": "Kup",
"addDescription": "Kup {{tokenSymbol}} w {{tokenNetwork}}, korzystając z usług jednego z naszych zaufanych dostawców",
"transfer": "Transfer",
- "transferDescription": "Użyj dowolnego portfela lub giełdy kompatybilnej z {{tokenNetwork}}, aby wpłacić {{tokenSymbol}}"
+ "transferDescription": "Użyj dowolnego portfela lub giełdy kompatybilnej z {{tokenNetwork}}, aby wpłacić {{tokenSymbol}}",
+ "addMore": "Kup więcej {{tokenSymbol}}",
+ "deposit": "Złóż depozyt na {{tokenSymbol}}",
+ "depositDescription": "Masz {{amount}} {{tokenSymbol}}"
}
}
},
diff --git a/locales/pt-BR/translation.json b/locales/pt-BR/translation.json
index 489da6b8f50..53b4d34a617 100644
--- a/locales/pt-BR/translation.json
+++ b/locales/pt-BR/translation.json
@@ -2781,9 +2781,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "Você precisa de {{tokenSymbol}} da {{tokenNetwork}} para depositar",
+ "depositTitle": "Depósito para piscina",
"crossChainAlternativeDescription": "Se não quiser usar seus tokens da {{tokenNetwork}}, escolha uma opção abaixo. Você precisará retornar para concluir o depósito no pool mais tarde.",
"beforeYouCanDepositTitle": "Antes de poder depositar...",
"beforeYouCanDepositDescription": "Você precisará adicionar um dos tokens do pool. Depois de adicionar, você precisará retornar para concluir o depósito no pool.",
+ "beforeYouCanDepositDescriptionV1_101": "Você precisará adicionar {{tokenSymbol}} em {{tokenNetwork}}. Depois de adicionado, você precisará retornar para concluir o depósito da piscina.",
"action": {
"swapAndDeposit": "Trocar e depositar",
"swapAndDepositDescription": "Escolha qualquer token da {{tokenNetwork}}. Faremos a troca e o depósito simultaneamente para você.",
@@ -2794,7 +2796,10 @@
"add": "Comprar",
"addDescription": "Compre {{tokenSymbol}} na {{tokenNetwork}} usando um dos nossos provedores confiáveis",
"transfer": "Transferir",
- "transferDescription": "Use qualquer carteira ou exchange compatível com {{tokenNetwork}} para depositar {{tokenSymbol}}"
+ "transferDescription": "Use qualquer carteira ou exchange compatível com {{tokenNetwork}} para depositar {{tokenSymbol}}",
+ "addMore": "Compre mais {{tokenSymbol}}",
+ "deposit": "Deposite seu {{tokenSymbol}}",
+ "depositDescription": "Você tem {{amount}} {{tokenSymbol}}"
}
}
},
diff --git a/locales/ru-RU/translation.json b/locales/ru-RU/translation.json
index f04fcc31eb3..ac9a1aa4f91 100644
--- a/locales/ru-RU/translation.json
+++ b/locales/ru-RU/translation.json
@@ -2785,9 +2785,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "Для пополнения счета потребуется {{tokenSymbol}} в {{tokenNetwork}}",
+ "depositTitle": "Депозит в бассейн",
"crossChainAlternativeDescription": "Если вы не хотите использовать свои токены в {{tokenNetwork}}, выберите вариант ниже. Потребуется вернуться, чтобы завершить пополнение счета в пуле позже.",
"beforeYouCanDepositTitle": "Для пополнения счета...",
"beforeYouCanDepositDescription": "Вам потребуется добавить один из токенов пула. После добавления потребуется вернуться, чтобы завершить пополнение счета в пуле.",
+ "beforeYouCanDepositDescriptionV1_101": "Тебе нужно будет добавить {{tokenSymbol}} на сайте {{tokenNetwork}}. После добавления тебе нужно будет вернуться, чтобы завершить депозит за бассейн.",
"action": {
"swapAndDeposit": "Обмен и пополнение счета",
"swapAndDepositDescription": "Выберите любой токен в {{tokenNetwork}}. Мы сразу выполним обмен и пополнение счета.",
@@ -2798,7 +2800,10 @@
"add": "Купить",
"addDescription": "Купите {{tokenSymbol}} в {{tokenNetwork}} с помощью одного из доверенных поставщиков",
"transfer": "Перевод",
- "transferDescription": "Используйте совместимый с {{tokenNetwork}} кошелек или криптобиржу для депонирования {{tokenSymbol}}"
+ "transferDescription": "Используйте совместимый с {{tokenNetwork}} кошелек или криптобиржу для депонирования {{tokenSymbol}}",
+ "addMore": "Покупай больше {{tokenSymbol}}",
+ "deposit": "Пополни свой счет {{tokenSymbol}}",
+ "depositDescription": "У тебя есть {{amount}} {{tokenSymbol}}."
}
}
},
diff --git a/locales/th-TH/translation.json b/locales/th-TH/translation.json
index 9db1bb10075..bd6e76dc86d 100644
--- a/locales/th-TH/translation.json
+++ b/locales/th-TH/translation.json
@@ -2779,9 +2779,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "คุณจำเป็นต้องมี {{tokenSymbol}} บน {{tokenNetwork}} จึงจะฝากเงินได้",
+ "depositTitle": "Deposit to pool",
"crossChainAlternativeDescription": "หากคุณไม่ต้องการใช้โทเค็นของคุณบน {{tokenNetwork}} ให้เลือกตัวเลือกด้านล่างนี้ ทั้งนี้ คุณจะต้องกลับมาฝากเงินเข้าพูลในภายหลัง",
"beforeYouCanDepositTitle": "ก่อนที่คุณจะสามารถฝากเงินได้...",
"beforeYouCanDepositDescription": "คุณจะต้องเพิ่มโทเค็นพูลหนึ่งรายการ เมื่อเพิ่มแล้ว คุณจะต้องกลับไปเพื่อทำการฝากเงินเข้าพูลให้เสร็จสมบูรณ์",
+ "beforeYouCanDepositDescriptionV1_101": "You’ll need to add {{tokenSymbol}} on {{tokenNetwork}}. Once added, you’ll need to return to complete your pool deposit.",
"action": {
"swapAndDeposit": "สว็อปและฝากเงิน",
"swapAndDepositDescription": "เลือกโทเค็นใดโทเค็นหนึ่งบน {{tokenNetwork}} เราจะสว็อปและฝากเงินให้คุณในเวลาเดียวกัน",
@@ -2792,7 +2794,10 @@
"add": "ซื้อ",
"addDescription": "ซื้อ {{tokenSymbol}} บน {{tokenNetwork}} ผ่านหนึ่งในผู้ให้บริการที่น่าเชื่อถือของเรา",
"transfer": "โอน",
- "transferDescription": "ใช้กระเป๋าเงินหรือกระดานแลกเปลี่ยนที่ใช้งานร่วมกันได้กับ {{tokenNetwork}} เพื่อฝาก {{tokenSymbol}}"
+ "transferDescription": "ใช้กระเป๋าเงินหรือกระดานแลกเปลี่ยนที่ใช้งานร่วมกันได้กับ {{tokenNetwork}} เพื่อฝาก {{tokenSymbol}}",
+ "addMore": "Buy more {{tokenSymbol}}",
+ "deposit": "Deposit your {{tokenSymbol}}",
+ "depositDescription": "You have {{amount}} {{tokenSymbol}}"
}
}
},
diff --git a/locales/tr-TR/translation.json b/locales/tr-TR/translation.json
index 62bf469a164..05a44a1f3f8 100644
--- a/locales/tr-TR/translation.json
+++ b/locales/tr-TR/translation.json
@@ -2781,9 +2781,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "Yatırma İşlemi için {{tokenNetwork}} ağında {{tokenSymbol}} tokenine sahip olmalısınız",
+ "depositTitle": "Havuz için depozito",
"crossChainAlternativeDescription": "{{tokenNetwork}} ağındaki tokenlerinizi kullanmaz istemiyorsanız aşağıdaki seçeneklerden birini seçin. Havuza yatırma işleminizi tamamlamak için daha sonra geri dönmeniz gerekecektir.",
"beforeYouCanDepositTitle": "Para yatırmadan önce...",
"beforeYouCanDepositDescription": "Havuz tokenlerinden birini eklemeniz gereklidir. Token eklendikten sonra havuza para yatırma işlemini tamamlamak için geri dönmeniz gerekir.",
+ "beforeYouCanDepositDescriptionV1_101": "{{tokenSymbol}} adresini {{tokenNetwork}}adresine eklemeniz gerekmektedir. Eklendikten sonra, havuz depozitonuzu tamamlamak için geri dönmeniz gerekecektir.",
"action": {
"swapAndDeposit": "Swap ve Para Yatırma",
"swapAndDepositDescription": "{{tokenNetwork}} ağındaki herhangi bir tokeni seçin. Seçtiğiniz tokeni sizin için anında swap edip yatırma işleminizi tamamlayacağız.",
@@ -2794,7 +2796,10 @@
"add": "Satın Al",
"addDescription": "Güvenilir sağlayıcılarımızdan birini kullanarak {{tokenNetwork}} ağında {{tokenSymbol}} satın alın",
"transfer": "Transfer Et",
- "transferDescription": "{{tokenSymbol}} yatırmak için {{tokenNetwork}} uyumlu cüzdan veya borsa kullanın"
+ "transferDescription": "{{tokenSymbol}} yatırmak için {{tokenNetwork}} uyumlu cüzdan veya borsa kullanın",
+ "addMore": "Daha fazla satın al {{tokenSymbol}}",
+ "deposit": "{{tokenSymbol}}adresinizi yatırın",
+ "depositDescription": "{{amount}} {{tokenSymbol}}adresiniz var."
}
}
},
diff --git a/locales/uk-UA/translation.json b/locales/uk-UA/translation.json
index 4f699c8b691..ec3762e177d 100644
--- a/locales/uk-UA/translation.json
+++ b/locales/uk-UA/translation.json
@@ -2785,9 +2785,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "Вам потрібен {{tokenSymbol}} в {{tokenNetwork}} для внесення депозиту",
+ "depositTitle": "Депозит в пул",
"crossChainAlternativeDescription": "Якщо ви не хочете використовувати свої токени в мережі {{tokenNetwork}}, виберіть один із варіантів нижче. Вам треба буде повернутися пізніше, щоб внести кошти в пул.",
"beforeYouCanDepositTitle": "Перш ніж внести депозит...",
"beforeYouCanDepositDescription": "Потрібно додати один із токенів пулу. Після додавання вам треба буде повернутися, щоб внести кошти в пул.",
+ "beforeYouCanDepositDescriptionV1_101": "Вам потрібно буде додати {{tokenSymbol}} на {{tokenNetwork}}. Після додавання вам потрібно буде повернутися, щоб поповнити свій депозит у пулі.",
"action": {
"swapAndDeposit": "Обмін і внесення депозиту",
"swapAndDepositDescription": "Виберіть будь-який токен у мережі {{tokenNetwork}}. Ми одночасно обміняємо його та внесемо депозит за вас.",
@@ -2798,7 +2800,10 @@
"add": "Купити",
"addDescription": "Купіть {{tokenSymbol}} у мережі {{tokenNetwork}} через одного з наших довірених постачальників",
"transfer": "Переказати",
- "transferDescription": "Скористайтеся будь-яким гаманцем, сумісним із мережею {{tokenNetwork}} або виконайте обмін, щоб внести {{tokenSymbol}}"
+ "transferDescription": "Скористайтеся будь-яким гаманцем, сумісним із мережею {{tokenNetwork}} або виконайте обмін, щоб внести {{tokenSymbol}}",
+ "addMore": "Купити більше {{tokenSymbol}}",
+ "deposit": "Поповніть свій рахунок на {{tokenSymbol}}",
+ "depositDescription": "У вас є {{amount}} {{tokenSymbol}}"
}
}
},
diff --git a/locales/vi-VN/translation.json b/locales/vi-VN/translation.json
index a5f180e02da..ec5c1cb872e 100644
--- a/locales/vi-VN/translation.json
+++ b/locales/vi-VN/translation.json
@@ -2779,9 +2779,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "Bạn cần {{tokenSymbol}} trên {{tokenNetwork}} để nạp",
+ "depositTitle": "Deposit to pool",
"crossChainAlternativeDescription": "Nếu bạn không muốn sử dụng token trên {{tokenNetwork}}, hãy chọn một lựa chọn bên dưới. Bạn sẽ phải quay lại để hoàn tất giao dịch nạp vào bể sau đó.",
"beforeYouCanDepositTitle": "Trước khi bạn có thể nạp...",
"beforeYouCanDepositDescription": "Bạn sẽ cần thêm một trong các token bể. Sau khi thêm, bạn phải quay lại để hoàn tất giao dịch nạp vào bể.",
+ "beforeYouCanDepositDescriptionV1_101": "You’ll need to add {{tokenSymbol}} on {{tokenNetwork}}. Once added, you’ll need to return to complete your pool deposit.",
"action": {
"swapAndDeposit": "Trao đổi và nạp",
"swapAndDepositDescription": "Chọn token bất kỳ trên {{tokenNetwork}}. Chúng tôi sẽ trao đổi và nạp đồng thời token đó cho bạn.",
@@ -2792,7 +2794,10 @@
"add": "Mua",
"addDescription": "Mua {{tokenSymbol}} trên {{tokenNetwork}} qua một trong những nhà cung cấp uy tín của chúng tôi",
"transfer": "Chuyển tiền",
- "transferDescription": "Sử dụng bất kỳ ví hoặc sàn giao dịch nào tương thích với {{tokenNetwork}} để nạp {{tokenSymbol}}"
+ "transferDescription": "Sử dụng bất kỳ ví hoặc sàn giao dịch nào tương thích với {{tokenNetwork}} để nạp {{tokenSymbol}}",
+ "addMore": "Buy more {{tokenSymbol}}",
+ "deposit": "Deposit your {{tokenSymbol}}",
+ "depositDescription": "You have {{amount}} {{tokenSymbol}}"
}
}
},
diff --git a/locales/zh-CN/translation.json b/locales/zh-CN/translation.json
index 7819aa9a3ff..93c3a0c9c44 100644
--- a/locales/zh-CN/translation.json
+++ b/locales/zh-CN/translation.json
@@ -2779,9 +2779,11 @@
},
"beforeDepositBottomSheet": {
"youNeedTitle": "您需要在 {{tokenNetwork}} 上持有 {{tokenSymbol}} 才可进行存款",
+ "depositTitle": "游泳池押金",
"crossChainAlternativeDescription": "如果您不想使用 {{tokenNetwork}} 上的代币,请选择以下选项。您需要稍后返回,继续完成资金池存款操作。",
"beforeYouCanDepositTitle": "在您进行存款之前……",
"beforeYouCanDepositDescription": "您需要添加某一资金池的代币。成功添加代币后,您需要返回继续完成资金池存款操作。",
+ "beforeYouCanDepositDescriptionV1_101": "您需要在 {{tokenNetwork}}上添加 {{tokenSymbol}} 。添加后,您需要返回以完成泳池押金。",
"action": {
"swapAndDeposit": "交换与存款",
"swapAndDepositDescription": "请选择 {{tokenNetwork}} 上的任何代币。我们将同步为您进行交换和存款。",
@@ -2792,7 +2794,10 @@
"add": "买入",
"addDescription": "使用我们值得信赖的提供商之一,在 {{tokenNetwork}} 上购买 {{tokenSymbol}}",
"transfer": "转账",
- "transferDescription": "使用任何与 {{tokenNetwork}} 兼容的钱包或交易所,来存入 {{tokenSymbol}}"
+ "transferDescription": "使用任何与 {{tokenNetwork}} 兼容的钱包或交易所,来存入 {{tokenSymbol}}",
+ "addMore": "购买更多 {{tokenSymbol}}",
+ "deposit": "存款 {{tokenSymbol}}",
+ "depositDescription": "您有 {{amount}} {{tokenSymbol}}"
}
}
},
diff --git a/package.json b/package.json
index 524f05169a6..d0ea1f55d51 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@valora/wallet",
- "version": "1.100.0",
+ "version": "1.101.0",
"author": "Valora Inc",
"license": "Apache-2.0",
"private": true,
@@ -73,8 +73,8 @@
"dependencies": {
"@badrap/result": "~0.2.13",
"@crowdin/ota-client": "^0.7.0",
- "@fiatconnect/fiatconnect-sdk": "^0.5.62",
- "@fiatconnect/fiatconnect-types": "^13.3.8",
+ "@fiatconnect/fiatconnect-sdk": "^0.5.66",
+ "@fiatconnect/fiatconnect-types": "^13.3.10",
"@gorhom/bottom-sheet": "^4.6.4",
"@json-rpc-tools/utils": "^1.7.6",
"@noble/secp256k1": "^1.7.1",
@@ -122,20 +122,20 @@
"fp-ts": "2.16.9",
"futoin-hkdf": "^1.5.3",
"fuzzysort": "^3.1.0",
- "google-libphonenumber": "^3.2.39",
+ "google-libphonenumber": "^3.2.40",
"i18next": "^23.16.8",
"ibantools": "^4.5.1",
"intl-pluralrules": "^2.0.1",
- "io-ts": "2.2.21",
+ "io-ts": "2.2.22",
"is-ip": "^3.1.0",
"jwt-decode": "^4.0.0",
"lodash": "^4.17.21",
"lottie-react-native": "^5.1.6",
"react": "18.3.1",
"react-async-hook": "^4.0.0",
- "react-i18next": "^15.1.3",
+ "react-i18next": "^15.1.4",
"react-native": "0.72.15",
- "react-native-adjust": "^5.0.2",
+ "react-native-adjust": "^5.0.3",
"react-native-android-open-settings": "^1.3.0",
"react-native-auth0": "^3.2.1",
"react-native-camera": "^4.2.1",
@@ -159,10 +159,10 @@
"react-native-picker-select": "^9.3.1",
"react-native-platform-touchable": "^1.1.1",
"react-native-qrcode-svg": "^6.3.12",
- "react-native-quick-crypto": "^0.7.7",
+ "react-native-quick-crypto": "^0.7.9",
"react-native-reanimated": "^3.15.1",
"react-native-restart": "^0.0.27",
- "react-native-safe-area-context": "^4.14.0",
+ "react-native-safe-area-context": "^4.14.1",
"react-native-screens": "^4.3.0",
"react-native-shake": "5.5.2",
"react-native-share": "^11.1.0",
diff --git a/src/app/saga.ts b/src/app/saga.ts
index 927e26691ba..3b76a1f24fe 100644
--- a/src/app/saga.ts
+++ b/src/app/saga.ts
@@ -323,7 +323,11 @@ export function* handleDeepLink(action: OpenDeepLink) {
}
function* watchDeepLinks() {
- yield* takeLatest(Actions.OPEN_DEEP_LINK, safely(handleDeepLink))
+ // using takeEvery over takeLatest because openScreen deep links could be
+ // fired by multiple handlers (one with isSecureOrigin and one without), and
+ // if takeLatest kills the call to the handler with isSecureOrigin, the deep
+ // link won't work.
+ yield* takeEvery(Actions.OPEN_DEEP_LINK, safely(handleDeepLink))
}
export function* handleOpenUrl(action: OpenUrlAction) {
diff --git a/src/app/useDeepLinks.test.tsx b/src/app/useDeepLinks.test.tsx
new file mode 100644
index 00000000000..99659260312
--- /dev/null
+++ b/src/app/useDeepLinks.test.tsx
@@ -0,0 +1,86 @@
+import { act, renderHook } from '@testing-library/react-native'
+import CleverTap from 'clevertap-react-native'
+import React from 'react'
+import { Linking } from 'react-native'
+import { Provider } from 'react-redux'
+import { useDeepLinks } from 'src/app/useDeepLinks'
+import { createMockStore } from 'test/utils'
+
+describe('useDeepLinks', () => {
+ let cleverTapListenerCallback: Function
+ let linkingListenerCallback: Function
+
+ beforeEach(() => {
+ jest.clearAllMocks()
+ jest.mocked(CleverTap.addListener).mockImplementation((event, callback) => {
+ if (event === 'CleverTapPushNotificationClicked') {
+ cleverTapListenerCallback = callback
+ }
+ })
+ jest.mocked(Linking.addEventListener).mockImplementation((event, callback) => {
+ if (event === 'url') {
+ linkingListenerCallback = callback
+ }
+ return {
+ remove: jest.fn(),
+ } as any
+ })
+ })
+
+ it('should handle clevertap push notifications with deep links', async () => {
+ const store = createMockStore()
+ renderHook(() => useDeepLinks(), {
+ wrapper: (component) => (
+ {component?.children ? component.children : component}
+ ),
+ })
+
+ await act(() => {
+ cleverTapListenerCallback({ wzrk_dl: 'some-link' })
+ })
+
+ expect(store.getActions()).toEqual([
+ {
+ deepLink: 'some-link',
+ isSecureOrigin: true,
+ type: 'APP/OPEN_DEEP_LINK',
+ },
+ ])
+ })
+
+ it('should not open deeplink if clevertap event does not have a deep link', async () => {
+ const store = createMockStore()
+ renderHook(() => useDeepLinks(), {
+ wrapper: (component) => (
+ {component?.children ? component.children : component}
+ ),
+ })
+
+ await act(() => {
+ cleverTapListenerCallback({})
+ })
+
+ expect(store.getActions()).toEqual([])
+ })
+
+ it('should handle linking events with deep links', async () => {
+ const store = createMockStore()
+ renderHook(() => useDeepLinks(), {
+ wrapper: (component) => (
+ {component?.children ? component.children : component}
+ ),
+ })
+
+ await act(() => {
+ linkingListenerCallback({ url: 'some-link' })
+ })
+
+ expect(store.getActions()).toEqual([
+ {
+ deepLink: 'some-link',
+ isSecureOrigin: false,
+ type: 'APP/OPEN_DEEP_LINK',
+ },
+ ])
+ })
+})
diff --git a/src/app/useDeepLinks.ts b/src/app/useDeepLinks.ts
index f4629009b91..7efd41de7d3 100644
--- a/src/app/useDeepLinks.ts
+++ b/src/app/useDeepLinks.ts
@@ -2,7 +2,7 @@ import dynamicLinks from '@react-native-firebase/dynamic-links'
import CleverTap from 'clevertap-react-native'
import { useEffect, useState } from 'react'
import { useAsync } from 'react-async-hook'
-import { Linking, Platform } from 'react-native'
+import { Linking } from 'react-native'
import { deepLinkDeferred, openDeepLink } from 'src/app/actions'
import { pendingDeepLinkSelector } from 'src/app/selectors'
import { DYNAMIC_LINK_DOMAIN_URI_PREFIX, FIREBASE_ENABLED } from 'src/config'
@@ -62,7 +62,7 @@ export const useDeepLinks = () => {
}
useAsync(async () => {
- // Handles opening Clevertap deeplinks when app is closed / in background
+ // Handles opening Clevertap deeplinks when app is closed
// @ts-expect-error the clevertap ts definition has url as an object, but it
// is a string!
CleverTap.getInitialUrl(async (err: any, url: string) => {
@@ -94,17 +94,19 @@ export const useDeepLinks = () => {
}, [])
useEffect(() => {
- // Handles opening Clevertap deeplinks when app is open
+ // Handles opening Clevertap deeplinks when app is open.
CleverTap.addListener('CleverTapPushNotificationClicked', async (event: any) => {
Logger.debug('useDeepLinks/useEffect', 'CleverTapPushNotificationClicked', event)
- // Url location differs for iOS and Android
- const url = Platform.OS === 'ios' ? event.customExtras['wzrk_dl'] : event['wzrk_dl']
+ const url = event['wzrk_dl']
if (url) {
Logger.debug('useDeepLinks/useEffect', 'CleverTapPushNotificationClicked, opening url', url)
handleOpenURL({ url }, true)
}
})
+ // Handles opening any deep links, this listener is also triggered when a
+ // its a clevertap push notification or when the app is closed, so the
+ // openDeepLink action could be dispatched multiple times in those cases.
const linkingEventListener = Linking.addEventListener('url', (event) => {
Logger.debug('useDeepLinks/useEffect', 'Linking url event', event)
handleOpenURL(event)
diff --git a/src/earn/poolInfoScreen/BeforeDepositBottomSheet.test.tsx b/src/earn/poolInfoScreen/BeforeDepositBottomSheet.test.tsx
new file mode 100644
index 00000000000..c2cb12a8692
--- /dev/null
+++ b/src/earn/poolInfoScreen/BeforeDepositBottomSheet.test.tsx
@@ -0,0 +1,313 @@
+import { fireEvent, render } from '@testing-library/react-native'
+import BigNumber from 'bignumber.js'
+import React from 'react'
+import { Provider } from 'react-redux'
+import BeforeDepositBottomSheet from 'src/earn/poolInfoScreen/BeforeDepositBottomSheet'
+import { CICOFlow } from 'src/fiatExchanges/types'
+import { navigate } from 'src/navigator/NavigationService'
+import { Screens } from 'src/navigator/Screens'
+import { createMockStore } from 'test/utils'
+import { mockEarnPositions, mockTokenBalances } from 'test/values'
+
+const mockPoolTokenId = mockEarnPositions[0].dataProps.depositTokenId
+const mockToken = {
+ ...mockTokenBalances[mockPoolTokenId],
+ balance: new BigNumber(1),
+ priceUsd: new BigNumber(1),
+ lastKnownPriceUsd: new BigNumber(1),
+}
+
+describe('BeforeDepositBottomSheet', () => {
+ it('show bottom sheet correctly when hasDepositToken is true, no other tokens', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/Deposit')).toBeTruthy()
+ expect(getByTestId('Earn/ActionCard/AddMore')).toBeTruthy()
+ })
+ it('show bottom sheet correctly when hasDepositToken is true, token(s) on same chain', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/Deposit')).toBeTruthy()
+ expect(getByTestId('Earn/ActionCard/SwapAndDeposit')).toBeTruthy()
+ expect(getByTestId('Earn/ActionCard/AddMore')).toBeTruthy()
+ })
+ it('show bottom sheet correctly when hasDepositToken is true, token(s) on differnet chain', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/Deposit')).toBeTruthy()
+ expect(getByTestId('Earn/ActionCard/Swap')).toBeTruthy()
+ expect(getByTestId('Earn/ActionCard/AddMore')).toBeTruthy()
+ })
+ it('show bottom sheet correctly when hasDepositToken is true, token(s) on same and different chains', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/Deposit')).toBeTruthy()
+ expect(getByTestId('Earn/ActionCard/SwapAndDeposit')).toBeTruthy()
+ expect(getByTestId('Earn/ActionCard/CrossChainSwap')).toBeTruthy()
+ })
+ it('show bottom sheet correctly when hasDepositToken is false, can same and cross chain swap', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/SwapAndDeposit')).toBeTruthy()
+ expect(getByTestId('Earn/ActionCard/CrossChainSwap')).toBeTruthy()
+ expect(getByTestId('Earn/ActionCard/Add')).toBeTruthy()
+ })
+
+ it('show bottom sheet correctly when hasDepositToken is false, can cross chain swap', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/Swap')).toBeTruthy()
+ expect(getByTestId('Earn/ActionCard/Add')).toBeTruthy()
+ })
+
+ it('show bottom sheet correctly when hasDepositToken is false, no tokens', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/Add')).toBeTruthy()
+ expect(getByTestId('Earn/ActionCard/Transfer')).toBeTruthy()
+ })
+
+ it('navigates correctly when deposit action item is tapped', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/Deposit')).toBeTruthy()
+ fireEvent.press(getByTestId('Earn/ActionCard/Deposit'))
+ expect(navigate).toHaveBeenCalledWith(Screens.EarnEnterAmount, {
+ pool: mockEarnPositions[0],
+ })
+ })
+
+ it('navigates correctly when swap and deposit action item is tapped', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/SwapAndDeposit')).toBeTruthy()
+ fireEvent.press(getByTestId('Earn/ActionCard/SwapAndDeposit'))
+ expect(navigate).toHaveBeenCalledWith(Screens.EarnEnterAmount, {
+ pool: mockEarnPositions[0],
+ mode: 'swap-deposit',
+ })
+ })
+
+ it('navigates correctly when cross chain swap action item is tapped', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/CrossChainSwap')).toBeTruthy()
+ fireEvent.press(getByTestId('Earn/ActionCard/CrossChainSwap'))
+ expect(navigate).toHaveBeenCalledWith(Screens.SwapScreenWithBack, {
+ toTokenId: mockEarnPositions[0].dataProps.depositTokenId,
+ })
+ })
+
+ it('navigates correctly when add more action item is tapped', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/AddMore')).toBeTruthy()
+ fireEvent.press(getByTestId('Earn/ActionCard/AddMore'))
+ expect(navigate).toHaveBeenCalledWith(Screens.FiatExchangeAmount, {
+ tokenId: mockEarnPositions[0].dataProps.depositTokenId,
+ flow: CICOFlow.CashIn,
+ tokenSymbol: 'USDC',
+ })
+ })
+
+ it('navigates correctly when add action item is tapped', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/Add')).toBeTruthy()
+ fireEvent.press(getByTestId('Earn/ActionCard/Add'))
+ expect(navigate).toHaveBeenCalledWith(Screens.FiatExchangeAmount, {
+ tokenId: mockEarnPositions[0].dataProps.depositTokenId,
+ flow: CICOFlow.CashIn,
+ tokenSymbol: 'USDC',
+ })
+ })
+
+ it('navigates correctly when swap action item is tapped', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/Swap')).toBeTruthy()
+ fireEvent.press(getByTestId('Earn/ActionCard/Swap'))
+ expect(navigate).toHaveBeenCalledWith(Screens.SwapScreenWithBack, {
+ toTokenId: mockEarnPositions[0].dataProps.depositTokenId,
+ })
+ })
+
+ it('navigates correctly when transfer action item is tapped', () => {
+ const { getByTestId } = render(
+
+
+
+ )
+ expect(getByTestId('Earn/ActionCard/Transfer')).toBeTruthy()
+ fireEvent.press(getByTestId('Earn/ActionCard/Transfer'))
+ expect(navigate).toHaveBeenCalledWith(Screens.ExchangeQR, {
+ flow: CICOFlow.CashIn,
+ exchanges: [],
+ })
+ })
+})
diff --git a/src/earn/poolInfoScreen/BeforeDepositBottomSheet.tsx b/src/earn/poolInfoScreen/BeforeDepositBottomSheet.tsx
index f163e75c867..42cabb5d6f1 100644
--- a/src/earn/poolInfoScreen/BeforeDepositBottomSheet.tsx
+++ b/src/earn/poolInfoScreen/BeforeDepositBottomSheet.tsx
@@ -9,6 +9,7 @@ import { ActionCard } from 'src/earn/ActionCard'
import { BeforeDepositAction } from 'src/earn/types'
import { ExternalExchangeProvider } from 'src/fiatExchanges/ExternalExchanges'
import { CICOFlow } from 'src/fiatExchanges/types'
+import EarnCoins from 'src/icons/EarnCoins'
import QuickActionsAdd from 'src/icons/quick-actions/Add'
import QuickActionsSend from 'src/icons/quick-actions/Send'
import SwapAndDeposit from 'src/icons/SwapAndDeposit'
@@ -59,6 +60,42 @@ function AddAction({
return
}
+function AddMoreAction({
+ token,
+ forwardedRef,
+ analyticsProps,
+}: {
+ token: TokenBalance
+ forwardedRef: React.RefObject
+ analyticsProps: EarnCommonProperties & TokenProperties
+}) {
+ const { t } = useTranslation()
+
+ const action: BeforeDepositAction = {
+ name: 'AddMore',
+ title: t('earnFlow.beforeDepositBottomSheet.action.addMore', { tokenSymbol: token.symbol }),
+ details: t('earnFlow.beforeDepositBottomSheet.action.addDescription', {
+ tokenSymbol: token.symbol,
+ tokenNetwork: NETWORK_NAMES[token.networkId],
+ }),
+ iconComponent: QuickActionsAdd,
+ onPress: () => {
+ AppAnalytics.track(EarnEvents.earn_before_deposit_action_press, {
+ action: 'AddMore',
+ ...analyticsProps,
+ })
+
+ navigate(Screens.FiatExchangeAmount, {
+ tokenId: token.tokenId,
+ flow: CICOFlow.CashIn,
+ tokenSymbol: token.symbol,
+ })
+ forwardedRef.current?.close()
+ },
+ }
+ return
+}
+
function TransferAction({
token,
exchanges,
@@ -190,10 +227,45 @@ function SwapAndDepositAction({
return
}
+function DepositAction({
+ token,
+ pool,
+ forwardedRef,
+ analyticsProps,
+}: {
+ token: TokenBalance
+ pool: EarnPosition
+ forwardedRef: React.RefObject
+ analyticsProps: EarnCommonProperties & TokenProperties
+}) {
+ const { t } = useTranslation()
+
+ const action: BeforeDepositAction = {
+ name: 'Deposit',
+ title: t('earnFlow.beforeDepositBottomSheet.action.deposit', { tokenSymbol: token.symbol }),
+ details: t('earnFlow.beforeDepositBottomSheet.action.depositDescription', {
+ amount: token.balance,
+ tokenSymbol: token.symbol,
+ }),
+ iconComponent: EarnCoins,
+ onPress: () => {
+ AppAnalytics.track(EarnEvents.earn_before_deposit_action_press, {
+ action: 'Deposit',
+ ...analyticsProps,
+ })
+
+ navigate(Screens.EarnEnterAmount, { pool })
+ forwardedRef.current?.close()
+ },
+ }
+ return
+}
+
export default function BeforeDepositBottomSheet({
forwardedRef,
token,
pool,
+ hasDepositToken,
hasTokensOnSameNetwork,
hasTokensOnOtherNetworks,
canAdd,
@@ -202,6 +274,7 @@ export default function BeforeDepositBottomSheet({
forwardedRef: RefObject
token: TokenBalance
pool: EarnPosition
+ hasDepositToken: boolean
hasTokensOnSameNetwork: boolean
hasTokensOnOtherNetworks: boolean
canAdd: boolean
@@ -212,12 +285,10 @@ export default function BeforeDepositBottomSheet({
const { availableShortcutIds } = pool
const canSwapDeposit = availableShortcutIds.includes('swap-deposit') && hasTokensOnSameNetwork
- const title = canSwapDeposit
- ? t('earnFlow.beforeDepositBottomSheet.youNeedTitle', {
- tokenSymbol: token.symbol,
- tokenNetwork: NETWORK_NAMES[token.networkId],
- })
- : t('earnFlow.beforeDepositBottomSheet.beforeYouCanDepositTitle')
+ const title =
+ canSwapDeposit || hasDepositToken
+ ? t('earnFlow.beforeDepositBottomSheet.depositTitle')
+ : t('earnFlow.beforeDepositBottomSheet.beforeYouCanDepositTitle')
const analyticsProps = {
...getTokenAnalyticsProps(token),
@@ -226,48 +297,81 @@ export default function BeforeDepositBottomSheet({
depositTokenId: pool.dataProps.depositTokenId,
}
+ const showCrossChainSwap = canSwapDeposit && hasTokensOnOtherNetworks
+ const showSwap = !canSwapDeposit && (hasTokensOnSameNetwork || hasTokensOnOtherNetworks)
+ const showAdd = canAdd && !hasDepositToken
+ // Show AddMore if the token is available for cash-in, the user has the deposit token,
+ // and does not have both tokens on the same and different networks (in which case deposit and both swap and cross-chain swap will show instead)
+ const showAddMore =
+ canAdd && hasDepositToken && !(hasTokensOnSameNetwork && hasTokensOnOtherNetworks)
+ // Show Transfer if the user does not have the deposit token and does not have any tokens available for swapping
+ // OR if the token is not a cash-in token and the user does not have the deposit token and both tokens on the same and different networks
+ // (in which case deposit and both swap and cross-chain swap will show instead)
+ const showTransfer =
+ (!hasDepositToken && !hasTokensOnSameNetwork && !hasTokensOnOtherNetworks) ||
+ (!canAdd && !(hasDepositToken && hasTokensOnSameNetwork && hasTokensOnOtherNetworks))
+
return (
+ {hasDepositToken && (
+
+ )}
{canSwapDeposit && (
- <>
-
+
+ )}
+ {(canSwapDeposit || hasDepositToken) &&
+ (showCrossChainSwap || showSwap || showAdd || showAddMore || showTransfer) && (
{t('earnFlow.beforeDepositBottomSheet.crossChainAlternativeDescription', {
tokenNetwork: NETWORK_NAMES[token.networkId],
})}
- {hasTokensOnOtherNetworks && (
-
- )}
- >
+ )}
+ {showCrossChainSwap && (
+
)}
- {!canSwapDeposit && (hasTokensOnSameNetwork || hasTokensOnOtherNetworks) && (
+ {showSwap && (
)}
- {canAdd && (
+ {showAdd && (
)}
- {!canSwapDeposit && (
+ {showAddMore && (
+
+ )}
+ {showTransfer && (
{
})
})
- it('navigate to EarnEnterAmount when Deposit button is tapped and depositTokenId has a balance', () => {
- const { getByText } = render(
+ it('Show bottom sheet when Deposit button is tapped and depositTokenId has a balance', () => {
+ const { getByText, getByTestId } = render(
@@ -406,221 +398,13 @@ describe('EarnPoolInfoScreen', () => {
hasTokensOnSameNetwork: false,
hasTokensOnOtherNetworks: false,
})
- expect(navigate).toHaveBeenCalledWith(Screens.EarnEnterAmount, {
- pool: mockEarnPositions[0],
- })
- })
-
- it('show bottom sheet correctly when Deposit button is tapped and depositTokenId does not have balance, can same and cross chain swap', () => {
- const { getByText, getByTestId } = render(
-
- {
- return (
-
- )
- }}
- />
-
- )
- fireEvent.press(getByText('earnFlow.poolInfoScreen.deposit'))
- expect(AppAnalytics.track).toHaveBeenCalledWith(EarnEvents.earn_pool_info_tap_deposit, {
- providerId: 'aave',
- poolId: 'arbitrum-sepolia:0x460b97bd498e1157530aeb3086301d5225b91216',
- networkId: 'arbitrum-sepolia',
- depositTokenId: mockEarnPositions[0].dataProps.depositTokenId,
- hasDepositToken: false,
- hasTokensOnSameNetwork: true,
- hasTokensOnOtherNetworks: true,
- })
- expect(getByTestId('Earn/BeforeDepositBottomSheet')).toBeVisible()
- expect(getByTestId('Earn/ActionCard/SwapAndDeposit')).toBeTruthy()
- expect(getByTestId('Earn/ActionCard/CrossChainSwap')).toBeTruthy()
- expect(getByTestId('Earn/ActionCard/Add')).toBeTruthy()
- })
-
- it('navigates correctly when swap and deposit action item is tapped', () => {
- const { getByText, getByTestId } = render(
-
- {
- return (
-
- )
- }}
- />
-
- )
- fireEvent.press(getByText('earnFlow.poolInfoScreen.deposit'))
- expect(getByTestId('Earn/ActionCard/SwapAndDeposit')).toBeTruthy()
- fireEvent.press(getByTestId('Earn/ActionCard/SwapAndDeposit'))
- expect(navigate).toHaveBeenCalledWith(Screens.EarnEnterAmount, {
- pool: mockEarnPositions[0],
- mode: 'swap-deposit',
- })
- expect(AppAnalytics.track).toHaveBeenCalledTimes(2)
- })
-
- it('navigates correctly when cross chain swap action item is tapped', () => {
- const { getByText, getByTestId } = render(
-
- {
- return (
-
- )
- }}
- />
-
- )
- fireEvent.press(getByText('earnFlow.poolInfoScreen.deposit'))
- expect(getByTestId('Earn/ActionCard/CrossChainSwap')).toBeTruthy()
- fireEvent.press(getByTestId('Earn/ActionCard/CrossChainSwap'))
- expect(navigate).toHaveBeenCalledWith(Screens.SwapScreenWithBack, {
- toTokenId: mockEarnPositions[0].dataProps.depositTokenId,
- })
- expect(AppAnalytics.track).toHaveBeenCalledTimes(2)
- })
-
- it('navigates correctly when add action item is tapped', () => {
- const { getByText, getByTestId } = render(
-
- {
- return (
-
- )
- }}
- />
-
- )
- fireEvent.press(getByText('earnFlow.poolInfoScreen.deposit'))
- expect(getByTestId('Earn/ActionCard/Add')).toBeTruthy()
- fireEvent.press(getByTestId('Earn/ActionCard/Add'))
- expect(navigate).toHaveBeenCalledWith(Screens.FiatExchangeAmount, {
- tokenId: mockEarnPositions[0].dataProps.depositTokenId,
- flow: CICOFlow.CashIn,
- tokenSymbol: 'USDC',
- })
- expect(AppAnalytics.track).toHaveBeenCalledTimes(2)
- })
-
- it('show bottom sheet correctly when Deposit button is tapped and depositTokenId does not have balance, can cross chain swap', () => {
- const { getByText, getByTestId } = render(
-
- {
- return (
-
- )
- }}
- />
-
- )
- fireEvent.press(getByText('earnFlow.poolInfoScreen.deposit'))
- expect(AppAnalytics.track).toHaveBeenCalledWith(EarnEvents.earn_pool_info_tap_deposit, {
- providerId: 'aave',
- poolId: 'arbitrum-sepolia:0x460b97bd498e1157530aeb3086301d5225b91216',
- networkId: 'arbitrum-sepolia',
- depositTokenId: mockEarnPositions[0].dataProps.depositTokenId,
- hasDepositToken: false,
- hasTokensOnSameNetwork: false,
- hasTokensOnOtherNetworks: true,
- })
expect(getByTestId('Earn/BeforeDepositBottomSheet')).toBeVisible()
- expect(getByTestId('Earn/ActionCard/Swap')).toBeTruthy()
- expect(getByTestId('Earn/ActionCard/Add')).toBeTruthy()
- expect(getByTestId('Earn/ActionCard/Transfer')).toBeTruthy()
})
- it('navigates correctly when swap action item is tapped', () => {
- jest
- .mocked(getFeatureGate)
- .mockImplementation((gate) => gate === StatsigFeatureGates.ALLOW_CROSS_CHAIN_SWAPS)
- const { getByText, getByTestId } = render(
-
- {
- return (
-
- )
- }}
- />
-
- )
- fireEvent.press(getByText('earnFlow.poolInfoScreen.deposit'))
- expect(getByTestId('Earn/ActionCard/Swap')).toBeTruthy()
- fireEvent.press(getByTestId('Earn/ActionCard/Swap'))
- expect(navigate).toHaveBeenCalledWith(Screens.SwapScreenWithBack, {
- toTokenId: mockEarnPositions[0].dataProps.depositTokenId,
- })
- expect(AppAnalytics.track).toHaveBeenCalledTimes(2)
- })
-
- it('navigates correctly when transfer action item is tapped', () => {
- const { getByText, getByTestId } = render(
-
- {
- return (
-
- )
- }}
- />
-
- )
- fireEvent.press(getByText('earnFlow.poolInfoScreen.deposit'))
- expect(getByTestId('Earn/ActionCard/Transfer')).toBeTruthy()
- fireEvent.press(getByTestId('Earn/ActionCard/Transfer'))
- expect(navigate).toHaveBeenCalledWith(Screens.ExchangeQR, {
- flow: CICOFlow.CashIn,
- exchanges: [],
- })
- expect(AppAnalytics.track).toHaveBeenCalledTimes(2)
- })
-
- it('show bottom sheet correctly when Deposit button is tapped and depositTokenId does not have balance, no tokens', () => {
+ it('Show bottom sheet when Deposit button is tapped and depositTokenId does not have a balance', () => {
const { getByText, getByTestId } = render(
- {
- return (
-
- )
- }}
- />
+
)
fireEvent.press(getByText('earnFlow.poolInfoScreen.deposit'))
@@ -634,8 +418,6 @@ describe('EarnPoolInfoScreen', () => {
hasTokensOnOtherNetworks: false,
})
expect(getByTestId('Earn/BeforeDepositBottomSheet')).toBeVisible()
- expect(getByTestId('Earn/ActionCard/Add')).toBeTruthy()
- expect(getByTestId('Earn/ActionCard/Transfer')).toBeTruthy()
})
it('navigate to EarnConfirmationScreen when Withdraw button is tapped, no rewards and cannot partial withdraw', () => {
diff --git a/src/earn/poolInfoScreen/EarnPoolInfoScreen.tsx b/src/earn/poolInfoScreen/EarnPoolInfoScreen.tsx
index 1277f5e92dd..5c438d66ff8 100644
--- a/src/earn/poolInfoScreen/EarnPoolInfoScreen.tsx
+++ b/src/earn/poolInfoScreen/EarnPoolInfoScreen.tsx
@@ -241,11 +241,7 @@ export default function EarnPoolInfoScreen({ route, navigation }: Props) {
hasTokensOnSameNetwork,
hasTokensOnOtherNetworks,
})
- if (hasDepositToken) {
- navigate(Screens.EarnEnterAmount, { pool })
- } else {
- beforeDepositBottomSheetRef.current?.snapToIndex(0)
- }
+ beforeDepositBottomSheetRef.current?.snapToIndex(0)
}
const beforeDepositBottomSheetRef = useRef(null)
@@ -427,6 +423,7 @@ export default function EarnPoolInfoScreen({ route, navigation }: Props) {
forwardedRef={beforeDepositBottomSheetRef}
token={depositToken}
pool={pool}
+ hasDepositToken={hasDepositToken}
hasTokensOnSameNetwork={hasTokensOnSameNetwork}
hasTokensOnOtherNetworks={hasTokensOnOtherNetworks}
canAdd={canCashIn}
diff --git a/src/earn/types.ts b/src/earn/types.ts
index 7f81cba0ce4..56c4e55d254 100644
--- a/src/earn/types.ts
+++ b/src/earn/types.ts
@@ -43,10 +43,12 @@ export interface PoolInfo {
export type BeforeDepositActionName =
| 'Add'
+ | 'AddMore'
| 'Transfer'
| 'SwapAndDeposit'
| 'CrossChainSwap'
| 'Swap'
+ | 'Deposit'
export interface BeforeDepositAction {
name: BeforeDepositActionName
diff --git a/yarn.lock b/yarn.lock
index bcc781e3cbc..9967db14f1c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1588,27 +1588,27 @@
resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-5.5.3.tgz#18e3af6b8eae7984072bbeb0c0858474d7c4cefe"
integrity sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==
-"@fiatconnect/fiatconnect-sdk@^0.5.62":
- version "0.5.62"
- resolved "https://registry.yarnpkg.com/@fiatconnect/fiatconnect-sdk/-/fiatconnect-sdk-0.5.62.tgz#09b062be9b44aa340afdbe857b61c904681becbb"
- integrity sha512-aWy1RHAZf4WJ1weAsCdk/twmSmKnriyaTyEsfCGERPr9H8xQ6KzrC8QbJccCzGylMO/VcFlT1KYg3XS+09nBSA==
+"@fiatconnect/fiatconnect-sdk@^0.5.66":
+ version "0.5.66"
+ resolved "https://registry.yarnpkg.com/@fiatconnect/fiatconnect-sdk/-/fiatconnect-sdk-0.5.66.tgz#8bf79df0c0c6be0d71a39905f6e6d7d7d814d29d"
+ integrity sha512-bS7Z1Cvl1u02Br8ZGTkDvnJllhyWBqbt7aXpUS64KfgMOZXpMhKbwmgfDHE2zXdYkbQZzG4/hdR6lpQFM4KvYw==
dependencies:
"@badrap/result" "^0.2.13"
- "@fiatconnect/fiatconnect-types" "^13.3.8"
+ "@fiatconnect/fiatconnect-types" "^13.3.10"
cross-fetch "^4.0.0"
ethers "^6.13.4"
fetch-cookie "^3.0.1"
siwe "^2.3.2"
tough-cookie "^5.0.0"
tslib "^2.8.1"
- zod "^3.23.8"
+ zod "^3.24.1"
-"@fiatconnect/fiatconnect-types@^13.3.8":
- version "13.3.8"
- resolved "https://registry.yarnpkg.com/@fiatconnect/fiatconnect-types/-/fiatconnect-types-13.3.8.tgz#9f358a39b79ec9c640305e5f5a74fc6cef0bff38"
- integrity sha512-SL3CMrrikxI1rnNjfisQ/M27XgH9Tz4PuNOILIk9LmSoYvWAzVNY+i4su3IiBnT/DrAHvibcYc7JFWV9LQlAOw==
+"@fiatconnect/fiatconnect-types@^13.3.10":
+ version "13.3.10"
+ resolved "https://registry.yarnpkg.com/@fiatconnect/fiatconnect-types/-/fiatconnect-types-13.3.10.tgz#ce689c97b98fae843b4f356add5ac62958b3ca65"
+ integrity sha512-ca/MtaQGAcKPPedbl0WN+97nexlFL2yi+QrTmMLgCEpCJz12ceixEZJlDUZfvBvHIQAsleba9HUSZFcXIn38FA==
dependencies:
- zod "^3.23.8"
+ zod "^3.24.1"
"@flatten-js/interval-tree@^1.1.2":
version "1.1.3"
@@ -8435,10 +8435,10 @@ globby@^14.0.0:
slash "^5.1.0"
unicorn-magic "^0.1.0"
-google-libphonenumber@^3.2.39:
- version "3.2.39"
- resolved "https://registry.yarnpkg.com/google-libphonenumber/-/google-libphonenumber-3.2.39.tgz#915fca5e75f6fb11b2cb7d5fe47eeb7ff65fe9f0"
- integrity sha512-dpCbkY6ZxHXIHEFDwSir/gPBWkn22e2EixBv47guVs/NE8+qd35f1yu+fxQ8awRnHEXC60uhcPM9mbqmrD6nmw==
+google-libphonenumber@^3.2.40:
+ version "3.2.40"
+ resolved "https://registry.yarnpkg.com/google-libphonenumber/-/google-libphonenumber-3.2.40.tgz#ed57d0db67a8745e8e6db7983dda7f94717fb4c9"
+ integrity sha512-bzGxX/vfggcV80LVcibki+JvR91x6zHpBpovDXSfmZUGn6uLzhbYXsWll2a80EG6qTmvf8lt7KZZ/pkMml8ckw==
gopd@^1.0.1:
version "1.0.1"
@@ -8894,10 +8894,10 @@ invariant@2.2.4, invariant@^2.2.2, invariant@^2.2.4:
dependencies:
loose-envify "^1.0.0"
-io-ts@2.2.21:
- version "2.2.21"
- resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.21.tgz#4ef754176f7082a1099d04c7d5c4ea53267c530a"
- integrity sha512-zz2Z69v9ZIC3mMLYWIeoUcwWD6f+O7yP92FMVVaXEOSZH1jnVBmET/urd/uoarD1WGBY4rCj8TAyMPzsGNzMFQ==
+io-ts@2.2.22:
+ version "2.2.22"
+ resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.22.tgz#5ab0d3636fe8494a275f0266461ab019da4b8d0b"
+ integrity sha512-FHCCztTkHoV9mdBsHpocLpdTAfh956ZQcIkWQxxS0U5HT53vtrcuYdQneEJKH6xILaLNzXVl2Cvwtoy8XNN0AA==
ip-regex@^4.0.0:
version "4.3.0"
@@ -12512,10 +12512,10 @@ react-freeze@^1.0.0:
resolved "https://registry.yarnpkg.com/react-freeze/-/react-freeze-1.0.0.tgz#b21c65fe1783743007c8c9a2952b1c8879a77354"
integrity sha512-yQaiOqDmoKqks56LN9MTgY06O0qQHgV4FUrikH357DydArSZHQhl0BJFqGKIZoTqi8JizF9Dxhuk1FIZD6qCaw==
-react-i18next@^15.1.3:
- version "15.1.3"
- resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.1.3.tgz#172c3905038ea4f90699a19949a0084b5641c94f"
- integrity sha512-J11oA30FbM3NZegUZjn8ySK903z6PLBz/ZuBYyT1JMR0QPrW6PFXvl1WoUhortdGi9dM0m48/zJQlPskVZXgVw==
+react-i18next@^15.1.4:
+ version "15.2.0"
+ resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.2.0.tgz#6b51650e1e93eb4d235a4d533fcf61b3bbf4ea10"
+ integrity sha512-iJNc8111EaDtVTVMKigvBtPHyrJV+KblWG73cUxqp+WmJCcwkzhWNFXmkAD5pwP2Z4woeDj/oXDdbjDsb3Gutg==
dependencies:
"@babel/runtime" "^7.25.0"
html-parse-stringify "^3.0.1"
@@ -12535,10 +12535,10 @@ react-is@^18.0.0, react-is@^18.2.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
-react-native-adjust@^5.0.2:
- version "5.0.2"
- resolved "https://registry.yarnpkg.com/react-native-adjust/-/react-native-adjust-5.0.2.tgz#3739518b7ee3c212de63ef12195c50c313a0cc80"
- integrity sha512-X1kx1/9DIMxxfUHiHbjm/W238OiYs5KrbJujhoXde8TU4mDVaCZCKpJ8BFJWOHIdiB/vbHrOtwDMN6KlyxZang==
+react-native-adjust@^5.0.3:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/react-native-adjust/-/react-native-adjust-5.0.3.tgz#1f60ccb198d52d251619ec01543475b9635f5367"
+ integrity sha512-P+/Sx961Plc9AtlRWL4TbP+Gi4Hwsyw7COnehlyl4f/cktAdtydrl7Q8mBtC41JQvLoXam3YZaNXNsmcXGkwoA==
react-native-android-open-settings@^1.3.0:
version "1.3.0"
@@ -12727,10 +12727,10 @@ react-native-quick-base64@^2.0.5:
dependencies:
base64-js "^1.5.1"
-react-native-quick-crypto@^0.7.7:
- version "0.7.7"
- resolved "https://registry.yarnpkg.com/react-native-quick-crypto/-/react-native-quick-crypto-0.7.7.tgz#2126beff48da8f5c71210fc89b93a15ce8f5f126"
- integrity sha512-+P7MWxo0KSCCyO6rwcW654l+GYV5tVkI7cusHSL/iCahnWCisuyBLzJENzdv6MqDM9pb59QJWbrLfOzpUHZpNw==
+react-native-quick-crypto@^0.7.9:
+ version "0.7.10"
+ resolved "https://registry.yarnpkg.com/react-native-quick-crypto/-/react-native-quick-crypto-0.7.10.tgz#b65359348b4c1f2677c52ef54ab568f81627a4cf"
+ integrity sha512-ziupKopD1o58v+ywL8aTvJMXBpGf89xLQc3JKG5CRSdEUfTUu5e4ru43KIXrG6uleCX8pcgD6e6RsMqrdEy0zw==
dependencies:
"@craftzdog/react-native-buffer" "^6.0.5"
events "^3.3.0"
@@ -12760,7 +12760,7 @@ react-native-restart@^0.0.27:
resolved "https://registry.yarnpkg.com/react-native-restart/-/react-native-restart-0.0.27.tgz#43aa8210312c9dfa5ec7bd4b2f35238ad7972b19"
integrity sha512-8KScVICrXwcTSJ1rjWkqVTHyEKQIttm5AIMGSK1QG1+RS5owYlE4z/1DykOTdWfVl9l16FIk0w9Xzk9ZO6jxlA==
-react-native-safe-area-context@^4.14.0:
+react-native-safe-area-context@^4.14.1:
version "4.14.1"
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.14.1.tgz#980c3c9db02a2314fa8ceb07f614728802320367"
integrity sha512-+tUhT5WBl8nh5+P+chYhAjR470iCByf9z5EYdCEbPaAK3Yfzw+o8VRPnUgmPAKlSccOgQBxx3NOl/Wzckn9ujg==
@@ -16022,7 +16022,7 @@ zod@3.22.4:
resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff"
integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==
-zod@^3.21.4, zod@^3.23.8:
- version "3.23.8"
- resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
- integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
+zod@^3.21.4, zod@^3.24.1:
+ version "3.24.1"
+ resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.1.tgz#27445c912738c8ad1e9de1bea0359fa44d9d35ee"
+ integrity sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==