From 03e3a0d29a5037730ae391559398c519c9959d6c Mon Sep 17 00:00:00 2001 From: thedoublejay Date: Mon, 2 Aug 2021 16:50:37 +0800 Subject: [PATCH 01/10] wait for confirmation --- .../OceanInterface/OceanInterface.test.tsx | 15 +++- .../OceanInterface/OceanInterface.tsx | 81 +++++++++++++++---- .../screens/Balances/screens/SendScreen.tsx | 13 ++- 3 files changed, 91 insertions(+), 18 deletions(-) diff --git a/app/components/OceanInterface/OceanInterface.test.tsx b/app/components/OceanInterface/OceanInterface.test.tsx index cd7b112302..db59cf9f56 100644 --- a/app/components/OceanInterface/OceanInterface.test.tsx +++ b/app/components/OceanInterface/OceanInterface.test.tsx @@ -6,6 +6,7 @@ import { Provider } from "react-redux"; import { SmartBuffer } from 'smart-buffer'; import { RootState } from "../../store"; import { ocean } from "../../store/ocean"; +import { wallet } from "../../store/wallet"; import { OceanInterface } from "./OceanInterface"; jest.mock('../../contexts/WalletContext', () => ({ @@ -21,11 +22,16 @@ describe('oceanInterface', () => { height: 49, transactions: [], err: new Error('An unknown error has occurred') + }, + wallet: { + address: 'bcrt1q6np0fh47ykhznjhrtfvduh73cgjg32yac8t07d', + utxoBalance: '77', + tokens: [] } }; const store = configureStore({ preloadedState: initialState, - reducer: { ocean: ocean.reducer } + reducer: { ocean: ocean.reducer, wallet: wallet.reducer } }) const component = ( @@ -48,11 +54,16 @@ describe('oceanInterface', () => { broadcasted: false, sign: async () => signed }] + }, + wallet: { + address: 'bcrt1q6np0fh47ykhznjhrtfvduh73cgjg32yac8t07d', + utxoBalance: '77', + tokens: [] } }; const store = configureStore({ preloadedState: initialState, - reducer: { ocean: ocean.reducer } + reducer: { ocean: ocean.reducer, wallet: wallet.reducer } }) const component = ( diff --git a/app/components/OceanInterface/OceanInterface.tsx b/app/components/OceanInterface/OceanInterface.tsx index 8a81a07973..11e76c7109 100644 --- a/app/components/OceanInterface/OceanInterface.tsx +++ b/app/components/OceanInterface/OceanInterface.tsx @@ -1,19 +1,23 @@ import { CTransactionSegWit } from '@defichain/jellyfish-transaction/dist' import { WhaleApiClient } from '@defichain/whale-api-client' +import { Transaction } from '@defichain/whale-api-client/dist/api/transactions' import { MaterialIcons } from '@expo/vector-icons' import React, { useCallback, useEffect, useRef, useState } from 'react' import { ActivityIndicator, Animated, Linking, TouchableOpacity, View } from 'react-native' import { useDispatch, useSelector } from 'react-redux' import { Text } from '..' -import { Logging } from '../../api/logging' +import { Logging } from '../../api' import { useWallet } from '../../contexts/WalletContext' import { useWhaleApiClient } from '../../contexts/WhaleContext' +import { fetchTokens } from '../../hooks/wallet/TokensAPI' import { RootState } from '../../store' import { firstTransactionSelector, ocean, OceanTransaction } from '../../store/ocean' import { tailwind } from '../../tailwind' import { translate } from '../../translations' const MAX_AUTO_RETRY = 1 +const MAX_TIMEOUT = 300000 +const TIMEOUT_INTERVAL = 30000 async function gotoExplorer (txid: string): Promise { // TODO(thedoublejay) explorer URL @@ -37,6 +41,30 @@ async function broadcastTransaction (tx: CTransactionSegWit, client: WhaleApiCli } } +async function waitForTxConfirmation (id: string, client: WhaleApiClient): Promise { + let start = 0 + let intervalTimeout = 10000 + // Start initial check after 10 seconds, then check after 30 seconds + return await new Promise((resolve, reject) => { + const interval = setInterval(() => { + intervalTimeout = TIMEOUT_INTERVAL + start += TIMEOUT_INTERVAL + client.transactions.get(id).then((tx) => { + clearInterval(interval) + resolve(tx) + }).catch((e) => { + if (start >= MAX_TIMEOUT) { + Logging.error(e) + if (interval !== undefined) { + clearInterval(interval) + } + reject(e) + } + }) + }, intervalTimeout) + }) +} + /** * @description - Global component to be used for async calls, network errors etc. This component is positioned above the bottom tab. * Need to get the height of bottom tab via `useBottomTabBarHeight()` hook to be called on screen. @@ -50,6 +78,7 @@ export function OceanInterface (): JSX.Element | null { const { height, err: e } = useSelector((state: RootState) => state.ocean) const transaction = useSelector((state: RootState) => firstTransactionSelector(state.ocean)) const slideAnim = useRef(new Animated.Value(0)).current + const address = useSelector((state: RootState) => state.wallet.address) // state const [tx, setTx] = useState(transaction) const [err, setError] = useState(e) @@ -72,13 +101,30 @@ export function OceanInterface (): JSX.Element | null { transaction.sign(walletContext.get(0)) .then(async signedTx => { setTxid(signedTx.txId) + setTx({ + ...transaction, + title: translate('screens/OceanInterface', 'Broadcasting...') + }) await broadcastTransaction(signedTx, client) + setTx({ + ...transaction, + title: translate('screens/OceanInterface', 'Waiting for confirmation') + }) + + let title + try { + await waitForTxConfirmation(signedTx.txId, client) + title = 'Transaction Completed' + } catch (e) { + Logging.error(e) + title = 'Sent but not confirmed' + } + setTx({ + ...transaction, + broadcasted: true, + title: translate('screens/OceanInterface', title) + }) }) - .then(() => setTx({ - ...transaction, - broadcasted: true, - title: translate('screens/OceanInterface', 'Transaction Sent') - })) .catch((e: Error) => { let errMsg = e.message if (txid !== undefined) { @@ -86,7 +132,10 @@ export function OceanInterface (): JSX.Element | null { } setError(new Error(errMsg)) }) - .finally(() => dispatch(ocean.actions.popTransaction())) // remove the job as soon as completion + .finally(() => { + dispatch(ocean.actions.popTransaction()) + fetchTokens(client, address, dispatch) + }) // remove the job as soon as completion } }, [transaction, walletContext]) @@ -104,16 +153,19 @@ export function OceanInterface (): JSX.Element | null { { err !== undefined ? - : + : } ) } -function TransactionDetail ({ broadcasted, txid, onClose }: { broadcasted: boolean, txid?: string, onClose: () => void }): JSX.Element { - let title = 'Signing...' - if (txid !== undefined) title = 'Broadcasting...' - if (broadcasted) title = 'Transaction Sent' +function TransactionDetail ({ + broadcasted, + txid, + onClose, + title +}: { broadcasted: boolean, txid?: string, onClose: () => void, title?: string }): JSX.Element { + title = title ?? translate('screens/OceanInterface', 'Signing...') return ( <> { @@ -123,7 +175,7 @@ function TransactionDetail ({ broadcasted, txid, onClose }: { broadcasted: boole {translate('screens/OceanInterface', title)} + >{title} { txid !== undefined && await gotoExplorer(txid)} /> @@ -177,7 +229,8 @@ function TransactionIDButton ({ txid, onPress }: { txid: string, onPress?: () => function TransactionCloseButton (props: { onPress: () => void }): JSX.Element { return ( {translate('screens/OceanInterface', 'OK')} diff --git a/app/screens/AppNavigator/screens/Balances/screens/SendScreen.tsx b/app/screens/AppNavigator/screens/Balances/screens/SendScreen.tsx index 1d6b0eb616..b619377721 100644 --- a/app/screens/AppNavigator/screens/Balances/screens/SendScreen.tsx +++ b/app/screens/AppNavigator/screens/Balances/screens/SendScreen.tsx @@ -12,13 +12,14 @@ import { ScrollView, TouchableOpacity, View } from 'react-native' import NumberFormat from 'react-number-format' import { useDispatch, useSelector } from 'react-redux' import { Dispatch } from 'redux' -import { Logging } from '../../../../../api/logging' +import { Logging } from '../../../../../api' import { Text, TextInput } from '../../../../../components' import { Button } from '../../../../../components/Button' import { getTokenIcon } from '../../../../../components/icons/tokens/_index' import { SectionTitle } from '../../../../../components/SectionTitle' import { useNetworkContext } from '../../../../../contexts/NetworkContext' import { useWhaleApiClient } from '../../../../../contexts/WhaleContext' +import { useTokensAPI } from '../../../../../hooks/wallet/TokensAPI' import { RootState } from '../../../../../store' import { hasTxQueued, ocean } from '../../../../../store/ocean' import { WalletToken } from '../../../../../store/wallet' @@ -73,7 +74,8 @@ type Props = StackScreenProps export function SendScreen ({ route, navigation }: Props): JSX.Element { const { networkName } = useNetworkContext() const client = useWhaleApiClient() - const [token] = useState(route.params.token) + const tokens = useTokensAPI() + const [token, setToken] = useState(route.params.token) const { control, setValue, formState: { isValid }, getValues, trigger } = useForm({ mode: 'onChange' }) const dispatch = useDispatch() const [fee, setFee] = useState(new BigNumber(0.0001)) @@ -84,6 +86,13 @@ export function SendScreen ({ route, navigation }: Props): JSX.Element { client.transactions.estimateFee().then((f) => setFee(new BigNumber(f))).catch((e) => Logging.error(e)) }, []) + useEffect(() => { + const t = tokens.find((t) => t.id === token.id) + if (t !== undefined) { + setToken({ ...t }) + } + }, [tokens]) + async function onSubmit (): Promise { if (hasPendingJob) { return From 593d81c1bc18382027ff4e895194187b0eb6c448 Mon Sep 17 00:00:00 2001 From: thedoublejay Date: Mon, 2 Aug 2021 17:02:55 +0800 Subject: [PATCH 02/10] close ocean interface e2e --- .../balances/convert/convert.spec.ts | 4 +- .../functional/balances/send.spec.ts | 4 +- .../functional/dex/poolswap.spec.ts | 2 +- .../functional/dex/remove_liquidity.spec.ts | 2 +- cypress/support/commands.ts | 76 +++++++++++-------- 5 files changed, 50 insertions(+), 38 deletions(-) diff --git a/cypress/integration/functional/balances/convert/convert.spec.ts b/cypress/integration/functional/balances/convert/convert.spec.ts index cad66e1d01..86714ff619 100644 --- a/cypress/integration/functional/balances/convert/convert.spec.ts +++ b/cypress/integration/functional/balances/convert/convert.spec.ts @@ -38,7 +38,7 @@ context('wallet/balances/convert - bi-direction success case', () => { it('utxosToToken: should be able to convert successfully', function () { cy.intercept('/v0/playground/transactions/send').as('sendRaw') cy.getByTestID('button_continue_convert').click().wait(4000) - cy.getByTestID('oceanInterface_close').click() + cy.closeOceanInterface() // check UI redirected (balances root) // cy.getByTestID('balances_list').should('exist') @@ -84,7 +84,7 @@ context('wallet/balances/convert - bi-direction success case', () => { it('tokenToUtxos: should be able to convert successfully', function () { cy.intercept('/v0/playground/transactions/send').as('sendRaw') cy.getByTestID('button_continue_convert').click().wait(4000) - cy.getByTestID('oceanInterface_close').click() + cy.closeOceanInterface() // check UI redirected (balances root) cy.getByTestID('balances_list').should('exist') diff --git a/cypress/integration/functional/balances/send.spec.ts b/cypress/integration/functional/balances/send.spec.ts index 5499b73050..f1bfa7ffd8 100644 --- a/cypress/integration/functional/balances/send.spec.ts +++ b/cypress/integration/functional/balances/send.spec.ts @@ -63,7 +63,7 @@ context('wallet/send', () => { cy.getByTestID('amount_input').clear().type('1') cy.getByTestID('send_submit_button').should('not.have.attr', 'disabled') cy.getByTestID('send_submit_button').click() - cy.wait(5000).getByTestID('oceanInterface_close').click().wait(5000) + cy.closeOceanInterface() cy.getByTestID('playground_wallet_fetch_balances').click() cy.getByTestID('bottom_tab_balances').click() }) @@ -100,7 +100,7 @@ context('wallet/send', () => { cy.getByTestID('address_input').type(address) cy.getByTestID('max_button').click() cy.getByTestID('send_submit_button').click() - cy.wait(5000).getByTestID('oceanInterface_close').click().wait(5000) + cy.closeOceanInterface() cy.getByTestID('playground_wallet_fetch_balances').click() cy.getByTestID('bottom_tab_balances').click() cy.getByTestID('balances_row_1_amount').should('not.exist') diff --git a/cypress/integration/functional/dex/poolswap.spec.ts b/cypress/integration/functional/dex/poolswap.spec.ts index 14b9f70975..4f0cb31d63 100644 --- a/cypress/integration/functional/dex/poolswap.spec.ts +++ b/cypress/integration/functional/dex/poolswap.spec.ts @@ -66,7 +66,7 @@ context('poolswap with values', () => { cy.getByTestID('text_price_row_minimum_0').then(() => { // const tokenValue = $txt[0].textContent.replace(' LTC', '').replace(',', '') cy.getByTestID('button_submit').click() - cy.wait(5000).getByTestID('oceanInterface_close').click().wait(5000) + cy.closeOceanInterface() cy.getByTestID('playground_wallet_fetch_balances').click() cy.getByTestID('bottom_tab_balances').click() cy.getByTestID('balances_row_4').should('exist') diff --git a/cypress/integration/functional/dex/remove_liquidity.spec.ts b/cypress/integration/functional/dex/remove_liquidity.spec.ts index 294894af27..e7eb0ecf29 100644 --- a/cypress/integration/functional/dex/remove_liquidity.spec.ts +++ b/cypress/integration/functional/dex/remove_liquidity.spec.ts @@ -52,7 +52,7 @@ context('app/dex/removeLiquidity', () => { cy.getByTestID('button_slider_max').click().wait(1000) cy.getByTestID('button_continue_remove_liq').click().wait(4000) cy.getByTestID('bottom_tab_dex').click().wait(1000) - cy.wait(5000).getByTestID('oceanInterface_close').click().wait(5000) + cy.closeOceanInterface() // redirected back to dex root page cy.getByTestID('liquidity_screen_list').should('exist') diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 57afeacbbf..1696a44cc1 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -28,38 +28,44 @@ import '@testing-library/cypress/add-commands' declare global { namespace Cypress { interface Chainable { - /** - * @description Custom command to select DOM element by data-testid attribute. - * @example cy.getByTestID('settings') - */ - getByTestID (value: string): Chainable - - /** - * @description Redirects to main page and creates an empty wallet for testing. Useful on starts of tests. - * @param {boolean} [isRandom=false] default = false, creates randomly generated mnemonic seed or abandon x23 - * @example cy.createEmptyWallet(isRandom?: boolean) - */ - createEmptyWallet (isRandom?: boolean): Chainable - - /** - * @description Sends UTXO DFI to wallet. - * @example cy.sendDFItoWallet().wait(4000) - */ - sendDFItoWallet (): Chainable - - /** - * @description Sends DFI Token to wallet. - * @example cy.sendDFITokentoWallet().wait(4000) - */ - sendDFITokentoWallet (): Chainable - - /** - * @description Sends token to wallet. Accepts a list of token symbols to be sent. - * @param {string[]} tokens to be sent - * @example cy.sendTokenToWallet(['BTC', 'ETH']).wait(4000) - */ - sendTokenToWallet (tokens: string[]): Chainable - } + /** + * @description Custom command to select DOM element by data-testid attribute. + * @example cy.getByTestID('settings') + */ + getByTestID (value: string): Chainable + + /** + * @description Redirects to main page and creates an empty wallet for testing. Useful on starts of tests. + * @param {boolean} [isRandom=false] default = false, creates randomly generated mnemonic seed or abandon x23 + * @example cy.createEmptyWallet(isRandom?: boolean) + */ + createEmptyWallet (isRandom?: boolean): Chainable + + /** + * @description Sends UTXO DFI to wallet. + * @example cy.sendDFItoWallet().wait(4000) + */ + sendDFItoWallet (): Chainable + + /** + * @description Sends DFI Token to wallet. + * @example cy.sendDFITokentoWallet().wait(4000) + */ + sendDFITokentoWallet (): Chainable + + /** + * @description Sends token to wallet. Accepts a list of token symbols to be sent. + * @param {string[]} tokens to be sent + * @example cy.sendTokenToWallet(['BTC', 'ETH']).wait(4000) + */ + sendTokenToWallet (tokens: string[]): Chainable + + /** + * @description Wait for the ocean interface to be confirmed then close the drawer + * @example cy.closeOceanInterface() + */ + closeOceanInterface (): Chainable + } } } @@ -91,3 +97,9 @@ Cypress.Commands.add('sendTokenToWallet', (tokens: string[]) => { }) cy.wait(['@sendTokensToAddress']) }) + +Cypress.Commands.add('closeOceanInterface', () => { + cy.intercept('GET', '**/regtest/transactions/**').as('confirmTransaction') + cy.wait(['@confirmTransaction'], { timeout: 60000 }) + cy.closeOceanInterface() +}) From 0762c600c36daaf9fe1d64a9f5346c5b99fc54fd Mon Sep 17 00:00:00 2001 From: thedoublejay Date: Mon, 2 Aug 2021 17:31:20 +0800 Subject: [PATCH 03/10] close ocean interface e2e --- .../integration/functional/balances/convert/convert.spec.ts | 4 ++-- cypress/support/commands.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cypress/integration/functional/balances/convert/convert.spec.ts b/cypress/integration/functional/balances/convert/convert.spec.ts index 86714ff619..38c083503b 100644 --- a/cypress/integration/functional/balances/convert/convert.spec.ts +++ b/cypress/integration/functional/balances/convert/convert.spec.ts @@ -37,7 +37,7 @@ context('wallet/balances/convert - bi-direction success case', () => { it('utxosToToken: should be able to convert successfully', function () { cy.intercept('/v0/playground/transactions/send').as('sendRaw') - cy.getByTestID('button_continue_convert').click().wait(4000) + cy.getByTestID('button_continue_convert').click() cy.closeOceanInterface() // check UI redirected (balances root) @@ -83,7 +83,7 @@ context('wallet/balances/convert - bi-direction success case', () => { it('tokenToUtxos: should be able to convert successfully', function () { cy.intercept('/v0/playground/transactions/send').as('sendRaw') - cy.getByTestID('button_continue_convert').click().wait(4000) + cy.getByTestID('button_continue_convert').click() cy.closeOceanInterface() // check UI redirected (balances root) diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 1696a44cc1..a37bfcaaf7 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -101,5 +101,5 @@ Cypress.Commands.add('sendTokenToWallet', (tokens: string[]) => { Cypress.Commands.add('closeOceanInterface', () => { cy.intercept('GET', '**/regtest/transactions/**').as('confirmTransaction') cy.wait(['@confirmTransaction'], { timeout: 60000 }) - cy.closeOceanInterface() + cy.getByTestID('oceanInterface_close').click() }) From bb768a364c729487503e0cf0b4daa5a3795f39b3 Mon Sep 17 00:00:00 2001 From: thedoublejay Date: Mon, 2 Aug 2021 17:55:36 +0800 Subject: [PATCH 04/10] close ocean interface e2e --- cypress/support/commands.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index a37bfcaaf7..595c8e56d3 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -99,7 +99,7 @@ Cypress.Commands.add('sendTokenToWallet', (tokens: string[]) => { }) Cypress.Commands.add('closeOceanInterface', () => { - cy.intercept('GET', '**/regtest/transactions/**').as('confirmTransaction') - cy.wait(['@confirmTransaction'], { timeout: 60000 }) + cy.intercept('GET', '**/regtest/transactions/*').as('confirmTransaction') + cy.wait(2000).wait(['@confirmTransaction'], { timeout: 60000 }) cy.getByTestID('oceanInterface_close').click() }) From dadef525a17837e79f98ac1294e4139ca5b6d3ba Mon Sep 17 00:00:00 2001 From: thedoublejay Date: Mon, 2 Aug 2021 22:13:14 +0800 Subject: [PATCH 05/10] close ocean interface e2e --- cypress/support/commands.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 595c8e56d3..8f45e63702 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -99,7 +99,5 @@ Cypress.Commands.add('sendTokenToWallet', (tokens: string[]) => { }) Cypress.Commands.add('closeOceanInterface', () => { - cy.intercept('GET', '**/regtest/transactions/*').as('confirmTransaction') - cy.wait(2000).wait(['@confirmTransaction'], { timeout: 60000 }) - cy.getByTestID('oceanInterface_close').click() + cy.wait(10000).getByTestID('oceanInterface_close').click().wait(2000) }) From 92415da54f27e848978fdae985f22f3dcf16736f Mon Sep 17 00:00:00 2001 From: thedoublejay Date: Tue, 3 Aug 2021 15:12:16 +0800 Subject: [PATCH 06/10] format --- cypress/support/commands.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 92ba1d0188..a2211f6ff3 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -26,8 +26,8 @@ import '@testing-library/cypress/add-commands' // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) declare global { - namespace Cypress { - interface Chainable { + namespace Cypress { + interface Chainable { /** * @description Custom command to select DOM element by data-testid attribute. * @example cy.getByTestID('settings') @@ -66,7 +66,7 @@ declare global { */ closeOceanInterface (): Chainable } - } + } } Cypress.Commands.add('getByTestID', (selector, ...args) => { From bd4caaa427e0090e57ac11b05fc2c7506a0de148 Mon Sep 17 00:00:00 2001 From: thedoublejay Date: Tue, 3 Aug 2021 15:14:29 +0800 Subject: [PATCH 07/10] format --- cypress/support/commands.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index a2211f6ff3..6e315ab66c 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -98,6 +98,10 @@ Cypress.Commands.add('sendTokenToWallet', (tokens: string[]) => { cy.wait(['@sendTokensToAddress']) }) -Cypress.Commands.add('closeOceanInterface', () => { - cy.wait(10000).getByTestID('oceanInterface_close').click().wait(2000) +Cypress.Commands.add('sendTokenToWallet', (tokens: string[]) => { + cy.intercept('/v0/playground/rpc/sendtokenstoaddress').as('sendTokensToAddress') + tokens.forEach((t: string) => { + cy.getByTestID(`playground_token_${t}`).click() + }) + cy.wait(['@sendTokensToAddress']) }) From 55365f11f4a3272a1c8bfd9317ff5c4022da6678 Mon Sep 17 00:00:00 2001 From: thedoublejay Date: Tue, 3 Aug 2021 15:17:07 +0800 Subject: [PATCH 08/10] command --- cypress/support/commands.ts | 76 +++++++++++++++---------------------- 1 file changed, 31 insertions(+), 45 deletions(-) diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 6e315ab66c..da5c25e6fd 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -26,47 +26,41 @@ import '@testing-library/cypress/add-commands' // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) declare global { - namespace Cypress { - interface Chainable { - /** - * @description Custom command to select DOM element by data-testid attribute. - * @example cy.getByTestID('settings') - */ - getByTestID (value: string): Chainable + namespace Cypress { + interface Chainable { + /** + * @description Custom command to select DOM element by data-testid attribute. + * @example cy.getByTestID('settings') + */ + getByTestID (value: string): Chainable - /** - * @description Redirects to main page and creates an empty wallet for testing. Useful on starts of tests. - * @param {boolean} [isRandom=false] default = false, creates randomly generated mnemonic seed or abandon x23 - * @example cy.createEmptyWallet(isRandom?: boolean) - */ - createEmptyWallet (isRandom?: boolean): Chainable + /** + * @description Redirects to main page and creates an empty wallet for testing. Useful on starts of tests. + * @param {boolean} [isRandom=false] default = false, creates randomly generated mnemonic seed or abandon x23 + * @example cy.createEmptyWallet(isRandom?: boolean) + */ + createEmptyWallet (isRandom?: boolean): Chainable - /** - * @description Sends UTXO DFI to wallet. - * @example cy.sendDFItoWallet().wait(4000) - */ - sendDFItoWallet (): Chainable + /** + * @description Sends UTXO DFI to wallet. + * @example cy.sendDFItoWallet().wait(4000) + */ + sendDFItoWallet (): Chainable - /** - * @description Sends DFI Token to wallet. - * @example cy.sendDFITokentoWallet().wait(4000) - */ - sendDFITokentoWallet (): Chainable + /** + * @description Sends DFI Token to wallet. + * @example cy.sendDFITokentoWallet().wait(4000) + */ + sendDFITokentoWallet (): Chainable - /** - * @description Sends token to wallet. Accepts a list of token symbols to be sent. - * @param {string[]} tokens to be sent - * @example cy.sendTokenToWallet(['BTC', 'ETH']).wait(4000) - */ - sendTokenToWallet (tokens: string[]): Chainable - - /** - * @description Wait for the ocean interface to be confirmed then close the drawer - * @example cy.closeOceanInterface() - */ - closeOceanInterface (): Chainable - } - } + /** + * @description Sends token to wallet. Accepts a list of token symbols to be sent. + * @param {string[]} tokens to be sent + * @example cy.sendTokenToWallet(['BTC', 'ETH']).wait(4000) + */ + sendTokenToWallet (tokens: string[]): Chainable + } + } } Cypress.Commands.add('getByTestID', (selector, ...args) => { @@ -97,11 +91,3 @@ Cypress.Commands.add('sendTokenToWallet', (tokens: string[]) => { }) cy.wait(['@sendTokensToAddress']) }) - -Cypress.Commands.add('sendTokenToWallet', (tokens: string[]) => { - cy.intercept('/v0/playground/rpc/sendtokenstoaddress').as('sendTokensToAddress') - tokens.forEach((t: string) => { - cy.getByTestID(`playground_token_${t}`).click() - }) - cy.wait(['@sendTokensToAddress']) -}) From 308db3a800663d0b442d9870d0dd4a81b8a78e6f Mon Sep 17 00:00:00 2001 From: thedoublejay Date: Tue, 3 Aug 2021 15:18:06 +0800 Subject: [PATCH 09/10] command --- cypress/support/commands.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index da5c25e6fd..06544656a3 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -59,6 +59,12 @@ declare global { * @example cy.sendTokenToWallet(['BTC', 'ETH']).wait(4000) */ sendTokenToWallet (tokens: string[]): Chainable + + /** + * @description Wait for the ocean interface to be confirmed then close the drawer + * @example cy.closeOceanInterface() + */ + closeOceanInterface (): Chainable } } } @@ -91,3 +97,7 @@ Cypress.Commands.add('sendTokenToWallet', (tokens: string[]) => { }) cy.wait(['@sendTokensToAddress']) }) + +Cypress.Commands.add('closeOceanInterface', () => { + cy.wait(10000).getByTestID('oceanInterface_close').click().wait(2000) +}) From bd250de6b8f8c1f861d6516ef2206a66dd02c508 Mon Sep 17 00:00:00 2001 From: thedoublejay Date: Tue, 3 Aug 2021 15:47:02 +0800 Subject: [PATCH 10/10] initial timeout --- .../OceanInterface/OceanInterface.tsx | 31 ++++++++++++------- cypress/support/commands.ts | 2 +- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/app/components/OceanInterface/OceanInterface.tsx b/app/components/OceanInterface/OceanInterface.tsx index 11e76c7109..ae018282fa 100644 --- a/app/components/OceanInterface/OceanInterface.tsx +++ b/app/components/OceanInterface/OceanInterface.tsx @@ -9,6 +9,7 @@ import { Text } from '..' import { Logging } from '../../api' import { useWallet } from '../../contexts/WalletContext' import { useWhaleApiClient } from '../../contexts/WhaleContext' +import { getEnvironment } from '../../environment' import { fetchTokens } from '../../hooks/wallet/TokensAPI' import { RootState } from '../../store' import { firstTransactionSelector, ocean, OceanTransaction } from '../../store/ocean' @@ -17,7 +18,7 @@ import { translate } from '../../translations' const MAX_AUTO_RETRY = 1 const MAX_TIMEOUT = 300000 -const TIMEOUT_INTERVAL = 30000 +const INTERVAL_TIME = 5000 async function gotoExplorer (txid: string): Promise { // TODO(thedoublejay) explorer URL @@ -42,26 +43,34 @@ async function broadcastTransaction (tx: CTransactionSegWit, client: WhaleApiCli } async function waitForTxConfirmation (id: string, client: WhaleApiClient): Promise { - let start = 0 - let intervalTimeout = 10000 - // Start initial check after 10 seconds, then check after 30 seconds + const initialTime = getEnvironment().debug ? 5000 : 30000 + let start = initialTime + return await new Promise((resolve, reject) => { - const interval = setInterval(() => { - intervalTimeout = TIMEOUT_INTERVAL - start += TIMEOUT_INTERVAL + let intervalID: number + const callTransaction = (): void => { client.transactions.get(id).then((tx) => { - clearInterval(interval) + if (intervalID !== undefined) { + clearInterval(intervalID) + } resolve(tx) }).catch((e) => { if (start >= MAX_TIMEOUT) { Logging.error(e) - if (interval !== undefined) { - clearInterval(interval) + if (intervalID !== undefined) { + clearInterval(intervalID) } reject(e) } }) - }, intervalTimeout) + } + setTimeout(() => { + callTransaction() + intervalID = setInterval(() => { + start += INTERVAL_TIME + callTransaction() + }, INTERVAL_TIME) + }, initialTime) }) } diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 06544656a3..f1a4423379 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -99,5 +99,5 @@ Cypress.Commands.add('sendTokenToWallet', (tokens: string[]) => { }) Cypress.Commands.add('closeOceanInterface', () => { - cy.wait(10000).getByTestID('oceanInterface_close').click().wait(2000) + cy.wait(5000).getByTestID('oceanInterface_close').click().wait(2000) })