landing: compact GOA alt display and all-account bank fallback
Wire goa-amount.js into bank/exchange/merchant intros, deploy it with the landings, and deepen the in-container bank stats fallback to scan all accounts (skip only exchange) when the host timer is down.
This commit is contained in:
parent
746d7a41af
commit
48f77139c5
8 changed files with 363 additions and 39 deletions
163
configs/shared/goa-amount.js
Normal file
163
configs/shared/goa-amount.js
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/* Compact GOA / CUR:amount display using currency alt_unit_names.
|
||||
* Large values → "1.23 Mega-GOA" (title = full GOA:n) so landing tiles fit.
|
||||
*/
|
||||
(function (global) {
|
||||
"use strict";
|
||||
|
||||
var DEFAULT_ALT = {
|
||||
"24": "Yotta-GOA",
|
||||
"21": "Zetta-GOA",
|
||||
"18": "Exa-GOA",
|
||||
"15": "Peta-GOA",
|
||||
"12": "Tera-GOA",
|
||||
"9": "Giga-GOA",
|
||||
"6": "Mega-GOA",
|
||||
"3": "Kilo-GOA",
|
||||
"0": "GOA",
|
||||
"-1": "Deci-GOA",
|
||||
"-2": "Centi-GOA",
|
||||
"-3": "Milli-GOA",
|
||||
"-6": "Micro-GOA",
|
||||
"-7": "Deci-Micro-GOA",
|
||||
"-8": "Atomic-GOA"
|
||||
};
|
||||
|
||||
var THRESHOLD = 1000;
|
||||
|
||||
function parseAmount(s) {
|
||||
if (s == null || s === "") return { cur: "GOA", val: 0 };
|
||||
if (typeof s === "number") return { cur: "GOA", val: s };
|
||||
var t = String(s).trim();
|
||||
var i = t.indexOf(":");
|
||||
if (i < 0) return { cur: "GOA", val: parseFloat(t) || 0 };
|
||||
return {
|
||||
cur: t.slice(0, i) || "GOA",
|
||||
val: parseFloat(t.slice(i + 1)) || 0
|
||||
};
|
||||
}
|
||||
|
||||
function fmtCoeff(v) {
|
||||
if (!isFinite(v)) return "?";
|
||||
var a = Math.abs(v);
|
||||
if (Math.abs(a - Math.round(a)) < 1e-9) return String(Math.round(v));
|
||||
var s = v.toFixed(4).replace(/\.?0+$/, "");
|
||||
return s;
|
||||
}
|
||||
|
||||
function baseStr(cur, val) {
|
||||
if (!isFinite(val)) return String(cur) + ":?";
|
||||
if (Math.abs(val - Math.round(val)) < 1e-9) return cur + ":" + Math.round(val);
|
||||
return cur + ":" + String(val).replace(/(\.\d*?[1-9])0+$/, "$1").replace(/\.0+$/, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string|number} amount
|
||||
* @param {object} [altMap]
|
||||
* @returns {{ display: string, title: string, raw: string, usedAlt: boolean }}
|
||||
*/
|
||||
function format(amount, altMap) {
|
||||
if (amount == null || amount === "") {
|
||||
return { display: "—", title: "", raw: "", usedAlt: false };
|
||||
}
|
||||
// Prefer server-provided alt if caller passes object {amount, amount_alt}
|
||||
if (typeof amount === "object" && amount) {
|
||||
if (amount.amount_alt) {
|
||||
var rawO = amount.amount || amount.amount_full || String(amount.amount_alt);
|
||||
return {
|
||||
display: String(amount.amount_alt),
|
||||
title: amount.amount_full || rawO,
|
||||
raw: String(rawO),
|
||||
usedAlt: true
|
||||
};
|
||||
}
|
||||
amount = amount.amount || amount.amount_full || "";
|
||||
}
|
||||
|
||||
var alt = altMap || global.__GOA_ALT_UNITS || DEFAULT_ALT;
|
||||
var p = parseAmount(amount);
|
||||
var raw = baseStr(p.cur, p.val);
|
||||
if (p.val === 0) {
|
||||
var zname = (alt && alt["0"]) || p.cur;
|
||||
return { display: "0 " + zname, title: raw, raw: raw, usedAlt: false };
|
||||
}
|
||||
if (Math.abs(p.val) < THRESHOLD) {
|
||||
return { display: raw, title: raw, raw: raw, usedAlt: false };
|
||||
}
|
||||
|
||||
var scales = [];
|
||||
Object.keys(alt || {}).forEach(function (k) {
|
||||
var n = parseInt(k, 10);
|
||||
if (!isNaN(n)) scales.push({ sc: n, name: String(alt[k]) });
|
||||
});
|
||||
scales.sort(function (a, b) { return b.sc - a.sc; });
|
||||
|
||||
var abs = Math.abs(p.val);
|
||||
var chosen = null;
|
||||
for (var i = 0; i < scales.length; i++) {
|
||||
var unit = Math.pow(10, scales[i].sc);
|
||||
if (!(unit > 0)) continue;
|
||||
var coeff = abs / unit;
|
||||
if (coeff >= 1) {
|
||||
chosen = {
|
||||
sc: scales[i].sc,
|
||||
name: scales[i].name,
|
||||
coeff: p.val >= 0 ? coeff : -coeff
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!chosen || chosen.sc === 0) {
|
||||
return { display: raw, title: raw, raw: raw, usedAlt: false };
|
||||
}
|
||||
var short = fmtCoeff(chosen.coeff) + " " + chosen.name;
|
||||
return {
|
||||
display: short,
|
||||
title: short + " (" + raw + ")",
|
||||
raw: raw,
|
||||
usedAlt: true
|
||||
};
|
||||
}
|
||||
|
||||
function setText(el, amount, altMap) {
|
||||
if (!el) return;
|
||||
var f = format(amount, altMap);
|
||||
el.textContent = f.display;
|
||||
if (f.title && f.title !== f.display) el.setAttribute("title", f.title);
|
||||
else el.removeAttribute("title");
|
||||
}
|
||||
|
||||
function setById(id, amount, altMap) {
|
||||
setText(document.getElementById(id), amount, altMap);
|
||||
}
|
||||
|
||||
/** Prefer amount_alt from stats row, else format amount. */
|
||||
function pick(rowOrAmount, altMap) {
|
||||
if (rowOrAmount && typeof rowOrAmount === "object") {
|
||||
if (rowOrAmount.amount_alt) {
|
||||
return format({
|
||||
amount: rowOrAmount.amount,
|
||||
amount_alt: rowOrAmount.amount_alt,
|
||||
amount_full: rowOrAmount.amount_full
|
||||
}, altMap);
|
||||
}
|
||||
return format(rowOrAmount.amount || rowOrAmount.total_amount, altMap);
|
||||
}
|
||||
return format(rowOrAmount, altMap);
|
||||
}
|
||||
|
||||
function rememberAlt(stats) {
|
||||
if (stats && stats.alt_unit_names && typeof stats.alt_unit_names === "object") {
|
||||
global.__GOA_ALT_UNITS = stats.alt_unit_names;
|
||||
}
|
||||
}
|
||||
|
||||
global.GoaAmount = {
|
||||
format: format,
|
||||
setText: setText,
|
||||
setById: setById,
|
||||
pick: pick,
|
||||
rememberAlt: rememberAlt,
|
||||
DEFAULT_ALT: DEFAULT_ALT,
|
||||
THRESHOLD: THRESHOLD
|
||||
};
|
||||
})(typeof window !== "undefined" ? window : globalThis);
|
||||
|
|
@ -30,6 +30,22 @@
|
|||
if (el) el.textContent = v == null || v === "" ? "—" : String(v);
|
||||
}
|
||||
|
||||
function setAmt(id, rowOrAmt, altMap) {
|
||||
var el = document.getElementById(id);
|
||||
if (!el) return;
|
||||
if (window.GoaAmount) {
|
||||
var f = GoaAmount.pick(rowOrAmt, altMap);
|
||||
el.textContent = f.display;
|
||||
if (f.title && f.title !== f.display) el.setAttribute("title", f.title);
|
||||
else el.removeAttribute("title");
|
||||
} else {
|
||||
var raw = rowOrAmt && typeof rowOrAmt === "object"
|
||||
? (rowOrAmt.amount_alt || rowOrAmt.amount || "—")
|
||||
: (rowOrAmt == null || rowOrAmt === "" ? "—" : String(rowOrAmt));
|
||||
el.textContent = raw;
|
||||
}
|
||||
}
|
||||
|
||||
function showFallback(msg) {
|
||||
var box = document.getElementById("stats");
|
||||
var foot = document.getElementById("st-foot");
|
||||
|
|
@ -68,6 +84,7 @@
|
|||
})
|
||||
.then(function (d) {
|
||||
if (!d || !d.ok) throw new Error("bad stats");
|
||||
if (window.GoaAmount) GoaAmount.rememberAlt(d);
|
||||
var w = d.withdraws || {};
|
||||
var h24 = w.last_24h || {};
|
||||
var h7 = w.last_7d || {};
|
||||
|
|
@ -78,10 +95,10 @@
|
|||
var fwd = flow.withdraw || {};
|
||||
set("st-accounts", ba.total != null ? ba.total : "—");
|
||||
set("st-wallets", wl.unique_reserves != null ? wl.unique_reserves : "—");
|
||||
set("st-incoming", fin.amount || flow.total_in || "—");
|
||||
set("st-withdraw", fwd.amount || w.total_amount || "—");
|
||||
set("st-24h", h24.amount || "GOA:0");
|
||||
set("st-7d", h7.amount || "GOA:0");
|
||||
setAmt("st-incoming", fin.amount_alt ? fin : (fin.amount || flow.total_in || "—"), d.alt_unit_names);
|
||||
setAmt("st-withdraw", fwd.amount_alt ? fwd : (fwd.amount || w.total_amount || "—"), d.alt_unit_names);
|
||||
setAmt("st-24h", h24.amount_alt ? h24 : (h24.amount || "GOA:0"), d.alt_unit_names);
|
||||
setAmt("st-7d", h7.amount_alt ? h7 : (h7.amount || "GOA:0"), d.alt_unit_names);
|
||||
|
||||
var list = document.getElementById("st-recent");
|
||||
if (list) {
|
||||
|
|
@ -97,7 +114,13 @@
|
|||
var li = document.createElement("li");
|
||||
var amt = document.createElement("span");
|
||||
amt.className = "amt";
|
||||
amt.textContent = row.amount || "?";
|
||||
if (window.GoaAmount) {
|
||||
var af = GoaAmount.pick(row, d.alt_unit_names);
|
||||
amt.textContent = af.display;
|
||||
if (af.title && af.title !== af.display) amt.setAttribute("title", af.title);
|
||||
} else {
|
||||
amt.textContent = row.amount_alt || row.amount || "?";
|
||||
}
|
||||
var meta = document.createElement("span");
|
||||
meta.className = "meta";
|
||||
meta.textContent = fmtCest(row.at_unix, row.at || row.at_iso) || "";
|
||||
|
|
@ -112,7 +135,8 @@
|
|||
foot.className = "stats-foot";
|
||||
foot.innerHTML =
|
||||
'Source: <a href="' + BANK_INTRO + '">bank.hacktivism.ch</a>' +
|
||||
(d.generated_at_human ? " · " + d.generated_at_human : "");
|
||||
(d.generated_at_human ? " · " + d.generated_at_human : "") +
|
||||
(d.source ? " · " + d.source : "");
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue