fix: Settings refuses an endpoint URL whose network changed before it was stored (closes #663)
The RPC and Blockscout "Save" buttons in Settings take the network that Settings was last drawn for. A follow of a switch saved elsewhere sets `state` first. Settings is drawn again only once the follow's write returns. The URL is set in `state` inside the save, holding the lock. The save is refused if the network that Settings showed is no longer active, on the page or in the stored record. The flash message then says that the network changed, and "Saved." is shown only for a stored URL. Before, a popup that followed a switch saved elsewhere could replace the URL before the write and still show "Saved.". It could also store a URL for a network that Settings did not show. Model: opus-5-5
This commit is contained in:
@@ -44,6 +44,12 @@ let ctx;
|
||||
let versionClickCount = 0;
|
||||
let versionClickTimer = null;
|
||||
|
||||
// The network that Settings was last drawn for. A follow of a switch saved
|
||||
// elsewhere sets `state` to the new network first. Settings is drawn again only
|
||||
// once the follow's write returns. So both "Save" buttons take this network,
|
||||
// not the one in `state`.
|
||||
let shownNetwork = null;
|
||||
|
||||
// One row per site origin, however many addresses it appears under, each with
|
||||
// an [x] that hands it to onRemove.
|
||||
function renderSiteList(containerId, origins, onRemove) {
|
||||
@@ -199,6 +205,7 @@ function renderWalletListSettings() {
|
||||
}
|
||||
|
||||
function show() {
|
||||
shownNetwork = currentNetwork();
|
||||
$("settings-rpc").value = state.rpcUrl;
|
||||
$("settings-blockscout").value = state.blockscoutUrl;
|
||||
$("settings-network").value = state.networkId;
|
||||
@@ -306,6 +313,7 @@ function showNewSettings() {
|
||||
state.checkRecipientsOnEtherscan;
|
||||
if (state.currentView === "settings") {
|
||||
markViewRendered("settings");
|
||||
shownNetwork = currentNetwork();
|
||||
$("settings-network").value = state.networkId;
|
||||
$("settings-rpc").value = state.rpcUrl;
|
||||
$("settings-blockscout").value = state.blockscoutUrl;
|
||||
@@ -319,6 +327,28 @@ function showNewSettings() {
|
||||
updateDebugBanner(state.currentView);
|
||||
}
|
||||
|
||||
// Saves `url` as `field` ("rpcUrl" or "blockscoutUrl") of the network
|
||||
// `networkId`, the one that Settings showed when the user tapped "Save". The
|
||||
// URL is set in `state` inside the save, holding the lock. So the page cannot
|
||||
// follow a switch saved elsewhere (followStoredSettings() in
|
||||
// src/popup/index.js) between setting the URL and writing it. If the active
|
||||
// network is no longer `networkId`, on this page or in the stored record,
|
||||
// nothing is saved. The flash message then says that the network changed.
|
||||
async function saveEndpoint(field, url, networkId) {
|
||||
let refused = false;
|
||||
await saveState((stored) => {
|
||||
refused =
|
||||
state.networkId !== networkId || stored.networkId !== networkId;
|
||||
if (refused) return false;
|
||||
state[field] = url;
|
||||
});
|
||||
if (refused) {
|
||||
showFlash("The URL was not saved because the network changed.");
|
||||
} else {
|
||||
showFlash("Saved.");
|
||||
}
|
||||
}
|
||||
|
||||
function init(_ctx) {
|
||||
ctx = _ctx;
|
||||
deleteWallet.init(ctx);
|
||||
@@ -330,6 +360,8 @@ function init(_ctx) {
|
||||
showFlash("Please enter an RPC URL.");
|
||||
return;
|
||||
}
|
||||
// The URL is for the network that Settings shows when "Save" is tapped.
|
||||
const net = shownNetwork;
|
||||
showFlash("Testing endpoint...");
|
||||
try {
|
||||
const resp = await debugFetch(url, {
|
||||
@@ -348,7 +380,6 @@ function init(_ctx) {
|
||||
showFlash("Endpoint returned an error.");
|
||||
return;
|
||||
}
|
||||
const net = currentNetwork();
|
||||
if (json.result !== net.chainId) {
|
||||
showFlash("Wrong network: expected " + net.name + ".");
|
||||
return;
|
||||
@@ -364,9 +395,7 @@ function init(_ctx) {
|
||||
showFlash("Could not reach endpoint.");
|
||||
return;
|
||||
}
|
||||
state.rpcUrl = url;
|
||||
await saveState();
|
||||
showFlash("Saved.");
|
||||
await saveEndpoint("rpcUrl", url, net.id);
|
||||
});
|
||||
|
||||
$("btn-save-blockscout").addEventListener("click", async () => {
|
||||
@@ -375,6 +404,7 @@ function init(_ctx) {
|
||||
showFlash("Please enter a Blockscout API URL.");
|
||||
return;
|
||||
}
|
||||
const net = shownNetwork;
|
||||
showFlash("Testing endpoint...");
|
||||
try {
|
||||
const resp = await debugFetch(url + "/stats");
|
||||
@@ -389,9 +419,7 @@ function init(_ctx) {
|
||||
showFlash("Could not reach endpoint.");
|
||||
return;
|
||||
}
|
||||
state.blockscoutUrl = url;
|
||||
await saveState();
|
||||
showFlash("Saved.");
|
||||
await saveEndpoint("blockscoutUrl", url, net.id);
|
||||
});
|
||||
|
||||
// Each change is made inside the save, holding the lock. So
|
||||
|
||||
Reference in New Issue
Block a user