-
Notifications
You must be signed in to change notification settings - Fork 2
chore(react-native): remove unused ActivityDetailSheet component / add missing translation keys #1211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
chore(react-native): remove unused ActivityDetailSheet component / add missing translation keys #1211
Changes from 13 commits
8a9bb69
3fdc20e
80a9f8c
0bbe6dd
60048e1
5d835b5
be68ff0
41a4c76
e0e7e27
8e47d52
3150e94
9f1ba43
eea7e13
e889f5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,7 +28,11 @@ export const sendTokenFlow = async ({ | |
| await page.getByTestId('next').click(); | ||
| await page.getByTestId('confirm').click(); | ||
| // Wait for the transaction to be completed | ||
| const txId = await waitForTransaction({ page, successtext: /Executed|Sealed/, ingoreFlowCharge }); | ||
| const txId = await waitForTransaction({ | ||
| page, | ||
| successtext: /success|Finalized|Executed|Sealed/, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a typo in |
||
| ingoreFlowCharge, | ||
| }); | ||
| return { txId, tokenname, amount, ingoreFlowCharge }; | ||
| }; | ||
|
|
||
|
|
@@ -47,7 +51,11 @@ export const moveTokenFlow = async ({ | |
| await page.getByRole('button', { name: 'Move' }).click(); | ||
|
|
||
| // Wait for the transaction to be completed | ||
| const txId = await waitForTransaction({ page, successtext: /Executed|Sealed/, ingoreFlowCharge }); | ||
| const txId = await waitForTransaction({ | ||
| page, | ||
| successtext: /success|Finalized|Executed|Sealed/, | ||
| ingoreFlowCharge, | ||
| }); | ||
| return { txId, tokenname, amount, ingoreFlowCharge }; | ||
| }; | ||
|
|
||
|
|
@@ -66,7 +74,11 @@ export const moveTokenFlowHomepage = async ({ | |
| await page.getByPlaceholder('0.00').fill(amount); | ||
| await page.getByRole('button', { name: 'Move' }).click(); | ||
| // Wait for the transaction to be completed | ||
| const txId = await waitForTransaction({ page, successtext: /Executed|Sealed/, ingoreFlowCharge }); | ||
| const txId = await waitForTransaction({ | ||
| page, | ||
| successtext: /success|Finalized|Executed|Sealed/, | ||
| ingoreFlowCharge, | ||
| }); | ||
| return { txId, tokenname, amount, ingoreFlowCharge }; | ||
| }; | ||
|
|
||
|
|
@@ -79,7 +91,7 @@ let txList: { txId: string; tokenname: string; amount: string; ingoreFlowCharge: | |
|
|
||
| //Send FLOW token from Flow to Flow | ||
| test('send Cadence transactions', async ({ page, extensionId }) => { | ||
| test.setTimeout(120_000); | ||
| test.setTimeout(600_000); | ||
| await loginToSenderAccount({ page, extensionId }); | ||
|
|
||
| await switchToMainAccount({ | ||
|
|
@@ -126,7 +138,7 @@ test('send Cadence transactions', async ({ page, extensionId }) => { | |
|
|
||
| //Send FLOW token to evm | ||
| test('send Cadence transactions to evm', async ({ page, extensionId }) => { | ||
| test.setTimeout(120_000); | ||
| test.setTimeout(600_000); | ||
| await loginToSenderAccount({ page, extensionId }); | ||
|
|
||
| await switchToMainAccount({ | ||
|
|
@@ -172,7 +184,7 @@ test('send Cadence transactions to evm', async ({ page, extensionId }) => { | |
| }); | ||
|
|
||
| test('send from evm to Flow', async ({ page, extensionId }) => { | ||
| test.setTimeout(120_000); | ||
| test.setTimeout(600_000); | ||
| await loginToSenderAccount({ page, extensionId }); | ||
|
|
||
| await switchToEOAAccount({ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -393,6 +393,25 @@ class TransactionActivity { | |
| ); | ||
| const existingTxList = existingTxStore?.list || []; | ||
| const existingPendingList = await this.getPendingList(network, address); | ||
|
|
||
| // If the in-memory pending list is empty (e.g., service worker was restarted), | ||
| // recover any in-progress items from the cached list so they are not lost while | ||
| // the API has not yet indexed those transactions. | ||
| // This includes PENDING, Executed, and Finalized states — all of which represent | ||
| // transactions that are not yet confirmed by the indexer. Recovering only PENDING | ||
| // items misses the case where updatePending already advanced the status before | ||
| // the SW restarted (common for EVM/Cadence hybrid transactions like withdrawCoa). | ||
| const TERMINAL_STATUSES = new Set(['SEALED', 'EXPIRED', 'ERROR']); | ||
| if (existingPendingList.length === 0 && existingTxList.length > 0) { | ||
| const cachedPendingItems = existingTxList.filter( | ||
| (item) => !TERMINAL_STATUSES.has((item.status ?? '').toUpperCase()) | ||
| ); | ||
| if (cachedPendingItems.length > 0) { | ||
| existingPendingList.push(...cachedPendingItems); | ||
| this.setPendingList(network, address, existingPendingList); | ||
| } | ||
| } | ||
|
|
||
| const txList: TransferItem[] = []; | ||
| data?.transactions?.forEach(async (tx) => { | ||
| const transactionHolder = { | ||
|
|
@@ -428,11 +447,13 @@ class TransactionActivity { | |
| transactionHolder.transferType = tx.transfer_type; | ||
| transactionHolder.additionalMessage = tx.additional_message; | ||
| // see if there's a pending item for this transaction | ||
| // Use case-insensitive comparison to handle API/FCL hash casing differences | ||
| const normalizedTxid = tx.txid.toLowerCase(); | ||
| const pendingItemIndex = existingPendingList.findIndex( | ||
| (item) => | ||
| item.hash.includes(tx.txid) || | ||
| item.cadenceTxId?.includes(tx.txid) || | ||
| item.evmTxIds?.includes(tx.txid) | ||
| item.hash.toLowerCase().includes(normalizedTxid) || | ||
| item.cadenceTxId?.toLowerCase().includes(normalizedTxid) || | ||
| item.evmTxIds?.some((id) => id.toLowerCase().includes(normalizedTxid)) | ||
|
Comment on lines
+454
to
+456
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using |
||
| ); | ||
| if (pendingItemIndex !== -1) { | ||
| // Store the cadence transaction id | ||
|
|
@@ -443,9 +464,9 @@ class TransactionActivity { | |
| // see if there's an existing transaction with cadenceId in the store | ||
| const existingTx = existingTxList.find( | ||
| (item) => | ||
| item.hash.includes(tx.txid) || | ||
| item.cadenceTxId?.includes(tx.txid) || | ||
| item.evmTxIds?.includes(tx.txid) | ||
| item.hash.toLowerCase().includes(normalizedTxid) || | ||
| item.cadenceTxId?.toLowerCase().includes(normalizedTxid) || | ||
| item.evmTxIds?.some((id) => id.toLowerCase().includes(normalizedTxid)) | ||
|
Comment on lines
+467
to
+469
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same issue as above - using |
||
| ); | ||
| if (existingTx && existingTx.cadenceTxId) { | ||
| // Found existing cadence transaction id | ||
|
|
@@ -595,6 +616,28 @@ class TransactionActivity { | |
| return this.getPendingList(network, address); | ||
| }; | ||
|
|
||
| /** | ||
| * Returns Cadence txIds from cached non-terminal transactions that need FCL monitoring | ||
| * re-registered after a service worker restart. Only items with a cadenceTxId and a | ||
| * non-terminal status (i.e., not SEALED/EXPIRED/ERROR) are returned. | ||
| */ | ||
| getRecoverableCadenceTxIds = async (network: string, address: string): Promise<string[]> => { | ||
| const TERMINAL_STATUSES = new Set(['SEALED', 'EXPIRED', 'ERROR']); | ||
| const existingTxStore = await getInvalidData<TransferListStore>( | ||
| transferListKey(network, address, '0', '15') | ||
| ); | ||
| if (!existingTxStore?.list?.length) { | ||
| return []; | ||
| } | ||
| const recoverableIds = new Set<string>(); | ||
| for (const item of existingTxStore.list) { | ||
| if (item.cadenceTxId && !TERMINAL_STATUSES.has((item.status ?? '').toUpperCase())) { | ||
| recoverableIds.add(item.cadenceTxId); | ||
| } | ||
| } | ||
| return Array.from(recoverableIds); | ||
| }; | ||
|
|
||
| getCount = async ( | ||
| network: string, | ||
| address: string, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1157,6 +1157,51 @@ class UserWallet { | |
| } | ||
| }; | ||
|
|
||
| /** | ||
| * Re-registers FCL monitoring for any pending Cadence transactions that were in | ||
| * progress before a service worker restart. This is necessary because FCL | ||
| * onceExecuted/onceSealed promise chains are lost when the SW restarts, leaving | ||
| * items permanently stuck in a non-terminal status (PENDING, Executed, Finalized). | ||
| * | ||
| * Unlike listenTransaction, this does NOT call setPending — the cached entry already | ||
| * exists. It only re-attaches FCL event subscriptions so updatePending can advance | ||
| * the status once on-chain confirmation arrives. | ||
| */ | ||
| resumePendingTransactions = async (): Promise<void> => { | ||
| try { | ||
| const network = await this.getNetwork(); | ||
| const address = await this.getCurrentAddress(); | ||
| if (!network || !address) { | ||
| return; | ||
| } | ||
| const cadenceTxIds = await transactionActivityService.getRecoverableCadenceTxIds( | ||
| network, | ||
| address | ||
| ); | ||
| for (const txId of cadenceTxIds) { | ||
| this.reattachFclMonitoring(network, address, txId).catch(() => {}); | ||
| } | ||
| } catch { | ||
| // Do not throw — SW startup should not fail due to recovery errors | ||
| } | ||
| }; | ||
|
|
||
| private reattachFclMonitoring = async ( | ||
| network: string, | ||
| address: string, | ||
| txId: string | ||
| ): Promise<void> => { | ||
| if (!txId || !txId.match(/^0?x?[0-9a-fA-F]{64}/)) { | ||
| return; | ||
| } | ||
| const fclTx = fcl.tx(txId); | ||
| const txStatusExecuted = await fclTx.onceExecuted(); | ||
| await transactionActivityService.updatePending(network, address, txId, txStatusExecuted); | ||
| const txStatusSealed = await fclTx.onceSealed(); | ||
| await transactionActivityService.updatePending(network, address, txId, txStatusSealed); | ||
| await transactionActivityService.pollTransferList(address, txId, network); | ||
|
Comment on lines
+1209
to
+1213
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If |
||
| }; | ||
|
|
||
| authorizationFunction = async (account) => { | ||
| // authorization function need to return an account | ||
| const address = fcl.withPrefix(await this.getParentAddress()); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a typo in the parameter name
ingoreFlowCharge- it should beignoreFlowCharge. This typo appears to be pre-existing in the codebase, but it's being propagated in the new code.