Disable send button after broadcast, show tx link and elapsed timer
Some checks failed
check / check (push) Has been cancelled
Some checks failed
check / check (push) Has been cancelled
Once a transaction is successfully broadcast: disable the send button to prevent double-sends, immediately show an etherscan link for the pending tx, and display a live elapsed-time counter that updates every second until confirmation arrives.
This commit is contained in:
@@ -19,6 +19,7 @@ const { getProvider } = require("../../shared/balances");
|
|||||||
const { isScamAddress } = require("../../shared/scamlist");
|
const { isScamAddress } = require("../../shared/scamlist");
|
||||||
|
|
||||||
let pendingTx = null;
|
let pendingTx = null;
|
||||||
|
let elapsedTimer = null;
|
||||||
|
|
||||||
function show(txInfo) {
|
function show(txInfo) {
|
||||||
pendingTx = txInfo;
|
pendingTx = txInfo;
|
||||||
@@ -172,8 +173,43 @@ function init(ctx) {
|
|||||||
to: pendingTx.to,
|
to: pendingTx.to,
|
||||||
value: parseEther(pendingTx.amount),
|
value: parseEther(pendingTx.amount),
|
||||||
});
|
});
|
||||||
statusEl.textContent = "Sent. Waiting for confirmation...";
|
|
||||||
|
// Disable send button immediately after broadcast
|
||||||
|
const sendBtn = $("btn-confirm-send");
|
||||||
|
sendBtn.disabled = true;
|
||||||
|
sendBtn.classList.add("text-muted");
|
||||||
|
|
||||||
|
// Show etherscan link and elapsed timer
|
||||||
|
const broadcastTime = Date.now();
|
||||||
|
statusEl.innerHTML = "";
|
||||||
|
statusEl.appendChild(
|
||||||
|
document.createTextNode(
|
||||||
|
"Broadcast. Waiting for confirmation... ",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const timerSpan = document.createElement("span");
|
||||||
|
timerSpan.textContent = "(0s)";
|
||||||
|
statusEl.appendChild(timerSpan);
|
||||||
|
statusEl.appendChild(document.createElement("br"));
|
||||||
|
const txLink = document.createElement("a");
|
||||||
|
txLink.href = "https://etherscan.io/tx/" + tx.hash;
|
||||||
|
txLink.target = "_blank";
|
||||||
|
txLink.rel = "noopener";
|
||||||
|
txLink.className = "underline decoration-dashed break-all";
|
||||||
|
txLink.textContent = tx.hash;
|
||||||
|
statusEl.appendChild(document.createTextNode("Tx: "));
|
||||||
|
statusEl.appendChild(txLink);
|
||||||
|
|
||||||
|
if (elapsedTimer) clearInterval(elapsedTimer);
|
||||||
|
elapsedTimer = setInterval(() => {
|
||||||
|
const elapsed = Math.floor((Date.now() - broadcastTime) / 1000);
|
||||||
|
timerSpan.textContent = "(" + elapsed + "s)";
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
const receipt = await tx.wait();
|
const receipt = await tx.wait();
|
||||||
|
clearInterval(elapsedTimer);
|
||||||
|
elapsedTimer = null;
|
||||||
|
|
||||||
statusEl.innerHTML = "";
|
statusEl.innerHTML = "";
|
||||||
statusEl.appendChild(
|
statusEl.appendChild(
|
||||||
document.createTextNode(
|
document.createTextNode(
|
||||||
@@ -189,6 +225,10 @@ function init(ctx) {
|
|||||||
statusEl.appendChild(link);
|
statusEl.appendChild(link);
|
||||||
ctx.doRefreshAndRender();
|
ctx.doRefreshAndRender();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (elapsedTimer) {
|
||||||
|
clearInterval(elapsedTimer);
|
||||||
|
elapsedTimer = null;
|
||||||
|
}
|
||||||
statusEl.textContent = "Failed: " + (e.shortMessage || e.message);
|
statusEl.textContent = "Failed: " + (e.shortMessage || e.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user