fix: WaitTx and TransactionDetail use the network the transaction was sent on (closes #584)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run

WaitTx asked the active network's node for the receipt, so after a network
switch a transaction sent on the other network was never found and was
reported as timed out. It now asks the node of the network its chain id
names, through reviewedNetworkProvider(), moved from ConfirmTx into the
shared view helpers so both screens use one function. WaitTx and
TransactionDetail build their explorer links for that network too. A stored
wait or transaction whose chain id names no network is refused on restore,
as a stored ConfirmTx transaction already is.

Model: opus-5-5
This commit was merged in pull request #621.
This commit is contained in:
2026-10-19 23:38:10 +02:00
parent 96446f4661
commit e46d894527
11 changed files with 220 additions and 66 deletions
+45 -2
View File
@@ -8,6 +8,10 @@
// tracks. It decodes against the address the explorer reports the transaction
// was sent to.
//
// Its links open the explorer of the network the transaction was sent on,
// whichever network is active
// (https://git.eeqj.de/sneak/AutistMask/issues/584).
//
// The row is the one the real history parser makes from the explorer's answer,
// opened through transactionDetail.show(), which is what a click on the row
// calls. Driven against a minimal DOM stub in the shape
@@ -35,6 +39,7 @@ globalThis.chrome = {
};
const { state } = require("../src/shared/state");
const { NETWORKS } = require("../src/shared/networks");
const { fetchRecentTransactions } = require("../src/shared/transactions");
const transactionDetail = require("../src/popup/views/transactionDetail");
@@ -77,7 +82,11 @@ function mockExplorerAnswer(url) {
};
}
if (url === EXPLORER + "/transactions/" + TX_HASH) {
return { to: { hash: TOKEN }, raw_input: TRANSFER_DATA };
return {
to: { hash: TOKEN },
raw_input: TRANSFER_DATA,
block_number: 100,
};
}
return { items: [] };
}
@@ -154,7 +163,11 @@ beforeEach(() => {
});
test("a token transfer's decoded details name the token contract and the amount at its scale", async () => {
const [row] = await fetchRecentTransactions(HOLDER, EXPLORER, 1);
const [row] = await fetchRecentTransactions(
HOLDER,
EXPLORER,
NETWORKS.mainnet.chainId,
);
expect(row.to).toBe(RECIPIENT);
expect(row.contractAddress).toBe(TOKEN.toLowerCase());
@@ -174,3 +187,33 @@ test("a token transfer's decoded details name the token contract and the amount
'<div class="font-bold">1234.5000 TDOL</div>',
);
});
// Mainnet is active and the row was read from Sepolia's explorer. The stub
// explorer answers whichever network asks, so every link on the screen is
// drawn.
test("with mainnet active, a Sepolia transaction's links open the Sepolia explorer", async () => {
state.networkId = "mainnet";
const [row] = await fetchRecentTransactions(
HOLDER,
EXPLORER,
NETWORKS.sepolia.chainId,
);
transactionDetail.show(row);
for (let i = 0; i < 10; i++) await new Promise((r) => setTimeout(r, 0));
const sepolia = "https://sepolia.etherscan.io";
const links = (id) =>
[...node(id).innerHTML.matchAll(/href="([^"]*)"/g)].map((m) => m[1]);
expect(links("tx-detail-hash")).toEqual([`${sepolia}/tx/${TX_HASH}`]);
expect(links("tx-detail-from")).toEqual([`${sepolia}/address/${HOLDER}`]);
expect(links("tx-detail-to")).toEqual([`${sepolia}/address/${RECIPIENT}`]);
expect(links("tx-detail-token-contract")).toEqual([
`${sepolia}/token/${TOKEN.toLowerCase()}`,
]);
expect(links("tx-detail-block")).toEqual([`${sepolia}/block/100`]);
expect(links("tx-detail-calldata-details")).toEqual([
`${sepolia}/address/${TOKEN}`,
`${sepolia}/address/${RECIPIENT}`,
]);
});