fix: a transaction history that lands after a network switch is dropped (closes #657)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s

Home, AddressDetail and AddressToken remember which network is active
before they ask Blockscout for the transaction history. Each screen drops
the answer if another network is active on the page or in storage when the
answer lands. AddressDetail and AddressToken also drop an answer that lands
once the screen shows another address. AddressToken also drops an answer
that lands once the screen shows another token.

A dropped answer draws no rows and saves no fraud contracts. A failed
request goes through the same checks. A dropped failure shows no message.
Holding the lock, the save adds new fraud contracts only if the page and
the stored record still name the request's network.

storedNetworkIs() reads the stored network, in src/shared/storedSettings.js.

Model: opus-5-5
This commit was merged in pull request #693.
This commit is contained in:
2026-11-02 23:41:24 +01:00
parent 016acbcda5
commit b5737f915c
6 changed files with 649 additions and 39 deletions
+34 -6
View File
@@ -44,6 +44,7 @@ const {
fetchRecentTransactions,
filterTransactions,
} = require("../../shared/transactions");
const { storedNetworkIs } = require("../../shared/storedSettings");
const { log } = require("../../shared/log");
function findActiveAddr() {
@@ -183,6 +184,7 @@ async function loadHomeTxs(ctx) {
}
if (allAddresses.length === 0) return;
const networkId = state.networkId;
const filters = {
hideSpoofedSymbols: state.hideSpoofedSymbols,
hideLowHolderTokens: state.hideLowHolderTokens,
@@ -202,6 +204,15 @@ async function loadHomeTxs(ctx) {
);
const results = await Promise.all(fetches);
// If the network changed during the lookups, nothing is saved or
// drawn. See src/shared/storedSettings.js.
if (
state.networkId !== networkId ||
!(await storedNetworkIs(networkId))
) {
return;
}
// Merge, deduplicate by hash, filter, sort, take 25
const seen = new Set();
let merged = [];
@@ -215,14 +226,24 @@ async function loadHomeTxs(ctx) {
const filtered = filterTransactions(merged, filters);
// Persist any newly discovered fraud contracts
// Persist any newly discovered fraud contracts, inside the save and
// holding the lock. Nothing is added unless this page and the stored
// record both still name the request's network.
if (filtered.newFraudContracts.length > 0) {
for (const addr of filtered.newFraudContracts) {
if (!state.fraudContracts.includes(addr)) {
state.fraudContracts.push(addr);
let saved = false;
await saveState((stored) => {
if (state.networkId !== networkId) return false;
if (stored.networkId !== networkId) return false;
for (const addr of filtered.newFraudContracts) {
if (!state.fraudContracts.includes(addr)) {
state.fraudContracts.push(addr);
}
}
}
await saveState();
saved = true;
});
// If the network changed while the save waited for the lock,
// nothing is drawn.
if (!saved) return;
}
merged = filtered.transactions;
@@ -234,6 +255,13 @@ async function loadHomeTxs(ctx) {
// src/popup/index.js.
if (ctx.pageClosed.aborted) return;
log.errorf("loadHomeTxs failed:", e.message);
// If the network changed, the failure is not shown.
if (
state.networkId !== networkId ||
!(await storedNetworkIs(networkId))
) {
return;
}
const list = $("home-tx-list");
if (list) {
list.innerHTML =