diff --git a/.github/workflows/e2e-main.yml b/.github/workflows/e2e-main.yml index be9edc6721b..0ffa0f2324f 100644 --- a/.github/workflows/e2e-main.yml +++ b/.github/workflows/e2e-main.yml @@ -32,7 +32,7 @@ jobs: # 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'] + android-api-level: [27] uses: ./.github/workflows/e2e-android.yml with: android-api-level: ${{ matrix.android-api-level }} diff --git a/Gemfile b/Gemfile index 0586461d232..8746aab3230 100644 --- a/Gemfile +++ b/Gemfile @@ -1,9 +1,6 @@ source "https://rubygems.org" - -# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper -# bound in the template on Cocoapods with next React Native release. -gem 'cocoapods', '>= 1.15.2', '< 1.16' +gem 'cocoapods', '>= 1.16.2', '< 1.17' gem "fastlane" gem "xcpretty" diff --git a/Gemfile.lock b/Gemfile.lock index bf0bc99a034..01c5ff10c2d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,7 +5,7 @@ GEM base64 nkf rexml - activesupport (6.1.7.3) + activesupport (6.1.7.10) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -37,10 +37,10 @@ GEM babosa (1.0.4) base64 (0.2.0) claide (1.1.0) - cocoapods (1.15.2) + cocoapods (1.16.2) addressable (~> 2.8) claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.15.2) + cocoapods-core (= 1.16.2) cocoapods-deintegrate (>= 1.0.3, < 2.0) cocoapods-downloader (>= 2.1, < 3.0) cocoapods-plugins (>= 1.0.0, < 2.0) @@ -54,8 +54,8 @@ GEM molinillo (~> 0.8.0) nap (~> 1.0) ruby-macho (>= 2.3.0, < 3.0) - xcodeproj (>= 1.23.0, < 2.0) - cocoapods-core (1.15.2) + xcodeproj (>= 1.27.0, < 2.0) + cocoapods-core (1.16.2) activesupport (>= 5.0, < 8) addressable (~> 2.8) algoliasearch (~> 1.0) @@ -78,7 +78,7 @@ GEM colored2 (3.1.2) commander (4.6.0) highline (~> 2.0.0) - concurrent-ruby (1.2.2) + concurrent-ruby (1.3.4) declarative (0.0.20) digest-crc (0.6.5) rake (>= 12.0.0, < 14.0.0) @@ -162,7 +162,9 @@ GEM fastlane-plugin-emerge (0.10.4) faraday (~> 1.1) fastlane-plugin-versioning (0.6.0) - ffi (1.15.5) + ffi (1.17.0) + ffi (1.17.0-arm64-darwin) + ffi (1.17.0-x86_64-darwin) fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) @@ -206,19 +208,19 @@ GEM http-cookie (1.0.7) domain_name (~> 0.5) httpclient (2.8.3) - i18n (1.14.1) + i18n (1.14.6) concurrent-ruby (~> 1.0) jmespath (1.6.2) - json (2.7.2) + json (2.9.0) jwt (2.8.2) base64 mini_magick (4.13.2) mini_mime (1.1.5) - minitest (5.18.0) + minitest (5.25.4) molinillo (0.8.0) multi_json (1.15.0) multipart-post (2.4.1) - nanaimo (0.3.0) + nanaimo (0.4.0) nap (1.1.0) naturally (2.2.1) netrc (0.11.0) @@ -233,7 +235,7 @@ GEM trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.3.7) + rexml (3.4.0) rouge (2.0.7) ruby-macho (2.5.1) ruby2_keywords (0.0.5) @@ -255,25 +257,25 @@ GEM tty-screen (0.8.2) tty-spinner (0.9.3) tty-cursor (~> 0.7) - typhoeus (1.4.0) + typhoeus (1.4.1) ethon (>= 0.9.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) uber (0.1.0) unicode-display_width (2.5.0) word_wrap (1.0.0) - xcodeproj (1.25.0) + xcodeproj (1.27.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) - nanaimo (~> 0.3.0) - rexml (>= 3.3.2, < 4.0) + nanaimo (~> 0.4.0) + rexml (>= 3.3.6, < 4.0) xcpretty (0.3.0) rouge (~> 2.0.7) xcpretty-travis-formatter (1.0.1) xcpretty (~> 0.2, >= 0.0.7) - zeitwerk (2.6.8) + zeitwerk (2.6.18) PLATFORMS ruby @@ -282,7 +284,7 @@ PLATFORMS universal-darwin-21 DEPENDENCIES - cocoapods (>= 1.15.2, < 1.16) + cocoapods (>= 1.16.2, < 1.17) fastlane fastlane-plugin-emerge fastlane-plugin-versioning diff --git a/e2e/src/QRScanner.spec.js b/e2e/src/QRScanner.spec.js index a63e27858a0..46b4f89b172 100644 --- a/e2e/src/QRScanner.spec.js +++ b/e2e/src/QRScanner.spec.js @@ -1,54 +1,52 @@ import { reloadReactNative } from './utils/retries' import { quickOnboarding, waitForElementById } from './utils/utils' +const verifyCamera = async () => { + // testID 'Camera' is one of the few that works on Android. iOS uses 'CameraScanInfo' because the camera is behind an opacity overlay + device.getPlatform() === 'ios' + ? await waitForElementById('CameraScanInfo') + : await waitForElementById('Camera') +} + describe('Given QR Scanner', () => { beforeAll(async () => { await quickOnboarding() + await reloadReactNative() }) describe('When opening QR scanner', () => { it('Then should display QR code', async () => { - await reloadReactNative() - await waitForElementById('HomeAction-Receive') - await element(by.id('HomeAction-Receive')).tap() + await waitForElementById('HomeAction-Receive', { tap: true }) await waitForElementById('QRCode') - await expect(element(by.id('QRCode'))).toBeVisible() }) it('Then should be able to toggle camera', async () => { - await waitForElementById('Scan') - await element(by.id('Scan')).tap() - await waitForElementById('CameraScanInfo') - await expect(element(by.id('CameraScanInfo'))).toBeVisible() + await waitForElementById('Scan', { tap: true }) + await verifyCamera() }) it('Then should be able to toggle to QR code', async () => { - await waitForElementById('My Code') - await element(by.id('My Code')).tap() + await waitForElementById('My Code', { tap: true }) await waitForElementById('QRCode') - await expect(element(by.id('QRCode'))).toBeVisible() }) it('Then should be able to close QR code scanner', async () => { - await waitForElementById('Times') - await element(by.id('Times')).tap() + await waitForElementById('Times', { tap: true }) await waitForElementById('HomeAction-Send') - await expect(element(by.id('HomeAction-Send'))).toBeVisible() }) }) describe("When 'scanning' QR", () => { beforeEach(async () => { await reloadReactNative() - await waitForElementById('HomeAction-Receive') - await element(by.id('HomeAction-Receive')).tap() - await waitForElementById('Scan') - await element(by.id('Scan')).tap() - await waitForElementById('CameraScanInfo') - await element(by.id('CameraScanInfo')).tap() + await waitForElementById('HomeAction-Receive', { tap: true }) + await waitForElementById('Scan', { tap: true }) + await verifyCamera() }) it('Then should be able to handle Celo pay QR', async () => { + // Use instead of waitForElementById as the element is not visible behind opacity overlay + await element(by.id('CameraScanInfo')).tap() await waitForElementById('ManualInput') await element(by.id('ManualInput')).replaceText( 'celo://wallet/pay?address=0xe5F5363e31351C38ac82DBAdeaD91Fd5a7B08846' @@ -62,6 +60,8 @@ describe('Given QR Scanner', () => { }) it('Then should handle address only QR', async () => { + // Use instead of waitForElementById as the element is not visible behind opacity overlay + await element(by.id('CameraScanInfo')).tap() await waitForElementById('ManualInput') await element(by.id('ManualInput')).replaceText('0xe5F5363e31351C38ac82DBAdeaD91Fd5a7B08846') await waitForElementById('ManualSubmit') diff --git a/ios/MobileStack.xcodeproj/project.pbxproj b/ios/MobileStack.xcodeproj/project.pbxproj index 1d26139c50b..5cfff439eaf 100644 --- a/ios/MobileStack.xcodeproj/project.pbxproj +++ b/ios/MobileStack.xcodeproj/project.pbxproj @@ -451,7 +451,6 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-MobileStack/Pods-MobileStack-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/AdjustSignature/AdjustSigSdk.framework/AdjustSigSdk", "${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-DoubleConversion/double-conversion.framework/double-conversion", "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL", "${PODS_XCFRAMEWORKS_BUILD_DIR}/PersonaInquirySDK2/Persona2.framework/Persona2", @@ -459,7 +458,6 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AdjustSigSdk.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/double-conversion.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Persona2.framework", diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 1e8c8a7a994..b4113bb5e74 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -4,11 +4,9 @@ PODS: - JWTDecode (= 3.1.0) - React-Core - SimpleKeychain (= 1.1.0) - - Adjust (5.0.1): - - Adjust/Adjust (= 5.0.1) - - Adjust/Adjust (5.0.1): - - AdjustSignature (~> 3.18) - - AdjustSignature (3.20.2) + - Adjust (4.38.2): + - Adjust/Core (= 4.38.2) + - Adjust/Core (4.38.2) - Auth0 (2.7.2): - JWTDecode (~> 3.1) - SimpleKeychain (~> 1.1) @@ -563,8 +561,8 @@ PODS: - React-jsinspector (0.72.15) - React-logger (0.72.15): - glog - - react-native-adjust (5.0.2): - - Adjust (= 5.0.1) + - react-native-adjust (4.38.1): + - Adjust (= 4.38.2) - React-Core - react-native-camera (4.2.1): - React-Core @@ -596,7 +594,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 @@ -966,7 +964,6 @@ DEPENDENCIES: SPEC REPOS: trunk: - Adjust - - AdjustSignature - Auth0 - CleverTap-iOS-SDK - CocoaAsyncSocket @@ -1200,14 +1197,13 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: - A0Auth0: 47cb14c87d549b95b92242675ff2198ccd9dcbc5 - Adjust: f27daaa40d0df5550b89dd428cd8545d812e1f6d - AdjustSignature: f42d8c64cda8361ff5b5a31e4536d82076be4306 + A0Auth0: 3e5033500f199020186a42c49020ecd508a72b27 + Adjust: 5a0f813fe079212bed61404d1f635cc330068b4a Auth0: 28cb24cb19ebd51f0b07751f16d83b59f4019532 boost: 7dcd2de282d72e344012f7d6564d024930a6a440 - BVLinearGradient: 880f91a7854faff2df62518f0281afb1c60d49a3 + BVLinearGradient: cb006ba232a1f3e4f341bb62c42d1098c284da70 CleverTap-iOS-SDK: 78ea6d752d84918f0426f7b3959777d862bcb348 - clevertap-react-native: 34c3acaf46e7f8cd4f349dd5a1f851580d410be3 + clevertap-react-native: 8c7a97304df1ee9640f963cc08a9069c42b4935c CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 CTNotificationService: 844eb0cf5a6260b76e05420dde49312b72c5ad7c DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 @@ -1248,51 +1244,51 @@ SPEC CHECKSUMS: libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009 lottie-ios: 8f97d3271e155c2d688875c29cd3c74908aef5f8 - lottie-react-native: 8f9d4be452e23f6e5ca0fdc11669dc99ab52be81 + lottie-react-native: 5d89c05930d4180a1e39b1757d46e6c0eec90255 nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c PersonaInquirySDK2: 8153173c5f6d4e964874c9f0d7b375652c9bb6f9 PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4 - RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 + RCT-Folly: 8dc08ca5a393b48b1c523ab6220dfdcc0fe000ad RCTRequired: fb207f74935626041e7308c9e88dcdda680f1073 RCTTypeSafety: 146fd11361680250b7580dd1f7f601995cfad1b1 React: f3712351445cc96ba507425675a0cd8d31321d0c React-callinvoker: dcc51a66e02d20a70aeca2abbb1388d4d3011bf8 - React-Codegen: 3f518318a055c69ea70ac02ca112731b6a57ea9a - React-Core: c74a1ddd76b14653cbf4f70d6d4754d14921ebaa - React-CoreModules: 8f51cf66f7d25d7d1bd009168df709e81b6ac155 - React-cxxreact: 2150e05cdd30c815c1bf27f41062cd33832ffe31 + React-Codegen: ad37706be19422a8dbdbcec953715ae5fc245726 + React-Core: e84c4cd970037bd279a7d69f39ff414ff869158f + React-CoreModules: 148a89a7def1f55eb79d1742acfac82ef170fd11 + React-cxxreact: eea5a7db909384f66c283e8ecf3a245a7fb97710 React-debug: 90b3e19503fd156170027d2d5bf93880f968c920 - React-hermes: 1ed296db543b7fdb01916a8e56255fcea0758264 - React-jsi: af5a8eaca28d67822fb14c648486d40737d2d2ab - React-jsiexecutor: d3eef5ddc78eeb9f0d02bed657a7f41d4910b966 + React-hermes: 2a9af75cde93f884cf71749a04034ca8f2af56f9 + React-jsi: 8e683815f2c49c5e954707bd9270d85b4278ff6e + React-jsiexecutor: 137efedd74aece84909335af73554e91dfe24165 React-jsinspector: b86a8abae760c28d69366bbc1d991561e51341ed - React-logger: ed7c9e01e58529065e7da6bf8318baf15024283e - react-native-adjust: 6a73063a62fb0f21dd2220f15b315c1e323268b0 - react-native-camera: 3eae183c1d111103963f3dd913b65d01aef8110f - react-native-compat: 24dedfbd7faba258560048606bc0fe9e73f7d2a3 - react-native-config: 8f7283449bbb048902f4e764affbbf24504454af - react-native-contacts: fd1614c74777089ebb6b0a0e3847dd78130ef9f4 - react-native-cookies: 672b2431ca44da2e2942af086d0c83aae42b989a - react-native-flipper: 9c1957af24b76493ba74f46d000a5c1d485e7731 - react-native-in-app-review: db8bb167a5f238e7ceca5c242d6b36ce8c4404a4 - react-native-launch-arguments: 5f41e0abf88a15e3c5309b8875d6fd5ac43df49d - react-native-netinfo: f0a9899081c185db1de5bb2fdc1c88c202a059ac - react-native-pager-view: c65514a81a384c3ce244b5bd87167761740308d3 - react-native-quick-crypto: e254783f9681542c182f9439f91139137e3b9e48 - react-native-restart: 7595693413fe3ca15893702f2c8306c62a708162 - react-native-safe-area-context: 141eca0fd4e4191288dfc8b96a7c7e1c2983447a - react-native-shake: 0c36371dd63019afa68890ccc65a442ee21b4dde - react-native-simple-toast: 1f1cc551d419bc0ab05dcb0136554006c274789d - react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457 - react-native-video: c2fbeb7e78f70486918b0a6b88cee7b2ae0b0973 - react-native-webview: f284fcfdf162521ffe19fd6c68fd837f3e0ce174 - React-NativeModulesApple: a2c783eea2b9354534d6e991669d5051435b51db + React-logger: 8c0f8173197ad28ac3212c18f8141690209dfe52 + react-native-adjust: a3d3fd6edd8d4a7ef707ebc45deaecab1ffb2afc + react-native-camera: 079d80421f0572d6b4e836908114d614d0adb553 + react-native-compat: 03e54a7e1a09f56471b0af199867b4edf13de7ca + react-native-config: ea75335a7cca1d3326de1da384227e580a7c082e + react-native-contacts: 5eeeb8bff95a0e1680a11329e15653eb73d29a1d + react-native-cookies: f7772e020f2d61cbbb591cf769ac352b8c1517e6 + react-native-flipper: 03f211cc2af0ecf4b9569f0dddcc3e5d2b2d8201 + react-native-in-app-review: b3d1eed3d1596ebf6539804778272c4c65e4a400 + react-native-launch-arguments: d4759f7591e2766e6c5ec746b7032429edaf7058 + react-native-netinfo: cec9c4e86083cb5b6aba0e0711f563e2fbbff187 + react-native-pager-view: 13652f56368120d8126ac3535a0d7fb0e9673c20 + react-native-quick-crypto: 6831a30c5ea409f8a42de84183edb64cd3c1931e + react-native-restart: 0bc732f4461709022a742bb29bcccf6bbc5b4863 + react-native-safe-area-context: 758e894ca5a9bd1868d2a9cfbca7326a2b6bf9dc + react-native-shake: a426aa83eb1bd32b931153a2479f5fcfd909e29a + react-native-simple-toast: f6316baf3870934e6e92cf48dbc9e330a5c8eb82 + react-native-splash-screen: 95994222cc95c236bd3cdc59fe45ed5f27969594 + react-native-video: 50cf661686af98a65bd40fe17b5fac54bdcf38e9 + react-native-webview: e27ee34f9a3bd53e833d8837ae2b09e936f60f41 + React-NativeModulesApple: e29c0ef4359dbb256738a05b39cc98627cf6c698 React-perflogger: 6acc671f527e69c0cd93b8e62821d33d3ddf25ca React-RCTActionSheet: 569bb9db46d85565d14697e15ecf2166e035eb07 React-RCTAnimation: fdf4c2ebb36ec54c30549c8ac271e5fbea10fe41 - React-RCTAppDelegate: fde369aa61c48b28fac14145bc4880e286aa2b0d - React-RCTBlob: d418809ccda6ecbfc82a57bd9bb0fba7a38c1d19 + React-RCTAppDelegate: 391104fb502596671a4dd6f7e7f149c4206de761 + React-RCTBlob: 125797666f071f966843675ec12f55776c690622 React-RCTImage: c0c941121b5a423d44ab8e5426fd871d50a9c6b6 React-RCTLinking: 620e07dc9217af617e4540bfe6e851bde0070700 React-RCTNetwork: e20e521de2ada7a3ab3777de28093cdc940d6b63 @@ -1301,47 +1297,47 @@ SPEC CHECKSUMS: React-RCTVibration: 1385c17d7b75f68b9567b96869f16d79aff002e7 React-rncore: ec681c42589abf33de39a8b3487463fac7649099 React-runtimeexecutor: d4f7ff5073fcf87e14dbf89541d434218630246e - React-runtimescheduler: 27262b26bc4d020f47fe34bf7bb0eb498164d9eb - React-utils: a2dfc4c77bb4f7fe4080219a82ace8929f334b1a - ReactCommon: 69acb76221a4c9d1b5740821ee1f0df89068fd6d + React-runtimescheduler: 8fb839e9b6dcc08f1d14a3f3a17b2c264313957c + React-utils: 6adfca7d3daf22cb012a0afd46cf307abcdc571d + ReactCommon: 8293fdd084a84919f4c02483642d281069c0ea86 RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21 - RNCAsyncStorage: cc6479c4acd84cc7004946946c8afe30b018184d - RNCClipboard: 69ab8e51324d5b351f6ba72bbdb72478087a2c64 - RNCMaskedView: 7fd800fe3508752504dbdc0a231cec05211ae769 - RNCPicker: d162737e03e48797110dbb60e5ddc03012e87e0b - RNDeviceInfo: 29e01d5ae94bdb5a0f6c11a4c438132545b4df80 - RNExitApp: 00036cabe7bacbb413d276d5520bf74ba39afa6a - RNFastImage: 5c9c9fed9c076e521b3f509fe79e790418a544e8 - RNFBAnalytics: 695dcc7123daa3cf938cf7123b8715c0b5c8c657 - RNFBApp: a0618c20c09e0e0df667c3543c18062287848510 - RNFBAuth: 20f4ea90149cb8b665f21c22a221cd4d2a3731c8 - RNFBDatabase: c3b27ba1274d6686cb8eb6c5333a1513d7675c42 - RNFBDynamicLinks: 8c9b4ca502d5ab02f7456fc6d4beb12767dcae37 - RNFBMessaging: 15439cf96be05b47d95334052afc306eac89c2ce - RNFBRemoteConfig: 37959d81004ff1232f26276d02655c992b1ce715 - RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 - RNGestureHandler: e9a9570cf592b2fa0f2dc90ae06f040d3ed4e4d3 - RNKeychain: bfe3d12bf4620fe488771c414530bf16e88f3678 - RNLocalize: 298e85ce16540a11de40c1a588ead39fc5e9a072 - RNPermissions: da2a4ded375aa8292d85ed93676e102c203d4717 - RNPersonaInquiry2: 3ab52078e891a5d2fa39bf7cc9119ca27f0337fd - RNReactNativeHapticFeedback: a15559aa2aa8b5e5d49616fd84259dfb3c415230 - RNReanimated: 739d696f5bd3bea1d675a86caec05064ab4d898f - RNScreens: cdb28656300719a3708d2209fad0bd6d83769d3a - RNSentry: b24b7150b302ce1c38cc679c548a8ef1aef831fa - RNShare: 8006ea4fac2acbbf55705d975dc6daefb3cb8178 - RNSVG: 4590aa95758149fa27c5c83e54a6a466349a1688 + RNCAsyncStorage: c91d753ede6dc21862c4922cd13f98f7cfde578e + RNCClipboard: dbcf25b8f666b4685c02eeb65be981d30198e505 + RNCMaskedView: fc28d1d31850784652229bb83f3c54799055acc9 + RNCPicker: d8662eb6615e3401acb590c44b97b2af3beb1e53 + RNDeviceInfo: ae26ae45db3f9937f038a284bcd0a1db8d70db96 + RNExitApp: 4432b9b7cc5ccec9f91c94e507849891282befd4 + RNFastImage: 462a183c4b0b6b26fdfd639e1ed6ba37536c3b87 + RNFBAnalytics: 2fe1c871d8d7c5953cd4dfe5cad7a357758dd976 + RNFBApp: c58a3c92d6aa0da8767daf13edc21cffcb4a8970 + RNFBAuth: 60b2f1b331961fa34cfb34e06a0f5ff1a2c822b1 + RNFBDatabase: ef0731594d10df0d48f47c91eb124c8ee2eb15dc + RNFBDynamicLinks: f761317263bd33aa3bced596bdc0f345d53b4c1b + RNFBMessaging: d90c3a9e3da96dc2cf150a01d3aa0a68a3c32501 + RNFBRemoteConfig: 1c92f072b1772b91663247b07a711cd4e9e191e8 + RNFS: 89de7d7f4c0f6bafa05343c578f61118c8282ed8 + RNGestureHandler: b81313e62e717cc165ea3b99436aa305d04c57b4 + RNKeychain: bbe2f6d5cc008920324acb49ef86ccc03d3b38e4 + RNLocalize: d024afa9204c13885e61dc88b8190651bcaabac9 + RNPermissions: 1d002266e43df33d7080d5355a64b7d12bdb5e75 + RNPersonaInquiry2: 4202f797d7a172af2908f271954123858abe47bf + RNReactNativeHapticFeedback: 341b13ced53433a826af92ba83db57803c733ec0 + RNReanimated: 87db48292c3059cf8a9a488ff6abc79c5d388692 + RNScreens: 498375cc973b98a886c6ce7e1a76423579700429 + RNSentry: a0dd196e728aeaf54ce5cb8e793ee58128a585fd + RNShare: 06c6b34c1a574406b1590a553ba5a80af1204d69 + RNSVG: 38b927ba26d717c85522fbf9a04b87dcd2d8227a SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d - segment-analytics-react-native: d57ed4971cbb995706babf29215ebdbf242ecdab + segment-analytics-react-native: 6f98edf18246782ee7428c5380c6519a3d2acf5e Sentry: 54d0fe6c0df448497c8ed4cce66ccf7027e1823e SimpleKeychain: f8707c8e97b38c6a6e687b17732afc9bcef06439 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 - sovran-react-native: eec37f82e4429f0e3661f46aaf4fcd85d1b54f60 + sovran-react-native: a3ad3f8ff90c2002b2aa9790001a78b0b0a38594 Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 Yoga: 6f5ab94cd8b1ecd04b6e973d0bc583ede2a598cc YogaKit: f782866e155069a2cca2517aafea43200b01fd5a PODFILE CHECKSUM: e49ec411923f9bb1906dff8d0e27d0aa410bf3ad -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/package.json b/package.json index bf0c5505ff2..2e76460c916 100644 --- a/package.json +++ b/package.json @@ -73,9 +73,9 @@ "dependencies": { "@badrap/result": "~0.2.13", "@crowdin/ota-client": "^0.7.0", - "@fiatconnect/fiatconnect-sdk": "^0.5.62", - "@fiatconnect/fiatconnect-types": "^13.3.8", - "@gorhom/bottom-sheet": "^4.6.4", + "@fiatconnect/fiatconnect-sdk": "^0.5.66", + "@fiatconnect/fiatconnect-types": "^13.3.10", + "@gorhom/bottom-sheet": "^5.0.6", "@json-rpc-tools/utils": "^1.7.6", "@noble/secp256k1": "^1.7.1", "@react-native-async-storage/async-storage": "^2.1.0", @@ -91,13 +91,13 @@ "@react-native-firebase/remote-config": "19.1.0", "@react-native-masked-view/masked-view": "^0.3.2", "@react-native-picker/picker": "^2.10.2", - "@react-navigation/bottom-tabs": "^7.1.3", - "@react-navigation/devtools": "^7.0.14", - "@react-navigation/elements": "^2.2.4", - "@react-navigation/material-top-tabs": "^7.0.18", - "@react-navigation/native": "^7.0.13", - "@react-navigation/native-stack": "^7.1.14", - "@reduxjs/toolkit": "^2.4.0", + "@react-navigation/bottom-tabs": "^7.2.0", + "@react-navigation/devtools": "^7.0.15", + "@react-navigation/elements": "^2.2.5", + "@react-navigation/material-top-tabs": "^7.1.0", + "@react-navigation/native": "^7.0.14", + "@react-navigation/native-stack": "^7.2.0", + "@reduxjs/toolkit": "^2.5.0", "@scure/bip39": "^1.5.0", "@segment/analytics-react-native": "^2.20.3", "@segment/analytics-react-native-plugin-adjust": "^0.7.0", @@ -122,20 +122,20 @@ "fp-ts": "2.16.9", "futoin-hkdf": "^1.5.3", "fuzzysort": "^3.1.0", - "google-libphonenumber": "^3.2.39", - "i18next": "^23.16.8", + "google-libphonenumber": "^3.2.40", + "i18next": "^24.1.0", "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.2.0", "react-native": "0.72.15", - "react-native-adjust": "^5.0.2", + "react-native-adjust": "^4.38.1", "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.10", "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", @@ -174,7 +174,7 @@ "react-native-url-polyfill": "^2.0.0", "react-native-video": "^6.6.4", "react-native-webview": "^13.12.5", - "react-redux": "^9.1.2", + "react-redux": "^9.2.0", "redux": "^5.0.1", "redux-persist": "^6.0.0", "redux-persist-fs-storage": "^1.3.0", @@ -187,7 +187,7 @@ "typed-redux-saga": "^1.5.0", "uuid": "^10.0.0", "victory-native": "^36.9.2", - "viem": "^2.21.53", + "viem": "^2.21.55", "web3-utils": "^4.3.3" }, "devDependencies": { @@ -232,7 +232,7 @@ "babel-jest": "^29.2.1", "babel-plugin-module-resolver": "^4.1.0", "chalk": "^4.0.0", - "detox": "^20.18.5", + "detox": "^20.28.0", "dotenv": "^16.3.1", "easy-table": "^1.2.0", "escape-string-regexp": "^1.0.5", diff --git a/renovate.json5 b/renovate.json5 index 21e1c34b26f..49a025a44de 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -100,5 +100,6 @@ ignoreDeps: [ 'lottie-react-native', // TODO (act-1187): handle 6.x breaking changes and upgrade 'react-native-shake', // https://github.com/Doko-Demo-Doa/react-native-shake/issues/62 + 'react-native-adjust', // TODO: remove once this issue is resolved https://github.com/segmentio/analytics-react-native/issues/1036 ], } diff --git a/src/account/LicenseDisclaimer.txt b/src/account/LicenseDisclaimer.txt index d2460e3ac0f..3d136c55caf 100644 --- a/src/account/LicenseDisclaimer.txt +++ b/src/account/LicenseDisclaimer.txt @@ -553,7 +553,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ----- -The following software may be included in this product: @jest/create-cache-key-function, @jest/environment, @jest/fake-timers, @jest/schemas, @jest/types, hermes-estree, hermes-parser, jest-environment-node, jest-get-type, jest-message-util, jest-mock, jest-util, jest-validate, pretty-format, react-native, scheduler. A copy of the source code may be downloaded from https://github.com/jestjs/jest.git (@jest/create-cache-key-function), https://github.com/jestjs/jest.git (@jest/environment), https://github.com/jestjs/jest.git (@jest/fake-timers), https://github.com/jestjs/jest.git (@jest/schemas), https://github.com/jestjs/jest.git (@jest/types), git@github.com:facebook/hermes.git (hermes-estree), git@github.com:facebook/hermes.git (hermes-parser), https://github.com/jestjs/jest.git (jest-environment-node), https://github.com/jestjs/jest.git (jest-get-type), https://github.com/jestjs/jest.git (jest-message-util), https://github.com/jestjs/jest.git (jest-mock), https://github.com/jestjs/jest.git (jest-util), https://github.com/jestjs/jest.git (jest-validate), https://github.com/jestjs/jest.git (pretty-format), https://github.com/facebook/react-native.git (react-native), https://github.com/facebook/react.git (scheduler). This software contains the following license and notice below: +The following software may be included in this product: @jest/create-cache-key-function, @jest/environment, @jest/fake-timers, @jest/schemas, @jest/types, hermes-estree, hermes-parser, jest-environment-node, jest-get-type, jest-message-util, jest-mock, jest-util, jest-validate, pretty-format, react-native, scheduler, use-sync-external-store. A copy of the source code may be downloaded from https://github.com/jestjs/jest.git (@jest/create-cache-key-function), https://github.com/jestjs/jest.git (@jest/environment), https://github.com/jestjs/jest.git (@jest/fake-timers), https://github.com/jestjs/jest.git (@jest/schemas), https://github.com/jestjs/jest.git (@jest/types), git@github.com:facebook/hermes.git (hermes-estree), git@github.com:facebook/hermes.git (hermes-parser), https://github.com/jestjs/jest.git (jest-environment-node), https://github.com/jestjs/jest.git (jest-get-type), https://github.com/jestjs/jest.git (jest-message-util), https://github.com/jestjs/jest.git (jest-mock), https://github.com/jestjs/jest.git (jest-util), https://github.com/jestjs/jest.git (jest-validate), https://github.com/jestjs/jest.git (pretty-format), https://github.com/facebook/react-native.git (react-native), https://github.com/facebook/react.git (scheduler), https://github.com/facebook/react.git (use-sync-external-store). This software contains the following license and notice below: MIT License @@ -579,7 +579,7 @@ SOFTWARE. ----- -The following software may be included in this product: @jest/types, babel-plugin-transform-flow-enums, flow-enums-runtime, jest-regex-util, jest-util, jest-worker, jscodeshift, pretty-format, react, react-is, react-refresh, react-shallow-renderer, use-sync-external-store. A copy of the source code may be downloaded from https://github.com/facebook/jest.git (@jest/types), git+https://github.com/facebook/flow.git (babel-plugin-transform-flow-enums), git+https://github.com/facebook/flow.git (flow-enums-runtime), https://github.com/facebook/jest.git (jest-regex-util), https://github.com/facebook/jest.git (jest-util), https://github.com/facebook/jest.git (jest-worker), https://github.com/facebook/jscodeshift.git (jscodeshift), https://github.com/facebook/jest.git (pretty-format), https://github.com/facebook/react.git (react), https://github.com/facebook/react.git (react-is), https://github.com/facebook/react.git (react-refresh), https://github.com/NMinhNguyen/react-shallow-renderer.git (react-shallow-renderer), https://github.com/facebook/react.git (use-sync-external-store). This software contains the following license and notice below: +The following software may be included in this product: @jest/types, babel-plugin-transform-flow-enums, flow-enums-runtime, jest-regex-util, jest-util, jest-worker, jscodeshift, pretty-format, react, react-is, react-refresh, react-shallow-renderer. A copy of the source code may be downloaded from https://github.com/facebook/jest.git (@jest/types), git+https://github.com/facebook/flow.git (babel-plugin-transform-flow-enums), git+https://github.com/facebook/flow.git (flow-enums-runtime), https://github.com/facebook/jest.git (jest-regex-util), https://github.com/facebook/jest.git (jest-util), https://github.com/facebook/jest.git (jest-worker), https://github.com/facebook/jscodeshift.git (jscodeshift), https://github.com/facebook/jest.git (pretty-format), https://github.com/facebook/react.git (react), https://github.com/facebook/react.git (react-is), https://github.com/facebook/react.git (react-refresh), https://github.com/NMinhNguyen/react-shallow-renderer.git (react-shallow-renderer). This software contains the following license and notice below: MIT License @@ -11794,28 +11794,27 @@ SOFTWARE. The following software may be included in this product: react-native-adjust. A copy of the source code may be downloaded from git://github.com/adjust/react_native_sdk.git. This software contains the following license and notice below: -The MIT License (MIT) +The Adjust SDK is licensed under the MIT License. -Copyright (c) 2016-Present Adjust GmbH, http://www.adjust.com +Copyright (c) 2012-Present Adjust GmbH, http://www.adjust.com -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. ----- diff --git a/src/earn/EarnEnterAmount.test.tsx b/src/earn/EarnEnterAmount.test.tsx index f8d38f6c645..73f720ccd30 100644 --- a/src/earn/EarnEnterAmount.test.tsx +++ b/src/earn/EarnEnterAmount.test.tsx @@ -8,6 +8,7 @@ import AppAnalytics from 'src/analytics/AppAnalytics' import { EarnEvents } from 'src/analytics/Events' import EarnEnterAmount from 'src/earn/EarnEnterAmount' import { usePrepareEnterAmountTransactionsCallback } from 'src/earn/hooks' +import { Status as EarnStatus } from 'src/earn/slice' import { CICOFlow } from 'src/fiatExchanges/types' import { navigate } from 'src/navigator/NavigationService' import { Screens } from 'src/navigator/Screens' @@ -35,7 +36,6 @@ import { mockTokenBalances, mockUSDCAddress, } from 'test/values' -import { Status as EarnStatus } from 'src/earn/slice' jest.mock('src/earn/hooks') jest.mock('react-native-localize') @@ -501,13 +501,6 @@ describe('EarnEnterAmount', () => { await waitFor(() => expect(getByText('earnFlow.enterAmount.continue')).not.toBeDisabled()) - expect(getByTestId('EarnEnterAmount/Withdraw/Crypto')).toBeTruthy() - expect(getByTestId('EarnEnterAmount/Withdraw/Crypto')).toHaveTextContent('11.00 USDC') - - expect(getByTestId('EarnEnterAmount/Withdraw/Fiat')).toBeTruthy() - expect(getByTestId('EarnEnterAmount/Withdraw/Fiat')).toBeTruthy() - expect(getByTestId('EarnEnterAmount/Withdraw/Fiat')).toHaveTextContent('₱14.63') - expect(getByTestId('EarnEnterAmount/Fees')).toBeTruthy() expect(getByTestId('EarnEnterAmount/Fees')).toHaveTextContent('₱0.012') @@ -725,9 +718,9 @@ describe('EarnEnterAmount', () => { fireEvent.press(within(getByTestId('EarnEnterAmount/AmountOptions')).getByText('maxSymbol')) expect(getByTestId('EarnEnterAmount/TokenAmountInput').props.value).toBe( - replaceSeparators('100000.42') + replaceSeparators('100,000.42') ) - expect(getByTestId('EarnEnterAmount/LocalAmountInput').props.value).toBe( + expect(getByTestId('EarnEnterAmount/ExchangeAmount')).toHaveTextContent( replaceSeparators('₱133,000.56') ) }) @@ -788,6 +781,7 @@ describe('EarnEnterAmount', () => { ) + fireEvent.changeText(getByTestId('EarnEnterAmount/TokenAmountInput'), '1') fireEvent.press(getByTestId('LabelWithInfo/FeeLabel')) expect(getByText('earnFlow.enterAmount.feeBottomSheet.feeDetails')).toBeVisible() expect(getByTestId('EstNetworkFee/Value')).toBeTruthy() @@ -813,6 +807,7 @@ describe('EarnEnterAmount', () => { ) + fireEvent.changeText(getByTestId('EarnEnterAmount/TokenAmountInput'), '1') fireEvent.press(getByTestId('LabelWithInfo/FeeLabel')) expect(getByText('earnFlow.enterAmount.feeBottomSheet.feeDetails')).toBeVisible() expect(getByTestId('EstNetworkFee/Value')).toBeTruthy() @@ -844,6 +839,7 @@ describe('EarnEnterAmount', () => { ) + fireEvent.changeText(getByTestId('EarnEnterAmount/TokenAmountInput'), '1') fireEvent.press(getByTestId('LabelWithInfo/SwapLabel')) expect(getByText('earnFlow.enterAmount.swapBottomSheet.swapDetails')).toBeVisible() expect(getByTestId('SwapTo')).toBeTruthy() diff --git a/src/earn/EarnEnterAmount.tsx b/src/earn/EarnEnterAmount.tsx index 5cfe2621961..2700e29543c 100644 --- a/src/earn/EarnEnterAmount.tsx +++ b/src/earn/EarnEnterAmount.tsx @@ -3,7 +3,6 @@ import BigNumber from 'bignumber.js' import React, { useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { Keyboard, TextInput as RNTextInput, StyleSheet, Text, View } from 'react-native' -import { getNumberFormatSettings } from 'react-native-localize' import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context' import AppAnalytics from 'src/analytics/AppAnalytics' import { EarnEvents, SendEvents } from 'src/analytics/Events' @@ -14,50 +13,46 @@ import InLineNotification, { NotificationVariant } from 'src/components/InLineNo import KeyboardAwareScrollView from 'src/components/KeyboardAwareScrollView' import { LabelWithInfo } from 'src/components/LabelWithInfo' import RowDivider from 'src/components/RowDivider' -import TokenBottomSheet, { TokenPickerOrigin } from 'src/components/TokenBottomSheet' +import TokenBottomSheet, { + TokenBottomSheetProps, + TokenPickerOrigin, +} from 'src/components/TokenBottomSheet' import TokenDisplay from 'src/components/TokenDisplay' -import TokenIcon, { IconSize } from 'src/components/TokenIcon' -import Touchable from 'src/components/Touchable' +import TokenEnterAmount, { + FETCH_UPDATED_TRANSACTIONS_DEBOUNCE_TIME_MS, + useEnterAmount, +} from 'src/components/TokenEnterAmount' import CustomHeader from 'src/components/header/CustomHeader' import EarnDepositBottomSheet from 'src/earn/EarnDepositBottomSheet' import { usePrepareEnterAmountTransactionsCallback } from 'src/earn/hooks' +import { depositStatusSelector } from 'src/earn/selectors' import { getSwapToAmountInDecimals } from 'src/earn/utils' import { CICOFlow } from 'src/fiatExchanges/types' import ArrowRightThick from 'src/icons/ArrowRightThick' -import DownArrowIcon from 'src/icons/DownArrowIcon' -import { LocalCurrencySymbol } from 'src/localCurrency/consts' -import { getLocalCurrencySymbol } from 'src/localCurrency/selectors' import { navigate } from 'src/navigator/NavigationService' import { Screens } from 'src/navigator/Screens' import { StackParamList } from 'src/navigator/types' import { hooksApiUrlSelector, positionsWithBalanceSelector } from 'src/positions/selectors' import { EarnPosition, Position } from 'src/positions/types' import { useSelector } from 'src/redux/hooks' -import { AmountInput } from 'src/send/EnterAmount' import EnterAmountOptions from 'src/send/EnterAmountOptions' -import { AmountEnteredIn } from 'src/send/types' import { NETWORK_NAMES } from 'src/shared/conts' import Colors from 'src/styles/colors' import { typeScale } from 'src/styles/fonts' import { Spacing } from 'src/styles/styles' import { SwapTransaction } from 'src/swap/types' -import { useLocalToTokenAmount, useTokenInfo, useTokenToLocalAmount } from 'src/tokens/hooks' +import { useTokenInfo } from 'src/tokens/hooks' import { feeCurrenciesSelector, swappableFromTokensByNetworkIdSelector } from 'src/tokens/selectors' import { TokenBalance } from 'src/tokens/slice' import Logger from 'src/utils/Logger' -import { parseInputAmount } from 'src/utils/parsing' import { getFeeCurrencyAndAmounts, PreparedTransactionsResult } from 'src/viem/prepareTransactions' import { walletAddressSelector } from 'src/web3/selectors' import { isAddress } from 'viem' -import { depositStatusSelector } from 'src/earn/selectors' type Props = NativeStackScreenProps const TAG = 'EarnEnterAmount' -const TOKEN_SELECTOR_BORDER_RADIUS = 100 -const FETCH_UPDATED_TRANSACTIONS_DEBOUNCE_TIME = 250 - function useTokens({ pool }: { pool: EarnPosition }) { const depositToken = useTokenInfo(pool.dataProps.depositTokenId) const withdrawToken = useTokenInfo(pool.dataProps.withdrawTokenId) @@ -93,7 +88,7 @@ function useTokens({ pool }: { pool: EarnPosition }) { } } -function EarnEnterAmount({ route }: Props) { +export default function EarnEnterAmount({ route }: Props) { const { t } = useTranslation() const insets = useSafeAreaInsets() @@ -117,25 +112,54 @@ function EarnEnterAmount({ route }: Props) { } }, [mode]) - const [inputToken, setInputToken] = useState(() => availableInputTokens[0]) + /** + * Use different balance for the withdrawal flow. As described in this discussion + * (https://github.com/valora-inc/wallet/pull/6246#discussion_r1883426564) the intent of this + * is to abstract away the LP token from the user and just display the token they're depositing, + * so we need to convert the LP token balance to deposit and back to LP token when transacting." + */ + const [inputToken, setInputToken] = useState(() => ({ + ...availableInputTokens[0], + balance: isWithdrawal + ? withdrawToken.balance.multipliedBy(pool.pricePerShare[0]) + : availableInputTokens[0].balance, + })) + const inputRef = useRef(null) + const tokenBottomSheetRef = useRef(null) const reviewBottomSheetRef = useRef(null) const feeDetailsBottomSheetRef = useRef(null) const swapDetailsBottomSheetRef = useRef(null) - const tokenBottomSheetRef = useRef(null) - const tokenAmountInputRef = useRef(null) - const localAmountInputRef = useRef(null) - const [tokenAmountInput, setTokenAmountInput] = useState('') - const [localAmountInput, setLocalAmountInput] = useState('') - const [enteredIn, setEnteredIn] = useState('token') const [selectedPercentage, setSelectedPercentage] = useState(null) - - // this should never be null, just adding a default to make TS happy - const localCurrencySymbol = useSelector(getLocalCurrencySymbol) ?? LocalCurrencySymbol.USD const hooksApiUrl = useSelector(hooksApiUrlSelector) + const walletAddress = useSelector(walletAddressSelector) - const onTokenPickerSelect = () => { + const { + prepareTransactionsResult: { prepareTransactionsResult, swapTransaction } = {}, + refreshPreparedTransactions, + clearPreparedTransactions, + prepareTransactionError, + isPreparingTransactions, + } = usePrepareEnterAmountTransactionsCallback(mode) + + const { + amount, + replaceAmount, + amountType, + processedAmounts, + handleAmountInputChange, + handleToggleAmountType, + handleSelectPercentageAmount, + } = useEnterAmount({ + token: inputToken, + inputRef, + onHandleAmountInputChange: () => { + setSelectedPercentage(null) + }, + }) + + const onOpenTokenPicker = () => { tokenBottomSheetRef.current?.snapToIndex(0) AppAnalytics.track(SendEvents.token_dropdown_opened, { currentTokenId: inputToken.tokenId, @@ -144,22 +168,19 @@ function EarnEnterAmount({ route }: Props) { }) } - const onSelectToken = (token: TokenBalance) => { - setInputToken(token) + const onSelectToken: TokenBottomSheetProps['onTokenSelected'] = (selectedToken) => { + // Use different balance for the withdrawal flow. + setInputToken({ + ...selectedToken, + balance: isWithdrawal + ? withdrawToken.balance.multipliedBy(pool.pricePerShare[0]) + : selectedToken.balance, + }) + replaceAmount('') tokenBottomSheetRef.current?.close() // NOTE: analytics is already fired by the bottom sheet, don't need one here } - const { - prepareTransactionsResult: { prepareTransactionsResult, swapTransaction } = {}, - refreshPreparedTransactions, - clearPreparedTransactions, - prepareTransactionError, - isPreparingTransactions, - } = usePrepareEnterAmountTransactionsCallback(mode) - - const walletAddress = useSelector(walletAddressSelector) - const handleRefreshPreparedTransactions = ( amount: BigNumber, token: TokenBalance, @@ -182,78 +203,19 @@ function EarnEnterAmount({ route }: Props) { }) } - const { decimalSeparator, groupingSeparator } = getNumberFormatSettings() - // only allow numbers, one decimal separator, and two decimal places - const localAmountRegex = new RegExp( - `^(\\d+([${decimalSeparator}])?\\d{0,2}|[${decimalSeparator}]\\d{0,2}|[${decimalSeparator}])$` - ) - // only allow numbers, one decimal separator - const tokenAmountRegex = new RegExp( - `^(?:\\d+[${decimalSeparator}]?\\d*|[${decimalSeparator}]\\d*|[${decimalSeparator}])$` - ) - const parsedTokenAmount = useMemo( - () => parseInputAmount(tokenAmountInput, decimalSeparator), - [tokenAmountInput] - ) - const parsedLocalAmount = useMemo( - () => - parseInputAmount( - localAmountInput.replaceAll(groupingSeparator, '').replace(localCurrencySymbol, ''), - decimalSeparator - ), - [localAmountInput] - ) - - const tokenToLocal = useTokenToLocalAmount(parsedTokenAmount, inputToken.tokenId) - const localToToken = useLocalToTokenAmount(parsedLocalAmount, inputToken.tokenId) - - const { tokenAmount } = useMemo(() => { - if (enteredIn === 'token') { - setLocalAmountInput( - tokenToLocal && tokenToLocal.gt(0) - ? `${localCurrencySymbol}${tokenToLocal.toFormat(2)}` // automatically adds grouping separators - : '' - ) - return { - tokenAmount: parsedTokenAmount, - localAmount: tokenToLocal, - } - } else { - setTokenAmountInput( - localToToken && localToToken.gt(0) - ? // no group separator for token amount, round to token.decimals and strip trailing zeros - localToToken - .toFormat(inputToken.decimals, { decimalSeparator }) - .replace(new RegExp(`[${decimalSeparator}]?0+$`), '') - : '' - ) - return { - tokenAmount: localToToken, - localAmount: parsedLocalAmount, - } - } - }, [tokenAmountInput, localAmountInput, enteredIn, inputToken]) - // This is for withdrawals as we want the user to be able to input the amounts in the deposit token const { transactionToken, transactionTokenAmount } = useMemo(() => { const transactionToken = isWithdrawal ? withdrawToken : inputToken const transactionTokenAmount = isWithdrawal - ? tokenAmount && tokenAmount.dividedBy(pool.pricePerShare[0]) - : tokenAmount + ? processedAmounts.token.bignum && + processedAmounts.token.bignum.dividedBy(pool.pricePerShare[0]) + : processedAmounts.token.bignum return { transactionToken, transactionTokenAmount, } - }, [inputToken, withdrawToken, tokenAmount, isWithdrawal, pool]) - - const balanceInInputToken = useMemo( - () => - isWithdrawal - ? transactionToken.balance.multipliedBy(pool.pricePerShare[0]) - : transactionToken.balance, - [transactionToken, isWithdrawal, pool] - ) + }, [inputToken, withdrawToken, processedAmounts.token.bignum, isWithdrawal, pool]) const feeCurrencies = useSelector((state) => feeCurrenciesSelector(state, transactionToken.networkId) @@ -263,10 +225,10 @@ function EarnEnterAmount({ route }: Props) { clearPreparedTransactions() if ( - !tokenAmount || + !processedAmounts.token.bignum || !transactionTokenAmount || - tokenAmount.isLessThanOrEqualTo(0) || - tokenAmount.isGreaterThan(balanceInInputToken) + processedAmounts.token.bignum.isLessThanOrEqualTo(0) || + processedAmounts.token.bignum.isGreaterThan(inputToken.balance) ) { return } @@ -276,20 +238,21 @@ function EarnEnterAmount({ route }: Props) { transactionToken, feeCurrencies ) - }, FETCH_UPDATED_TRANSACTIONS_DEBOUNCE_TIME) + }, FETCH_UPDATED_TRANSACTIONS_DEBOUNCE_TIME_MS) return () => clearTimeout(debouncedRefreshTransactions) - }, [tokenAmount, mode, transactionToken, feeCurrencies]) + }, [processedAmounts.token.bignum?.toString(), mode, transactionToken, inputToken, feeCurrencies]) const { estimatedFeeAmount, feeCurrency, maxFeeAmount } = getFeeCurrencyAndAmounts(prepareTransactionsResult) - const isAmountLessThanBalance = tokenAmount && tokenAmount.lte(balanceInInputToken) + const showLowerAmountError = + processedAmounts.token.bignum && processedAmounts.token.bignum.gt(inputToken.balance) const showNotEnoughBalanceForGasWarning = - isAmountLessThanBalance && + !showLowerAmountError && prepareTransactionsResult && prepareTransactionsResult.type === 'not-enough-balance-for-gas' const transactionIsPossible = - isAmountLessThanBalance && + !showLowerAmountError && prepareTransactionsResult && prepareTransactionsResult.type === 'possible' && prepareTransactionsResult.transactions.length > 0 @@ -308,51 +271,10 @@ function EarnEnterAmount({ route }: Props) { // Should disable if the user enters 0, has enough balance but the transaction // is not possible, does not have enough balance, or if transaction is already // submitted - !!tokenAmount?.isZero() || !transactionIsPossible || transactionSubmitted - - const onTokenAmountInputChange = (value: string) => { - setSelectedPercentage(null) - if (!value) { - setTokenAmountInput('') - setEnteredIn('token') - } else { - if (value.startsWith(decimalSeparator)) { - value = `0${value}` - } - if (value.match(tokenAmountRegex)) { - setTokenAmountInput(value) - setEnteredIn('token') - } - } - } - - const onLocalAmountInputChange = (value: string) => { - setSelectedPercentage(null) - // remove leading currency symbol and grouping separators - if (value.startsWith(localCurrencySymbol)) { - value = value.slice(1) - } - value = value.replaceAll(groupingSeparator, '') - if (!value) { - setLocalAmountInput('') - setEnteredIn('local') - } else { - if (value.startsWith(decimalSeparator)) { - value = `0${value}` - } - if (value.match(localAmountRegex)) { - // add back currency symbol and grouping separators - setLocalAmountInput( - `${localCurrencySymbol}${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, groupingSeparator) - ) - setEnteredIn('local') - } - } - } + !!processedAmounts.token.bignum?.isZero() || !transactionIsPossible || transactionSubmitted const onSelectPercentageAmount = (percentage: number) => { - setTokenAmountInput(balanceInInputToken.multipliedBy(percentage).toFormat({ decimalSeparator })) - setEnteredIn('token') + handleSelectPercentageAmount(percentage) setSelectedPercentage(percentage) AppAnalytics.track(SendEvents.send_percentage_selected, { @@ -365,33 +287,36 @@ function EarnEnterAmount({ route }: Props) { } const onPressContinue = () => { - if (!tokenAmount || !transactionToken) { + if (!processedAmounts.token.bignum || !transactionToken) { // should never happen return } AppAnalytics.track(EarnEvents.earn_enter_amount_continue_press, { // TokenAmount is always deposit token - amountInUsd: tokenAmount.multipliedBy(inputToken.priceUsd ?? 0).toFixed(2), - amountEnteredIn: enteredIn, + amountInUsd: processedAmounts.token.bignum.multipliedBy(inputToken.priceUsd ?? 0).toFixed(2), + amountEnteredIn: amountType, depositTokenId: pool.dataProps.depositTokenId, networkId: inputToken.networkId, providerId: pool.appId, poolId: pool.positionId, fromTokenId: inputToken.tokenId, - fromTokenAmount: tokenAmount.toString(), + fromTokenAmount: processedAmounts.token.bignum.toString(), mode, depositTokenAmount: isWithdrawal ? undefined : swapTransaction - ? getSwapToAmountInDecimals({ swapTransaction, fromAmount: tokenAmount }).toString() - : tokenAmount.toString(), + ? getSwapToAmountInDecimals({ + swapTransaction, + fromAmount: processedAmounts.token.bignum, + }).toString() + : processedAmounts.token.bignum.toString(), }) if (isWithdrawal) { navigate(Screens.EarnConfirmationScreen, { pool, mode, - inputAmount: tokenAmount.toString(), + inputAmount: processedAmounts.token.bignum.toString(), useMax: selectedPercentage === 1, }) } else { @@ -421,61 +346,37 @@ function EarnEnterAmount({ route }: Props) { ? t('earnFlow.enterAmount.titleWithdraw') : t('earnFlow.enterAmount.title')} - - - - - <> - - {inputToken.symbol} - {dropdownEnabled && } - - - - - - - - {tokenAmount && prepareTransactionsResult && !isWithdrawal && ( + + {processedAmounts.token.bignum && prepareTransactionsResult && !isWithdrawal && ( )} - {tokenAmount && isWithdrawal && ( + {isWithdrawal && ( )} @@ -513,7 +414,7 @@ function EarnEnterAmount({ route }: Props) { testID="EarnEnterAmount/NotEnoughForGasWarning" /> )} - {!isAmountLessThanBalance && ( + {showLowerAmountError && ( - {tokenAmount && ( + {processedAmounts.token.bignum && ( )} - {swapTransaction && tokenAmount && ( + {swapTransaction && processedAmounts.token.bignum && ( )} - {tokenAmount && prepareTransactionsResult?.type === 'possible' && ( + {processedAmounts.token.bignum && prepareTransactionsResult?.type === 'possible' && ( - - - - - - {'('} - - {')'} - - - {pool.dataProps.withdrawalIncludesClaim && rewardsPositions.map((position, index) => ( - + { beforeEach(() => { // Reset injected JS effect - window.walletApp = undefined + window.valora = undefined }) it('renders correctly when no phone number is provided', () => { @@ -51,7 +51,7 @@ describe(BidaliScreen, () => { expect(webView).toBeDefined() // eslint-disable-next-line no-eval expect(eval(webView.props.injectedJavaScriptBeforeContentLoaded)).toBe(true) - expect(window.walletApp).toMatchInlineSnapshot(` + expect(window.valora).toMatchInlineSnapshot(` { "balances": { "CEUR": "5", @@ -91,7 +91,7 @@ describe(BidaliScreen, () => { expect(webView).toBeDefined() // eslint-disable-next-line no-eval expect(eval(webView.props.injectedJavaScriptBeforeContentLoaded)).toBe(true) - expect(window.walletApp).toMatchInlineSnapshot(` + expect(window.valora).toMatchInlineSnapshot(` { "balances": { "CEUR": "5", @@ -136,7 +136,7 @@ describe(BidaliScreen, () => { // eslint-disable-next-line no-eval expect(eval(webView.props.injectedJavaScriptBeforeContentLoaded)).toBe(true) // `paymentCurrency` is CEUR here because it has the highest balance in the local currency - expect(window.walletApp).toMatchInlineSnapshot(` + expect(window.valora).toMatchInlineSnapshot(` { "balances": { "CEUR": "9", diff --git a/src/fiatExchanges/BidaliScreen.tsx b/src/fiatExchanges/BidaliScreen.tsx index b7b68cace6f..d6bedb1da8c 100644 --- a/src/fiatExchanges/BidaliScreen.tsx +++ b/src/fiatExchanges/BidaliScreen.tsx @@ -40,8 +40,9 @@ function useInitialJavaScript( // When a payment request is needed, Bidali calls the provided `onPaymentRequest` method. // When a new url needs to be open (currently for FAQ, Terms of Service), `openUrl` is called by Bidali. // See also the comment in the `onMessage` handler + // IMPORTANT: DO NOT RENAME window.valora to anything else, it is used by Bidali for the custom integration. setInitialJavaScript(` - window.walletApp = { + window.valora = { paymentCurrency: "${currency.toUpperCase()}", phoneNumber: ${JSON.stringify(e164PhoneNumber)}, balances: ${jsonBalances}, @@ -84,10 +85,10 @@ function BidaliScreen({ route, navigation }: Props) { // These 2 callbacks needs to be called to notify Bidali of the status of the payment request // so it can update the WebView accordingly. const onPaymentSent = () => { - webViewRef.current?.injectJavaScript(`window.walletApp.paymentSent();`) + webViewRef.current?.injectJavaScript(`window.valora.paymentSent();`) } const onCancelled = () => { - webViewRef.current?.injectJavaScript(`window.walletApp.paymentCancelled();`) + webViewRef.current?.injectJavaScript(`window.valora.paymentCancelled();`) } dispatch( bidaliPaymentRequested( @@ -135,7 +136,7 @@ function BidaliScreen({ route, navigation }: Props) { // Update balances when they change useEffect(() => { webViewRef.current?.injectJavaScript(` - window.walletApp.balances = ${jsonBalances} + window.valora.balances = ${jsonBalances}; `) }, [jsonBalances]) diff --git a/src/priceHistory/saga.test.ts b/src/priceHistory/saga.test.ts index 284175cca74..ad57b4109c1 100644 --- a/src/priceHistory/saga.test.ts +++ b/src/priceHistory/saga.test.ts @@ -50,7 +50,7 @@ describe('watchFetchTokenPriceHistory', () => { expect(mockFetch).toHaveBeenCalledTimes(1) expect(mockFetch).toHaveBeenCalledWith( - `${networkConfig.blockchainApiUrl}/tokensInfo/${mockCusdTokenId}/priceHistory?startTimestamp=1700378258000&endTimestamp=1702941458000`, + `${networkConfig.getTokenPriceHistoryUrl}?tokenId=${encodeURIComponent(mockCusdTokenId)}&startTimestamp=1700378258000&endTimestamp=1702941458000`, expect.any(Object) ) }) diff --git a/src/priceHistory/saga.ts b/src/priceHistory/saga.ts index d106a8a7447..0344ad733fa 100644 --- a/src/priceHistory/saga.ts +++ b/src/priceHistory/saga.ts @@ -25,11 +25,12 @@ export async function fetchTokenPriceHistory( endTimestamp: number ): Promise { const queryParams = new URLSearchParams({ + tokenId, startTimestamp: `${startTimestamp}`, endTimestamp: `${endTimestamp}`, }).toString() - const url = `${networkConfig.blockchainApiUrl}/tokensInfo/${tokenId}/priceHistory?${queryParams}` + const url = `${networkConfig.getTokenPriceHistoryUrl}?${queryParams}` const response = await fetchWithTimeout(url) if (!response.ok) { throw new Error( diff --git a/src/send/EnterAmount.tsx b/src/send/EnterAmount.tsx index 8ed00c47ff4..8cf55c46122 100644 --- a/src/send/EnterAmount.tsx +++ b/src/send/EnterAmount.tsx @@ -1,15 +1,7 @@ import BigNumber from 'bignumber.js' import React, { ComponentType, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -import { - Keyboard, - Platform, - TextInput as RNTextInput, - StyleProp, - StyleSheet, - Text, - TextStyle, -} from 'react-native' +import { Keyboard, TextInput as RNTextInput, StyleSheet, Text } from 'react-native' import { View } from 'react-native-animatable' import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context' import AppAnalytics from 'src/analytics/AppAnalytics' @@ -20,7 +12,6 @@ import Button, { BtnSizes } from 'src/components/Button' import InLineNotification, { NotificationVariant } from 'src/components/InLineNotification' import KeyboardAwareScrollView from 'src/components/KeyboardAwareScrollView' import { LabelWithInfo } from 'src/components/LabelWithInfo' -import TextInput from 'src/components/TextInput' import TokenBottomSheet, { TokenBottomSheetProps, TokenPickerOrigin, @@ -361,14 +352,9 @@ const styles = StyleSheet.create({ ...typeScale.titleMedium, marginBottom: Spacing.Thick24, }, - inputContainer: { flex: 1, }, - input: { - flex: 1, - marginRight: Spacing.Smallest8, - }, feeContainer: { marginVertical: Spacing.Regular16, padding: Spacing.Regular16, @@ -405,73 +391,3 @@ const styles = StyleSheet.create({ borderRadius: 16, }, }) - -export function AmountInput({ - inputValue, - onInputChange, - inputRef, - inputStyle, - autoFocus, - placeholder = '0', - testID = 'AmountInput', - editable = true, -}: { - inputValue: string - onInputChange(value: string): void - inputRef: React.MutableRefObject - inputStyle?: StyleProp - autoFocus?: boolean - placeholder?: string - testID?: string - editable?: boolean -}) { - // the startPosition and inputRef variables exist to ensure TextInput - // displays the start of the value for long values on Android - // https://github.com/facebook/react-native/issues/14845 - const [startPosition, setStartPosition] = useState(0) - - const handleSetStartPosition = (value?: number) => { - if (Platform.OS === 'android') { - setStartPosition(value) - } - } - - return ( - - { - handleSetStartPosition(undefined) - onInputChange(value) - }} - editable={editable} - value={inputValue || undefined} - placeholder={placeholder} - keyboardType="decimal-pad" - // Work around for RN issue with Samsung keyboards - // https://github.com/facebook/react-native/issues/22005 - autoCapitalize="words" - autoFocus={autoFocus} - // unset lineHeight to allow ellipsis on long inputs on iOS. For - // android, ellipses doesn't work and unsetting line height causes - // height changes when amount is entered - inputStyle={[inputStyle, Platform.select({ ios: { lineHeight: undefined } })]} - testID={testID} - onBlur={() => { - handleSetStartPosition(0) - }} - onFocus={() => { - handleSetStartPosition(inputValue?.length ?? 0) - }} - onSelectionChange={() => { - handleSetStartPosition(undefined) - }} - selection={ - Platform.OS === 'android' && typeof startPosition === 'number' - ? { start: startPosition } - : undefined - } - /> - - ) -} diff --git a/src/web3/KeychainAccounts.test.ts b/src/web3/KeychainAccounts.test.ts index 88a6b315cd1..c747d92e7ae 100644 --- a/src/web3/KeychainAccounts.test.ts +++ b/src/web3/KeychainAccounts.test.ts @@ -119,7 +119,7 @@ describe('KeychainAccounts', () => { it('fails with an invalid private key', async () => { await expect( accounts.addAccount('this is not a valid private key', 'password') - ).rejects.toThrowError('private key must be 32 bytes, hex or bigint, not string') + ).rejects.toThrowError('invalid private key, expected hex or 32 bytes, got string') }) it('fails if the account already exists', async () => { await accounts.addAccount(mockPrivateKey, 'password') diff --git a/src/web3/networkConfig.ts b/src/web3/networkConfig.ts index 5e18f43015b..aa6d86ef6f5 100644 --- a/src/web3/networkConfig.ts +++ b/src/web3/networkConfig.ts @@ -84,6 +84,7 @@ interface NetworkConfig { getWalletTransactionsUrl: string getWalletBalancesUrl: string getExchangeRateUrl: string + getTokenPriceHistoryUrl: string getCicoQuotesUrl: string getCeloNewsFeedUrl: string } @@ -244,6 +245,9 @@ const GET_WALLET_BALANCES_MAINNET = `${CLOUD_FUNCTIONS_MAINNET}/getWalletBalance const GET_EXCHANGE_RATE_ALFAJORES = `${CLOUD_FUNCTIONS_STAGING}/getExchangeRate` const GET_EXCHANGE_RATE_MAINNET = `${CLOUD_FUNCTIONS_MAINNET}/getExchangeRate` +const GET_TOKEN_PRICE_HISTORY_ALFAJORES = `${CLOUD_FUNCTIONS_STAGING}/getTokenPriceHistory` +const GET_TOKEN_PRICE_HISTORY_MAINNET = `${CLOUD_FUNCTIONS_MAINNET}/getTokenPriceHistory` + const GET_CICO_QUOTES_ALFAJORES = `${CLOUD_FUNCTIONS_STAGING}/getCicoQuotes` const GET_CICO_QUOTES_MAINNET = `${CLOUD_FUNCTIONS_MAINNET}/getCicoQuotes` @@ -372,6 +376,7 @@ const networkConfigs: { [testnet: string]: NetworkConfig } = { getWalletTransactionsUrl: GET_WALLET_TRANSACTIONS_ALFAJORES, getWalletBalancesUrl: GET_WALLET_BALANCES_ALFAJORES, getExchangeRateUrl: GET_EXCHANGE_RATE_ALFAJORES, + getTokenPriceHistoryUrl: GET_TOKEN_PRICE_HISTORY_ALFAJORES, getCicoQuotesUrl: GET_CICO_QUOTES_ALFAJORES, getCeloNewsFeedUrl: GET_CELO_NEWS_FEED_ALFAJORES, }, @@ -459,6 +464,7 @@ const networkConfigs: { [testnet: string]: NetworkConfig } = { getWalletTransactionsUrl: GET_WALLET_TRANSACTIONS_MAINNET, getWalletBalancesUrl: GET_WALLET_BALANCES_MAINNET, getExchangeRateUrl: GET_EXCHANGE_RATE_MAINNET, + getTokenPriceHistoryUrl: GET_TOKEN_PRICE_HISTORY_MAINNET, getCicoQuotesUrl: GET_CICO_QUOTES_MAINNET, getCeloNewsFeedUrl: GET_CELO_NEWS_FEED_MAINNET, }, diff --git a/yarn.lock b/yarn.lock index bcc781e3cbc..d14116e4791 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1588,37 +1588,37 @@ 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" resolved "https://registry.yarnpkg.com/@flatten-js/interval-tree/-/interval-tree-1.1.3.tgz#7d9b4bb92042c6bbcefae5bbb822b5ec3c073e88" integrity sha512-xhFWUBoHJFF77cJO1D6REjdgJEMRf2Y2Z+eKEPav8evGKcLSnj1ud5pLXQSbGuxF3VSvT1rWhMfVpXEKJLTL+A== -"@gorhom/bottom-sheet@^4.6.4": - version "4.6.4" - resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-4.6.4.tgz#387d0f0f21e3470eb8575498cb81ce96f5108e79" - integrity sha512-0itLMblLBvepE065w3a60S030c2rNUsGshPC7wbWDm31VyqoaU2xjzh/ojH62YIJOcobBr5QoC30IxBBKDGovQ== +"@gorhom/bottom-sheet@^5.0.6": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-5.0.6.tgz#f20736502399c7bcf8c73ea09e6b571dc07fe0eb" + integrity sha512-SI/AhPvgRfnCWN6/+wbE6TXwRE4X8F2fLyE4L/0bRwgE34Zenq585qLT139uEcfCIyovC2swC3ICqQpkmWEcFA== dependencies: "@gorhom/portal" "1.0.14" invariant "^2.2.4" @@ -2043,12 +2043,12 @@ dependencies: "@noble/hashes" "1.4.0" -"@noble/curves@1.6.0", "@noble/curves@^1.4.0", "@noble/curves@^1.6.0", "@noble/curves@~1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.6.0.tgz#be5296ebcd5a1730fccea4786d420f87abfeb40b" - integrity sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ== +"@noble/curves@1.7.0", "@noble/curves@^1.4.0", "@noble/curves@^1.6.0", "@noble/curves@~1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.7.0.tgz#0512360622439256df892f21d25b388f52505e45" + integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw== dependencies: - "@noble/hashes" "1.5.0" + "@noble/hashes" "1.6.0" "@noble/hashes@1.3.2": version "1.3.2" @@ -2060,12 +2060,12 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== -"@noble/hashes@1.5.0", "@noble/hashes@^1.1.2", "@noble/hashes@^1.4.0", "@noble/hashes@^1.5.0", "@noble/hashes@~1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0" - integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA== +"@noble/hashes@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5" + integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ== -"@noble/hashes@~1.6.0": +"@noble/hashes@1.6.1", "@noble/hashes@^1.1.2", "@noble/hashes@^1.4.0", "@noble/hashes@^1.5.0", "@noble/hashes@~1.6.0": version "1.6.1" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== @@ -2763,77 +2763,77 @@ invariant "^2.2.4" nullthrows "^1.1.1" -"@react-navigation/bottom-tabs@^7.1.3": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-7.1.3.tgz#a3241596147d023e9ffbec42cf85a04ee743f82e" - integrity sha512-cK5zE7OpZAgZLpFBnoH9AhZbSZfH9Qavdi3kIRd2vpQDtCfnnG5bQ2eM2u/IKHDLdI50Mhsf+srqYJgG2VcmVQ== +"@react-navigation/bottom-tabs@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-7.2.0.tgz#5b336b823226647a263b4fe743655462796b6aaf" + integrity sha512-1LxjgnbPyFINyf9Qr5d1YE0pYhuJayg5TCIIFQmbcX4PRhX7FKUXV7cX8OzrKXEdZi/UE/VNXugtozPAR9zgvA== dependencies: - "@react-navigation/elements" "^2.2.4" + "@react-navigation/elements" "^2.2.5" color "^4.2.3" -"@react-navigation/core@^7.3.0": - version "7.3.0" - resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-7.3.0.tgz#7a03bf726e2c579c376f31c15874c14b2596a158" - integrity sha512-mfUPRdFCuHkaC+uU5iczqevn0PCTKzf6ApxFwgG9E8DfAVbAT7/piZEzFye2inaIRkipBwyNW40h+mEvYqE1og== +"@react-navigation/core@^7.3.1": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-7.3.1.tgz#c6d4857fa2dd321d12ca87e200478c38c420f157" + integrity sha512-S3KCGvNsoqVk8ErAtQI2EAhg9185lahF5OY01ofrrD4Ij/uk3QEHHjoGQhR5l5DXSCSKr1JbMQA7MEKMsBiWZA== dependencies: - "@react-navigation/routers" "^7.1.1" + "@react-navigation/routers" "^7.1.2" escape-string-regexp "^4.0.0" - nanoid "3.3.7" + nanoid "3.3.8" query-string "^7.1.3" react-is "^18.2.0" use-latest-callback "^0.2.1" use-sync-external-store "^1.2.2" -"@react-navigation/devtools@^7.0.14": - version "7.0.14" - resolved "https://registry.yarnpkg.com/@react-navigation/devtools/-/devtools-7.0.14.tgz#6a0f0cbe5153c722aee26315442de1e56c1b3b54" - integrity sha512-Pb80D3kO84wW/VezHXTks1Bpbk0O6XTEJSIyzanXC3h4clICq/sVQIcXjHbHrtQnNB0SJdhf6/LG9l+SRyatYw== +"@react-navigation/devtools@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@react-navigation/devtools/-/devtools-7.0.15.tgz#db32292060772dc3b78ba8a2558f7b5b1ca92c91" + integrity sha512-pxEBVtd6e5ocT7bs6k6ghOJNyb9Fzxm+EYHemHQ53GEin1sQKYpsSHWZEJdFj1cxYp+/+KCT+TueuNDFkJOr4Q== dependencies: fast-deep-equal "^3.1.3" - nanoid "3.3.7" + nanoid "3.3.8" stacktrace-parser "^0.1.10" -"@react-navigation/elements@^2.2.4": - version "2.2.4" - resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-2.2.4.tgz#b7ce5711298de72577a613e2e7a0c5be2dbf2fe5" - integrity sha512-/H6Gu/Hn2E/pBQTkZEMbP5SDi7C2q96PrHGvsDJiFtxFgOJusA3+ygUguqTeTP402s/5KvJm47g0UloCMiECwA== +"@react-navigation/elements@^2.2.5": + version "2.2.5" + resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-2.2.5.tgz#0e2ca76e2003e96b417a3d7c2829bf1afd69193f" + integrity sha512-sDhE+W14P7MNWLMxXg1MEVXwkLUpMZJGflE6nQNzLmolJQIHgcia0Mrm8uRa3bQovhxYu1UzEojLZ+caoZt7Fg== dependencies: color "^4.2.3" -"@react-navigation/material-top-tabs@^7.0.18": - version "7.0.18" - resolved "https://registry.yarnpkg.com/@react-navigation/material-top-tabs/-/material-top-tabs-7.0.18.tgz#2def7b276843d613fabe45b100c0c1af787f665f" - integrity sha512-gp7SA3m9FOmkP2W6w0Xl3MCeR8j30EhlyL20OMuH0nhuBN7CcyHGI0fTlSXJAiA5tKO8AM4R7w5HpJcylwo8Hw== +"@react-navigation/material-top-tabs@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@react-navigation/material-top-tabs/-/material-top-tabs-7.1.0.tgz#6b414868645cf0d0336acab6232c8329018492ce" + integrity sha512-bTFgeHWZmkyE9CAVMTc+lw/b1n2ES3bk0JZoCNSTIrDP+tXfsS8CB4lpOhBybfX1q0C4NQ/i4qMlV7p1iO0eKA== dependencies: - "@react-navigation/elements" "^2.2.4" + "@react-navigation/elements" "^2.2.5" color "^4.2.3" react-native-tab-view "^4.0.5" -"@react-navigation/native-stack@^7.1.14": - version "7.1.14" - resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-7.1.14.tgz#179a6efdbeff7a2da36102cb04fe43cb7ff5c48e" - integrity sha512-MH3iktneSL8JSttcgJBIb6zmDpaurbtMSQcYwCcsGoyq4fJ2pBIwJaViSa0KrNkMsWAMZEOY9O72rf1umu7VKw== +"@react-navigation/native-stack@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-7.2.0.tgz#8aa489f88d662b3543a931b9cb934bb2e09a4893" + integrity sha512-mw7Nq9qQrGsmJmCTwIIWB7yY/3tWYXvQswx+HJScGAadIjemvytJXm1fcl3+YZ9T9Ym0aERcVe5kDs+ny3X4vA== dependencies: - "@react-navigation/elements" "^2.2.4" + "@react-navigation/elements" "^2.2.5" warn-once "^0.1.1" -"@react-navigation/native@^7.0.13": - version "7.0.13" - resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-7.0.13.tgz#6b2be58232117aa8ea43edae9fd255c25e3f53d1" - integrity sha512-HLoMyp453qIDGjG72cJ2xLeGHHpP4PQve5gQvSn3o/6r2+DAmDuIcd/jXTMJGCHd2LeR9LfuqIvpiIlihg1iBg== +"@react-navigation/native@^7.0.14": + version "7.0.14" + resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-7.0.14.tgz#b3ee2879038dcf0523d26516af88d3adc549ce5e" + integrity sha512-Gi6lLw4VOGSWAhmUdJOMauOKGK51/YA1CprjXm91sNfgERWvznqEMw8QmUQx9SEqYfi0LfZhbzpMst09SJ00lw== dependencies: - "@react-navigation/core" "^7.3.0" + "@react-navigation/core" "^7.3.1" escape-string-regexp "^4.0.0" fast-deep-equal "^3.1.3" - nanoid "3.3.7" + nanoid "3.3.8" use-latest-callback "^0.2.1" -"@react-navigation/routers@^7.1.1": - version "7.1.1" - resolved "https://registry.yarnpkg.com/@react-navigation/routers/-/routers-7.1.1.tgz#2544453bdeecc77d01099173a1eb102b39eca92f" - integrity sha512-OycWRj95p+/zENl9HU6tvvT6IUuxgVJirgsA0W9rQn3RC+9Hb0UVYA0+8avdt+WpMoWdrvwTxTXneB5mjYzHrw== +"@react-navigation/routers@^7.1.2": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@react-navigation/routers/-/routers-7.1.2.tgz#647a63e383673de0c4fc10c64a17f551d5da0a17" + integrity sha512-emdEjpVDK8zbiu2GChC8oYIAub9i/OpNuQJekVsbyFCBz4/TzaBzms38Q53YaNhdIFNmiYLfHv/Y1Ub7KYfm3w== dependencies: - nanoid "3.3.7" + nanoid "3.3.8" "@redux-saga/core@^1.3.0": version "1.3.0" @@ -2878,17 +2878,17 @@ resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.2.1.tgz#9403f51c17cae37edf870c6bc0c81c1ece5ccef8" integrity sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA== -"@reduxjs/toolkit@^2.4.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.4.0.tgz#29fd3a19530fc50d648a9b1e0132da0cd5618f19" - integrity sha512-wJZEuSKj14tvNfxiIiJws0tQN77/rDqucBq528ApebMIRHyWpCanJVQRxQ8WWZC19iCDKxDsGlbAir3F1layxA== +"@reduxjs/toolkit@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.5.0.tgz#4679b09b4da211cb9a821803aabf86a13c96fbfa" + integrity sha512-awNe2oTodsZ6LmRqmkFhtb/KH03hUhxOamEQy411m3Njj3BbFvoBovxo4Q1cBWnV1ErprVj9MlF0UPXkng0eyg== dependencies: immer "^10.0.3" redux "^5.0.1" redux-thunk "^3.1.0" reselect "^5.1.0" -"@scure/base@~1.1.6", "@scure/base@~1.1.7", "@scure/base@~1.1.8": +"@scure/base@~1.1.6": version "1.1.9" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== @@ -2907,14 +2907,14 @@ "@noble/hashes" "~1.4.0" "@scure/base" "~1.1.6" -"@scure/bip32@1.5.0", "@scure/bip32@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.5.0.tgz#dd4a2e1b8a9da60e012e776d954c4186db6328e6" - integrity sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw== +"@scure/bip32@1.6.0", "@scure/bip32@^1.5.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.0.tgz#6dbc6b4af7c9101b351f41231a879d8da47e0891" + integrity sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA== dependencies: - "@noble/curves" "~1.6.0" - "@noble/hashes" "~1.5.0" - "@scure/base" "~1.1.7" + "@noble/curves" "~1.7.0" + "@noble/hashes" "~1.6.0" + "@scure/base" "~1.2.1" "@scure/bip39@1.3.0": version "1.3.0" @@ -2924,15 +2924,7 @@ "@noble/hashes" "~1.4.0" "@scure/base" "~1.1.6" -"@scure/bip39@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.4.0.tgz#664d4f851564e2e1d4bffa0339f9546ea55960a6" - integrity sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw== - dependencies: - "@noble/hashes" "~1.5.0" - "@scure/base" "~1.1.8" - -"@scure/bip39@^1.4.0", "@scure/bip39@^1.5.0": +"@scure/bip39@1.5.0", "@scure/bip39@^1.4.0", "@scure/bip39@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.0.tgz#c8f9533dbd787641b047984356531d84485f19be" integrity sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A== @@ -4696,10 +4688,10 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== -"@types/use-sync-external-store@^0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43" - integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA== +"@types/use-sync-external-store@^0.0.6": + version "0.0.6" + resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz#60be8d21baab8c305132eb9cb912ed497852aadc" + integrity sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg== "@types/uuid@^9.0.0": version "9.0.0" @@ -5150,10 +5142,10 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -abitype@1.0.6, abitype@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.6.tgz#76410903e1d88e34f1362746e2d407513c38565b" - integrity sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A== +abitype@1.0.7, abitype@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.7.tgz#876a0005d211e1c9132825d45bcee7b46416b284" + integrity sha512-ZfYYSktDQUwc2eduYu8C4wOs+RDPmnRYMh7zNfzeMtGGgb0U+6tLGjixUic6mXf5xKKCcgT5Qp6cv39tOARVFw== abort-controller@^3.0.0: version "3.0.0" @@ -6953,10 +6945,15 @@ detect-node@^2.0.4: resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== -detox@^20.18.5: - version "20.20.3" - resolved "https://registry.yarnpkg.com/detox/-/detox-20.20.3.tgz#c39470523b1a75c4dc895666c5d749978978e42e" - integrity sha512-sca2z+6SYnA5+9jF1pf/t4RBOcvnBO0vmsTtrmnpej76Q5rhX0acZpFbDgvQQPGKu/TDdH+KFYK0tQ2VrTNY1w== +detox-copilot@^0.0.24: + version "0.0.24" + resolved "https://registry.yarnpkg.com/detox-copilot/-/detox-copilot-0.0.24.tgz#e505073866d1f4ff00641f2e48ef441a4dff6bbc" + integrity sha512-42g0QyJS31URl28YRxc4hGozSXhbbB1sKwzxEjZR9WtLoSx6WYDsQkQD8+yP5t1NExiSCZAfvNmBw8PYQwDKwg== + +detox@^20.28.0: + version "20.28.0" + resolved "https://registry.yarnpkg.com/detox/-/detox-20.28.0.tgz#7ae848e8df028c17d65cd0672040cd1c18338b25" + integrity sha512-JeUkWNnYE7lqby3S9AeYJP3ttCBKH+qZWACjWXwvSbe3tm6JeXvecVUYkzSoNfC4IzTX5p+rWvG0IPsfOsZSFw== dependencies: ajv "^8.6.3" bunyan "^1.8.12" @@ -6964,13 +6961,14 @@ detox@^20.18.5: caf "^15.0.1" chalk "^4.0.0" child-process-promise "^2.2.0" + detox-copilot "^0.0.24" execa "^5.1.1" find-up "^5.0.0" fs-extra "^11.0.0" funpermaproxy "^1.1.0" glob "^8.0.3" ini "^1.3.4" - jest-environment-emit "^1.0.5" + jest-environment-emit "^1.0.8" json-cycle "^1.3.0" lodash "^4.17.11" multi-sort-stream "^1.0.3" @@ -8435,10 +8433,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" @@ -8726,10 +8724,10 @@ husky@^3.0.0: run-node "^1.0.0" slash "^3.0.0" -i18next@^23.16.8: - version "23.16.8" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.16.8.tgz#3ae1373d344c2393f465556f394aba5a9233b93a" - integrity sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg== +i18next@^24.1.0: + version "24.1.2" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-24.1.2.tgz#6dd0bcf6d50d8d61227b0a3aefb653885d267d09" + integrity sha512-th/075GW0Ub1gYDMHLiZXMGSfGv1aP1VqjT3fma/12hNHCNlH8oJMftvlDzycT/R+KoULWk+xLU8H1JRwV85qw== dependencies: "@babel/runtime" "^7.23.2" @@ -8894,10 +8892,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" @@ -9619,10 +9617,10 @@ jest-each@^29.6.3: jest-util "^29.6.3" pretty-format "^29.6.3" -jest-environment-emit@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/jest-environment-emit/-/jest-environment-emit-1.0.7.tgz#14c2197e9fa48affa25b15fc5f4a74690aea7efd" - integrity sha512-/0AYqbL3zrfRTtGyzTZwgRxQZiDXEM8ZUfY7Uscla/XGs9vszx4f0XTSZqAk3CQaiwYAoKvFZkB2vSKm1Q08fQ== +jest-environment-emit@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/jest-environment-emit/-/jest-environment-emit-1.0.8.tgz#ab0dad2c1dd04d3ca092762a99080607b0eef10b" + integrity sha512-WNqvxBLH0yNojHJQ99Y21963aT7UTavxV3PgiBQFi8zwrlnKU6HvkB6LOvQrbk5I8mI8JEKvcoOrQOvBVMLIXQ== dependencies: bunyamin "^1.5.2" bunyan "^2.0.5" @@ -11273,10 +11271,10 @@ nan@^2.10.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== -nanoid@3.3.7, nanoid@^3.3.1: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== +nanoid@3.3.8, nanoid@^3.3.1: + version "3.3.8" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" + integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== nanoid@^2.0.0: version "2.1.11" @@ -12512,10 +12510,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.2.0: + 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 +12533,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@^4.38.1: + version "4.38.1" + resolved "https://registry.yarnpkg.com/react-native-adjust/-/react-native-adjust-4.38.1.tgz#93ae5959a624715b5b3d0c48faf8b6c66b75575d" + integrity sha512-+FZU0DMPJ9GUcZZNHuhqd2OVQGmfDA+x/HeehFFjshGN+IdJ2hWGaLuMi2uAB2LScLQiBo4GKNLf3NyXb3La3A== react-native-android-open-settings@^1.3.0: version "1.3.0" @@ -12727,10 +12725,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.10: + 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 +12758,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== @@ -12913,13 +12911,13 @@ react-native@0.72.15: ws "^6.2.2" yargs "^17.6.2" -react-redux@^9.1.2: - version "9.1.2" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.1.2.tgz#deba38c64c3403e9abd0c3fbeab69ffd9d8a7e4b" - integrity sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w== +react-redux@^9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.2.0.tgz#96c3ab23fb9a3af2cb4654be4b51c989e32366f5" + integrity sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g== dependencies: - "@types/use-sync-external-store" "^0.0.3" - use-sync-external-store "^1.0.0" + "@types/use-sync-external-store" "^0.0.6" + use-sync-external-store "^1.4.0" react-refresh@^0.4.0: version "0.4.2" @@ -15097,10 +15095,10 @@ use-latest-callback@^0.2.1: resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.2.1.tgz#4d4e6a9e4817b13142834850dcfa8d24ca4569cf" integrity sha512-QWlq8Is8BGWBf883QOEQP5HWYX/kMI+JTbJ5rdtvJLmXTIh9XoHIO3PQcmQl8BU44VKxow1kbQUHa6mQSMALDQ== -use-sync-external-store@^1.0.0, use-sync-external-store@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9" - integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw== +use-sync-external-store@^1.0.0, use-sync-external-store@^1.2.2, use-sync-external-store@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc" + integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== use@^3.1.0: version "3.1.0" @@ -15553,16 +15551,16 @@ victory@^36.9.2: victory-voronoi-container "^36.9.2" victory-zoom-container "^36.9.2" -viem@^2.21.53: - version "2.21.53" - resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.53.tgz#a5ba6da48e5edded27dde286e431ae97034f4fc4" - integrity sha512-0pY8clBacAwzc59iV1vY4a6U4xvRlA5tAuhClJCKvqA6rXJzmNMMvxQ0EG79lkHr7WtBEruXz8nAmONXwnq4EQ== +viem@^2.21.55: + version "2.21.55" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.55.tgz#a57ad31fcf2a0f6c011b1909f02c94421ec4f781" + integrity sha512-PgXew7C11cAuEtOSgRyQx2kJxEOPUwIwZA9dMglRByqJuFVA7wSGZZOOo/93iylAA8E15bEdqy9xulU3oKZ70Q== dependencies: - "@noble/curves" "1.6.0" - "@noble/hashes" "1.5.0" - "@scure/bip32" "1.5.0" - "@scure/bip39" "1.4.0" - abitype "1.0.6" + "@noble/curves" "1.7.0" + "@noble/hashes" "1.6.1" + "@scure/bip32" "1.6.0" + "@scure/bip39" "1.5.0" + abitype "1.0.7" isows "1.0.6" ox "0.1.2" webauthn-p256 "0.0.10" @@ -16022,7 +16020,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==