diff --git a/RULES.md b/RULES.md index 6c4e4a8..79c8b13 100644 --- a/RULES.md +++ b/RULES.md @@ -17,8 +17,8 @@ contradicts either, the originals govern. ## External Communication -- [ ] Extension contacts exactly two external services: configured RPC endpoint - and CoinDesk price API +- [ ] Extension contacts exactly three external services: configured RPC + endpoint, CoinDesk price API, and Blockscout block-explorer API - [ ] No analytics, telemetry, or tracking - [ ] No user-specific data sent except to the configured RPC endpoint - [ ] No Infura/Alchemy hard dependency diff --git a/src/popup/views/helpers.js b/src/popup/views/helpers.js index fcaa8c3..e265dcb 100644 --- a/src/popup/views/helpers.js +++ b/src/popup/views/helpers.js @@ -82,7 +82,7 @@ function showFlash(msg, duration = 2000) { function balanceLine(symbol, amount, price, tokenId) { const qty = amount.toFixed(4); - const usd = price ? formatUsd(amount * price) : ""; + const usd = price ? formatUsd(amount * price) || " " : " "; const tokenAttr = tokenId ? ` data-token="${tokenId}"` : ""; const clickClass = tokenId ? " cursor-pointer hover:bg-hover balance-row" @@ -219,6 +219,41 @@ function formatAddressHtml(address, ensName, maxLen, title) { return `
${dot}${escapeHtml(displayAddr)}
`; } +function isoDate(timestamp) { + const d = new Date(timestamp * 1000); + const pad = (n) => String(n).padStart(2, "0"); + return ( + d.getFullYear() + + "-" + + pad(d.getMonth() + 1) + + "-" + + pad(d.getDate()) + + " " + + pad(d.getHours()) + + ":" + + pad(d.getMinutes()) + + ":" + + pad(d.getSeconds()) + ); +} + +function timeAgo(timestamp) { + const seconds = Math.floor(Date.now() / 1000 - timestamp); + if (seconds < 60) return seconds + " seconds ago"; + const minutes = Math.floor(seconds / 60); + if (minutes < 60) + return minutes + " minute" + (minutes !== 1 ? "s" : "") + " ago"; + const hours = Math.floor(minutes / 60); + if (hours < 24) return hours + " hour" + (hours !== 1 ? "s" : "") + " ago"; + const days = Math.floor(hours / 24); + if (days < 30) return days + " day" + (days !== 1 ? "s" : "") + " ago"; + const months = Math.floor(days / 30); + if (months < 12) + return months + " month" + (months !== 1 ? "s" : "") + " ago"; + const years = Math.floor(days / 365); + return years + " year" + (years !== 1 ? "s" : "") + " ago"; +} + module.exports = { $, showError, @@ -233,4 +268,6 @@ module.exports = { addressTitle, formatAddressHtml, truncateMiddle, + isoDate, + timeAgo, }; diff --git a/src/popup/views/home.js b/src/popup/views/home.js index 7fd2262..62b352b 100644 --- a/src/popup/views/home.js +++ b/src/popup/views/home.js @@ -3,6 +3,8 @@ const { showView, showFlash, balanceLinesForAddress, + isoDate, + timeAgo, addressDotHtml, escapeHtml, truncateMiddle, @@ -87,41 +89,6 @@ function renderActiveAddress() { } } -function timeAgo(timestamp) { - const seconds = Math.floor(Date.now() / 1000 - timestamp); - if (seconds < 60) return seconds + " seconds ago"; - const minutes = Math.floor(seconds / 60); - if (minutes < 60) - return minutes + " minute" + (minutes !== 1 ? "s" : "") + " ago"; - const hours = Math.floor(minutes / 60); - if (hours < 24) return hours + " hour" + (hours !== 1 ? "s" : "") + " ago"; - const days = Math.floor(hours / 24); - if (days < 30) return days + " day" + (days !== 1 ? "s" : "") + " ago"; - const months = Math.floor(days / 30); - if (months < 12) - return months + " month" + (months !== 1 ? "s" : "") + " ago"; - const years = Math.floor(days / 365); - return years + " year" + (years !== 1 ? "s" : "") + " ago"; -} - -function isoDate(timestamp) { - const d = new Date(timestamp * 1000); - const pad = (n) => String(n).padStart(2, "0"); - return ( - d.getFullYear() + - "-" + - pad(d.getMonth() + 1) + - "-" + - pad(d.getDate()) + - " " + - pad(d.getHours()) + - ":" + - pad(d.getMinutes()) + - ":" + - pad(d.getSeconds()) - ); -} - let homeTxs = []; function renderHomeTxList(ctx) { diff --git a/src/popup/views/transactionDetail.js b/src/popup/views/transactionDetail.js index 0ec1dc3..8ecbfe3 100644 --- a/src/popup/views/transactionDetail.js +++ b/src/popup/views/transactionDetail.js @@ -8,6 +8,8 @@ const { addressDotHtml, addressTitle, escapeHtml, + isoDate, + timeAgo, } = require("./helpers"); const { state } = require("../../shared/state"); const makeBlockie = require("ethereum-blockies-base64"); @@ -21,41 +23,6 @@ const EXT_ICON = let ctx; -function isoDate(timestamp) { - const d = new Date(timestamp * 1000); - const pad = (n) => String(n).padStart(2, "0"); - return ( - d.getFullYear() + - "-" + - pad(d.getMonth() + 1) + - "-" + - pad(d.getDate()) + - " " + - pad(d.getHours()) + - ":" + - pad(d.getMinutes()) + - ":" + - pad(d.getSeconds()) - ); -} - -function timeAgo(timestamp) { - const seconds = Math.floor(Date.now() / 1000 - timestamp); - if (seconds < 60) return seconds + " seconds ago"; - const minutes = Math.floor(seconds / 60); - if (minutes < 60) - return minutes + " minute" + (minutes !== 1 ? "s" : "") + " ago"; - const hours = Math.floor(minutes / 60); - if (hours < 24) return hours + " hour" + (hours !== 1 ? "s" : "") + " ago"; - const days = Math.floor(hours / 24); - if (days < 30) return days + " day" + (days !== 1 ? "s" : "") + " ago"; - const months = Math.floor(days / 30); - if (months < 12) - return months + " month" + (months !== 1 ? "s" : "") + " ago"; - const years = Math.floor(days / 365); - return years + " year" + (years !== 1 ? "s" : "") + " ago"; -} - function copyableHtml(text, extraClass) { const cls = "underline decoration-dashed cursor-pointer" +