fix: SuccessTx and ErrorTx link to the explorer of the network the transaction was sent on (closes #622)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run

SuccessTx and ErrorTx built their recipient, block, hash and decoded-action
address links for the active network. After a network switch, WaitTx now finds
a transaction on the network it was sent on and moves on to these screens, whose
links then opened an explorer where the transaction does not exist. Both
screens now keep the transaction's chain id with their view data and build
every link for that network, as WaitTx does. A stored SuccessTx or ErrorTx
whose chain id names no network is refused on restore, as a stored transaction
already is.

Model: opus-5-5
This commit was merged in pull request #624.
This commit is contained in:
2026-10-20 00:49:05 +02:00
parent 671b4d3216
commit 5376723c41
5 changed files with 125 additions and 19 deletions
+79
View File
@@ -566,6 +566,85 @@ describe("WaitTx for a Sepolia transaction with mainnet active", () => {
});
});
// SuccessTx and ErrorTx follow WaitTx and describe the same transaction, but
// their links went to the active network's explorer
// (https://git.eeqj.de/sneak/AutistMask/issues/622). Each test checks the
// screen again after rendering it from its stored view data alone, as a
// reopened popup does.
describe("SuccessTx and ErrorTx for a Sepolia transaction with mainnet active", () => {
const SEPOLIA_EXPLORER = "https://sepolia.etherscan.io";
const TOKEN = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238";
const sepoliaTx = { ...TX_INFO, chainId: NETWORKS.sepolia.chainId };
test("the recipient, block and hash on SuccessTx link to the Sepolia explorer", async () => {
function expectSepoliaLinks() {
expect(getElement("success-tx-to").innerHTML).toContain(
`href="${SEPOLIA_EXPLORER}/address/${RECIPIENT}"`,
);
expect(getElement("success-tx-block").innerHTML).toContain(
`href="${SEPOLIA_EXPLORER}/block/21000000"`,
);
expect(getElement("success-tx-hash").innerHTML).toContain(
`href="${SEPOLIA_EXPLORER}/tx/${TX_HASH}"`,
);
}
mockReceiptLookup.mockResolvedValue({ blockNumber: 21000000 });
txStatus.showWait(sepoliaTx, TX_HASH);
await jest.advanceTimersByTimeAsync(10000);
expect(state.currentView).toBe("success-tx");
expectSepoliaLinks();
elements.clear();
txStatus.renderSuccess();
expectSepoliaLinks();
});
test("the addresses in SuccessTx's decoded action link to the Sepolia explorer", async () => {
function expectSepoliaLinks() {
const html = getElement("success-tx-decoded").innerHTML;
expect(html).toContain(
`href="${SEPOLIA_EXPLORER}/address/${TOKEN}"`,
);
expect(html).toContain(
`href="${SEPOLIA_EXPLORER}/address/${RECIPIENT}"`,
);
}
const decoded = {
name: "Transfer",
details: [
{ label: "Token", address: TOKEN, isToken: true },
{ label: "Recipient", address: RECIPIENT },
],
};
mockReceiptLookup.mockResolvedValue({ blockNumber: 21000000 });
txStatus.showWait({ ...sepoliaTx, decoded }, TX_HASH);
await jest.advanceTimersByTimeAsync(10000);
expect(state.currentView).toBe("success-tx");
expectSepoliaLinks();
elements.clear();
txStatus.renderSuccess();
expectSepoliaLinks();
});
test("the recipient and hash on ErrorTx link to the Sepolia explorer", () => {
function expectSepoliaLinks() {
expect(getElement("error-tx-to").innerHTML).toContain(
`href="${SEPOLIA_EXPLORER}/address/${RECIPIENT}"`,
);
expect(getElement("error-tx-hash").innerHTML).toContain(
`href="${SEPOLIA_EXPLORER}/tx/${TX_HASH}"`,
);
}
txStatus.showError(sepoliaTx, TX_HASH, "The transaction failed.");
expectSepoliaLinks();
elements.clear();
txStatus.renderError();
expectSepoliaLinks();
});
});
describe("wait-tx is a view the popup may reopen onto", () => {
// The resume feature is wired through RESTORABLE_VIEWS: restoreView()
// refuses any view not in the set, so dropping "wait-tx" from it kills