diff --git a/.github/workflows/macstadium-e2e.yml b/.github/workflows/macstadium-e2e.yml new file mode 100644 index 00000000000..62aefce7597 --- /dev/null +++ b/.github/workflows/macstadium-e2e.yml @@ -0,0 +1,33 @@ +# This is a basic workflow to help you get started with Actions + +name: CI + +# Controls when the workflow will run +on: + # Triggers the workflow on push or pull request events but only for the "develop" branch + pull_request: + branches: [ "@bruno/macstadium-e2e" ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: self-hosted + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + + - name: Get ENV vars + run: yarn update-env + + - name: Install deps + run: yarn fast + + - name: Run e2e tests in release mode + run: yarn detox:ios:release diff --git a/e2e/deeplinks.spec.js b/e2e/deeplinks.spec.js index 85c37792ef6..b4ed1e6b1e6 100644 --- a/e2e/deeplinks.spec.js +++ b/e2e/deeplinks.spec.js @@ -56,7 +56,7 @@ describe('Deeplinks spec', () => { await Helpers.enableSynchronization(); }); - it('should be able to handle ethereum payments urls for ETH (mainnet)', async () => { + xit('should be able to handle ethereum payments urls for ETH (mainnet)', async () => { const url = 'ethereum:payment-brunobarbieri.eth@1?value=1e15'; await testEthereumDeeplink(url); }); @@ -71,7 +71,7 @@ describe('Deeplinks spec', () => { await testEthereumDeeplink(url); }); - it('should be able to handle ethereum payments urls for DAI (mainnet)', async () => { + xit('should be able to handle ethereum payments urls for DAI (mainnet)', async () => { const url = 'ethereum:0x6b175474e89094c44da98b954eedeac495271d0f@1/transfer?address=brunobarbieri.eth&uint256=1e18'; await testEthereumDeeplink(url); diff --git a/e2e/sendSheetFlow.spec.js b/e2e/sendSheetFlow.spec.js index e810593b924..ecbc68f0565 100644 --- a/e2e/sendSheetFlow.spec.js +++ b/e2e/sendSheetFlow.spec.js @@ -1,7 +1,13 @@ /* eslint-disable no-undef */ /* eslint-disable jest/expect-expect */ +import { exec } from 'child_process'; import * as Helpers from './helpers'; +beforeAll(async () => { + // Connect to hardhat + await exec('yarn hardhat'); +}); + describe('Send Sheet Interaction Flow', () => { it('Should show the welcome screen', async () => { await Helpers.checkIfVisible('welcome-screen'); @@ -52,6 +58,22 @@ describe('Send Sheet Interaction Flow', () => { await Helpers.enableSynchronization(); }); + it('Should send ETH to test wallet"', async () => { + await Helpers.sendETHtoTestWallet(); + }); + + it('Should connect to hardhat', async () => { + await Helpers.swipe('wallet-screen', 'right', 'slow'); + await Helpers.checkIfVisible('profile-screen'); + await Helpers.waitAndTap('settings-button'); + await Helpers.checkIfVisible('settings-modal'); + await Helpers.waitAndTap('developer-section'); + await Helpers.checkIfVisible('developer-settings-modal'); + await Helpers.waitAndTap('hardhat-section'); + await Helpers.checkIfVisible('testnet-toast-Hardhat'); + await Helpers.swipe('profile-screen', 'left', 'slow'); + }); + // Saving for now in case we want to test iCloud back up sheet // it('Should show the backup sheet', async () => { // await Helpers.checkIfVisible('backup-sheet'); @@ -305,6 +327,7 @@ describe('Send Sheet Interaction Flow', () => { afterAll(async () => { // Reset the app state await device.clearKeychain(); + await exec('kill $(lsof -t -i:8545)'); await Helpers.delay(2000); }); }); diff --git a/e2e/swapSheetFlow.spec.js b/e2e/swapSheetFlow.spec.js index 55281d47d1a..002a1771e53 100644 --- a/e2e/swapSheetFlow.spec.js +++ b/e2e/swapSheetFlow.spec.js @@ -1,7 +1,13 @@ /* eslint-disable no-undef */ /* eslint-disable jest/expect-expect */ +import { exec } from 'child_process'; import * as Helpers from './helpers'; +beforeAll(async () => { + // Connect to hardhat + await exec('yarn hardhat'); +}); + describe('Swap Sheet Interaction Flow', () => { it('Should show the welcome screen', async () => { await Helpers.checkIfVisible('welcome-screen'); @@ -42,6 +48,22 @@ describe('Swap Sheet Interaction Flow', () => { await Helpers.enableSynchronization(); }); + it('Should send ETH to test wallet"', async () => { + await Helpers.sendETHtoTestWallet(); + }); + + it('Should connect to hardhat', async () => { + await Helpers.swipe('wallet-screen', 'right', 'slow'); + await Helpers.checkIfVisible('profile-screen'); + await Helpers.waitAndTap('settings-button'); + await Helpers.checkIfVisible('settings-modal'); + await Helpers.waitAndTap('developer-section'); + await Helpers.checkIfVisible('developer-settings-modal'); + await Helpers.waitAndTap('hardhat-section'); + await Helpers.checkIfVisible('testnet-toast-Hardhat'); + await Helpers.swipe('profile-screen', 'left', 'slow'); + }); + it('Should display swap modal on swap-fab press', async () => { await Helpers.checkIfVisible('wallet-screen'); await Helpers.delay(5000); @@ -265,7 +287,7 @@ describe('Swap Sheet Interaction Flow', () => { await Helpers.waitAndTap('exchange-modal-output-selection-button'); await Helpers.typeText('currency-select-search-input', 'ZRX', false); await Helpers.waitAndTap('currency-select-list-exchange-coin-row-ZRX'); - await Helpers.typeText('exchange-modal-input', '0.546', false); + await Helpers.typeText('exchange-modal-input', '500000000000', false); await Helpers.checkForElementByLabel('Insufficient Funds'); }); @@ -405,6 +427,7 @@ describe('Swap Sheet Interaction Flow', () => { afterAll(async () => { // Reset the app state await device.clearKeychain(); + await exec('kill $(lsof -t -i:8545)'); await Helpers.delay(2000); }); }); diff --git a/index.js b/index.js index 6764fea5ae7..ad279722a4a 100644 --- a/index.js +++ b/index.js @@ -14,7 +14,7 @@ PerformanceTracking.logDirectly( PerformanceMetrics.loadJSBundle, Date.now() - StartTime.START_TIME ); -PerformanceTracking.startMeasuring(PerformanceMetrics.loadJSBundle); +PerformanceTracking.startMeasuring(PerformanceMetrics.loadRootAppComponent); PerformanceTracking.startMeasuring(PerformanceMetrics.timeToInteractive); /* diff --git a/src/components/settings-menu/DevNotificationsSection.tsx b/src/components/settings-menu/DevNotificationsSection.tsx index 6e25f747b3e..cafb1f8a1fd 100644 --- a/src/components/settings-menu/DevNotificationsSection.tsx +++ b/src/components/settings-menu/DevNotificationsSection.tsx @@ -196,7 +196,7 @@ const DevNotificationsSection = () => { /> - + {wallet.label || wallet.color} diff --git a/src/components/settings-menu/DevSection.js b/src/components/settings-menu/DevSection.js index 144cb7f5be5..049b67d88ad 100644 --- a/src/components/settings-menu/DevSection.js +++ b/src/components/settings-menu/DevSection.js @@ -4,7 +4,11 @@ import React, { useCallback, useContext } from 'react'; import { Alert, ScrollView } from 'react-native'; // eslint-disable-next-line import/default import codePush from 'react-native-code-push'; -import { HARDHAT_URL_ANDROID, HARDHAT_URL_IOS } from 'react-native-dotenv'; +import { + HARDHAT_URL_ANDROID, + HARDHAT_URL_IOS, + IS_TESTING, +} from 'react-native-dotenv'; import Restart from 'react-native-restart'; import { useDispatch } from 'react-redux'; import { defaultConfig } from '../../config/experimental'; @@ -14,10 +18,17 @@ import { RadioListItem } from '../radio-list'; import UserDevSection from './UserDevSection'; import { Divider } from '@rainbow-me/design-system'; import { deleteAllBackups } from '@rainbow-me/handlers/cloudBackup'; -import { web3SetHttpProvider } from '@rainbow-me/handlers/web3'; +import { + getProviderForNetwork, + web3SetHttpProvider, +} from '@rainbow-me/handlers/web3'; import { RainbowContext } from '@rainbow-me/helpers/RainbowContext'; -import networkTypes from '@rainbow-me/helpers/networkTypes'; -import { useWallets } from '@rainbow-me/hooks'; +import networkTypes, { Network } from '@rainbow-me/helpers/networkTypes'; +import { + useAccountSettings, + useUpdateAssetOnchainBalance, + useWallets, +} from '@rainbow-me/hooks'; import { ImgixImage } from '@rainbow-me/images'; import { wipeKeychain } from '@rainbow-me/model/keychain'; import { clearAllStorages } from '@rainbow-me/model/mmkv'; @@ -27,14 +38,18 @@ import { explorerInit } from '@rainbow-me/redux/explorer'; import { clearImageMetadataCache } from '@rainbow-me/redux/imageMetadata'; import store from '@rainbow-me/redux/store'; import { walletsUpdate } from '@rainbow-me/redux/wallets'; +import { ETH_ADDRESS } from '@rainbow-me/references'; import Routes from '@rainbow-me/routes'; +import { ethereumUtils } from '@rainbow-me/utils'; import logger from 'logger'; const DevSection = () => { const { navigate } = useNavigation(); const { config, setConfig } = useContext(RainbowContext); const { wallets } = useWallets(); + const { accountAddress } = useAccountSettings(); const dispatch = useDispatch(); + const updateAssetOnchainBalanceIfNeeded = useUpdateAssetOnchainBalance(); const onExperimentalKeyChange = useCallback( value => { @@ -61,7 +76,19 @@ const DevSection = () => { } navigate(Routes.PROFILE_SCREEN); dispatch(explorerInit()); - }, [dispatch, navigate]); + + if (IS_TESTING === 'true') { + const provider = await getProviderForNetwork(Network.mainnet); + const ethAsset = ethereumUtils.getAccountAsset(ETH_ADDRESS); + updateAssetOnchainBalanceIfNeeded( + ethAsset, + accountAddress, + Network.mainnet, + provider, + () => {} + ); + } + }, [accountAddress, dispatch, navigate, updateAssetOnchainBalanceIfNeeded]); const syncCodepush = useCallback(async () => { const isUpdate = !!(await codePush.checkForUpdate()); diff --git a/src/hooks/useENSRegistrationCosts.ts b/src/hooks/useENSRegistrationCosts.ts index b54931b0b76..7bb8e63c1ee 100644 --- a/src/hooks/useENSRegistrationCosts.ts +++ b/src/hooks/useENSRegistrationCosts.ts @@ -369,9 +369,10 @@ export default function useENSRegistrationCosts({ useEffect(() => { if ( !isEmpty(useGasGasFeeParamsBySpeed) && - gasFeeParams.gasFeeParamsBySpeed !== useGasGasFeeParamsBySpeed && - gasFeeParams.currentBaseFee !== useGasCurrentBlockParams.baseFeePerGas && - useGasCurrentBlockParams.baseFeePerGas + gasFeeParams?.gasFeeParamsBySpeed !== useGasGasFeeParamsBySpeed && + gasFeeParams?.currentBaseFee !== + useGasCurrentBlockParams?.baseFeePerGas && + useGasCurrentBlockParams?.baseFeePerGas ) { setGasFeeParams({ currentBaseFee: useGasCurrentBlockParams.baseFeePerGas, diff --git a/src/redux/data.ts b/src/redux/data.ts index d221d90dcfc..4da3ecf9224 100644 --- a/src/redux/data.ts +++ b/src/redux/data.ts @@ -885,7 +885,10 @@ const checkForUpdatedNonce = (transactionData: ZerionTransaction[]) => ( if (transactionData.length) { const { accountAddress, network } = getState().settings; const txSortedByDescendingNonce = transactionData - .filter(({ address_from }) => address_from === accountAddress) + .filter( + ({ address_from }) => + address_from?.toLowerCase() === accountAddress.toLowerCase() + ) .sort(({ nonce: n1 }, { nonce: n2 }) => (n2 ?? 0) - (n1 ?? 0)); const [latestTx] = txSortedByDescendingNonce; const { address_from, nonce } = latestTx;