landing: harden GOA alt display for all three sites
Ship goa-amount.js inside each landing tree, add an inline fallback when the asset is not yet deployed, keep CHF free of GOA unit names, fix exchange amount_full wiring, and add test-landing-stats.sh (local + live).
This commit is contained in:
parent
b65018cd0b
commit
9e0f85024b
10 changed files with 796 additions and 16 deletions
169
configs/bank-landing/goa-amount.js
Normal file
169
configs/bank-landing/goa-amount.js
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
/* 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);
|
||||||
|
// Foreign currencies must not pick up Kilo-GOA / Mega-GOA labels
|
||||||
|
var baseName = (alt && alt["0"]) || p.cur;
|
||||||
|
var curU = String(p.cur || "").toUpperCase();
|
||||||
|
var baseU = String(baseName || "").toUpperCase();
|
||||||
|
if (curU && curU !== "GOA" && (baseU === "GOA" || baseU.indexOf("GOA") !== -1)) {
|
||||||
|
return { display: raw, title: raw, raw: raw, usedAlt: false };
|
||||||
|
}
|
||||||
|
if (p.val === 0) {
|
||||||
|
return { display: raw, 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);
|
||||||
|
|
@ -1493,6 +1493,33 @@ tw run-until-done && tw balance</pre>
|
||||||
|
|
||||||
<script src="/intro/goa-amount.js"></script>
|
<script src="/intro/goa-amount.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
/* Fallback if goa-amount.js not yet deployed (uses amount_alt from stats.json) */
|
||||||
|
(function () {
|
||||||
|
if (window.GoaAmount) return;
|
||||||
|
window.GoaAmount = {
|
||||||
|
rememberAlt: function () {},
|
||||||
|
format: function (a) {
|
||||||
|
var s = a == null || a === "" ? "—" : String(a);
|
||||||
|
return { display: s, title: s === "—" ? "" : s, raw: s, usedAlt: false };
|
||||||
|
},
|
||||||
|
pick: function (row) {
|
||||||
|
if (row && typeof row === "object") {
|
||||||
|
if (row.amount_alt) {
|
||||||
|
return {
|
||||||
|
display: String(row.amount_alt),
|
||||||
|
title: String(row.amount_full || row.amount || row.amount_alt),
|
||||||
|
raw: String(row.amount || ""),
|
||||||
|
usedAlt: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this.format(row.amount || row.total_amount || "—");
|
||||||
|
}
|
||||||
|
return this.format(row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
var WEBUI = "https://bank.hacktivism.ch/webui/";
|
var WEBUI = "https://bank.hacktivism.ch/webui/";
|
||||||
/* Secondary: own-account path (register first) */
|
/* Secondary: own-account path (register first) */
|
||||||
|
|
|
||||||
169
configs/exchange-landing/goa-amount.js
Normal file
169
configs/exchange-landing/goa-amount.js
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
/* 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);
|
||||||
|
// Foreign currencies must not pick up Kilo-GOA / Mega-GOA labels
|
||||||
|
var baseName = (alt && alt["0"]) || p.cur;
|
||||||
|
var curU = String(p.cur || "").toUpperCase();
|
||||||
|
var baseU = String(baseName || "").toUpperCase();
|
||||||
|
if (curU && curU !== "GOA" && (baseU === "GOA" || baseU.indexOf("GOA") !== -1)) {
|
||||||
|
return { display: raw, title: raw, raw: raw, usedAlt: false };
|
||||||
|
}
|
||||||
|
if (p.val === 0) {
|
||||||
|
return { display: raw, 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);
|
||||||
|
|
@ -446,6 +446,33 @@ sudo apt-get install -y taler-wallet-cli</pre>
|
||||||
</main>
|
</main>
|
||||||
<script src="/intro/goa-amount.js"></script>
|
<script src="/intro/goa-amount.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
/* Fallback if goa-amount.js not yet deployed (uses amount_alt from stats.json) */
|
||||||
|
(function () {
|
||||||
|
if (window.GoaAmount) return;
|
||||||
|
window.GoaAmount = {
|
||||||
|
rememberAlt: function () {},
|
||||||
|
format: function (a) {
|
||||||
|
var s = a == null || a === "" ? "—" : String(a);
|
||||||
|
return { display: s, title: s === "—" ? "" : s, raw: s, usedAlt: false };
|
||||||
|
},
|
||||||
|
pick: function (row) {
|
||||||
|
if (row && typeof row === "object") {
|
||||||
|
if (row.amount_alt) {
|
||||||
|
return {
|
||||||
|
display: String(row.amount_alt),
|
||||||
|
title: String(row.amount_full || row.amount || row.amount_alt),
|
||||||
|
raw: String(row.amount || ""),
|
||||||
|
usedAlt: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this.format(row.amount || row.total_amount || "—");
|
||||||
|
}
|
||||||
|
return this.format(row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
function set(id, v) {
|
function set(id, v) {
|
||||||
var el = document.getElementById(id);
|
var el = document.getElementById(id);
|
||||||
|
|
@ -454,17 +481,21 @@ sudo apt-get install -y taler-wallet-cli</pre>
|
||||||
function setAmt(id, amount, altKey, d) {
|
function setAmt(id, amount, altKey, d) {
|
||||||
var el = document.getElementById(id);
|
var el = document.getElementById(id);
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
var row = null;
|
var row = { amount: amount };
|
||||||
if (altKey && d && d[altKey]) {
|
if (altKey && d && d[altKey]) {
|
||||||
row = { amount: amount, amount_alt: d[altKey], amount_full: d[altKey.replace(/_alt$/, "_full")] || d[amount + "_full"] };
|
row.amount_alt = d[altKey];
|
||||||
|
var fullKey = String(altKey).replace(/_alt$/, "_full");
|
||||||
|
if (d[fullKey]) row.amount_full = d[fullKey];
|
||||||
}
|
}
|
||||||
if (window.GoaAmount) {
|
if (window.GoaAmount) {
|
||||||
var f = row ? GoaAmount.pick(row, d && d.alt_unit_names) : GoaAmount.format(amount, d && d.alt_unit_names);
|
var f = (row.amount_alt || (d && d.alt_unit_names))
|
||||||
|
? GoaAmount.pick(row, d && d.alt_unit_names)
|
||||||
|
: GoaAmount.format(amount, d && d.alt_unit_names);
|
||||||
el.textContent = f.display;
|
el.textContent = f.display;
|
||||||
if (f.title && f.title !== f.display) el.setAttribute("title", f.title);
|
if (f.title && f.title !== f.display) el.setAttribute("title", f.title);
|
||||||
else el.removeAttribute("title");
|
else el.removeAttribute("title");
|
||||||
} else {
|
} else {
|
||||||
el.textContent = (row && row.amount_alt) || amount || "—";
|
el.textContent = row.amount_alt || amount || "—";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function msLabel(ms, http) {
|
function msLabel(ms, http) {
|
||||||
|
|
|
||||||
169
configs/merchant-landing/goa-amount.js
Normal file
169
configs/merchant-landing/goa-amount.js
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
/* 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);
|
||||||
|
// Foreign currencies must not pick up Kilo-GOA / Mega-GOA labels
|
||||||
|
var baseName = (alt && alt["0"]) || p.cur;
|
||||||
|
var curU = String(p.cur || "").toUpperCase();
|
||||||
|
var baseU = String(baseName || "").toUpperCase();
|
||||||
|
if (curU && curU !== "GOA" && (baseU === "GOA" || baseU.indexOf("GOA") !== -1)) {
|
||||||
|
return { display: raw, title: raw, raw: raw, usedAlt: false };
|
||||||
|
}
|
||||||
|
if (p.val === 0) {
|
||||||
|
return { display: raw, 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);
|
||||||
|
|
@ -813,6 +813,33 @@ sudo apt-get install -y taler-wallet-cli</pre>
|
||||||
</main>
|
</main>
|
||||||
<script src="/intro/goa-amount.js"></script>
|
<script src="/intro/goa-amount.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
/* Fallback if goa-amount.js not yet deployed (uses amount_alt from stats.json) */
|
||||||
|
(function () {
|
||||||
|
if (window.GoaAmount) return;
|
||||||
|
window.GoaAmount = {
|
||||||
|
rememberAlt: function () {},
|
||||||
|
format: function (a) {
|
||||||
|
var s = a == null || a === "" ? "—" : String(a);
|
||||||
|
return { display: s, title: s === "—" ? "" : s, raw: s, usedAlt: false };
|
||||||
|
},
|
||||||
|
pick: function (row) {
|
||||||
|
if (row && typeof row === "object") {
|
||||||
|
if (row.amount_alt) {
|
||||||
|
return {
|
||||||
|
display: String(row.amount_alt),
|
||||||
|
title: String(row.amount_full || row.amount || row.amount_alt),
|
||||||
|
raw: String(row.amount || ""),
|
||||||
|
usedAlt: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this.format(row.amount || row.amount_paid_sum || row.amount_sum || "—");
|
||||||
|
}
|
||||||
|
return this.format(row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
function set(id, v) {
|
function set(id, v) {
|
||||||
var el = document.getElementById(id);
|
var el = document.getElementById(id);
|
||||||
|
|
|
||||||
|
|
@ -76,9 +76,15 @@
|
||||||
var alt = altMap || global.__GOA_ALT_UNITS || DEFAULT_ALT;
|
var alt = altMap || global.__GOA_ALT_UNITS || DEFAULT_ALT;
|
||||||
var p = parseAmount(amount);
|
var p = parseAmount(amount);
|
||||||
var raw = baseStr(p.cur, p.val);
|
var raw = baseStr(p.cur, p.val);
|
||||||
|
// Foreign currencies must not pick up Kilo-GOA / Mega-GOA labels
|
||||||
|
var baseName = (alt && alt["0"]) || p.cur;
|
||||||
|
var curU = String(p.cur || "").toUpperCase();
|
||||||
|
var baseU = String(baseName || "").toUpperCase();
|
||||||
|
if (curU && curU !== "GOA" && (baseU === "GOA" || baseU.indexOf("GOA") !== -1)) {
|
||||||
|
return { display: raw, title: raw, raw: raw, usedAlt: false };
|
||||||
|
}
|
||||||
if (p.val === 0) {
|
if (p.val === 0) {
|
||||||
var zname = (alt && alt["0"]) || p.cur;
|
return { display: raw, title: raw, raw: raw, usedAlt: false };
|
||||||
return { display: "0 " + zname, title: raw, raw: raw, usedAlt: false };
|
|
||||||
}
|
}
|
||||||
if (Math.abs(p.val) < THRESHOLD) {
|
if (Math.abs(p.val) < THRESHOLD) {
|
||||||
return { display: raw, title: raw, raw: raw, usedAlt: false };
|
return { display: raw, title: raw, raw: raw, usedAlt: false };
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,26 @@ C_EX=taler-hacktivism-exchange-ansible
|
||||||
C_MER=taler-hacktivism
|
C_MER=taler-hacktivism
|
||||||
C_BANK="${C_BANK:-taler-hacktivism-bank}"
|
C_BANK="${C_BANK:-taler-hacktivism-bank}"
|
||||||
|
|
||||||
|
# Prefer per-landing copy, then shared (keeps bank/exchange/merchant in sync)
|
||||||
|
resolve_goa_amount() {
|
||||||
|
local local_copy="$1"
|
||||||
|
if [ -f "$local_copy" ]; then
|
||||||
|
printf '%s' "$local_copy"
|
||||||
|
elif [ -f "$SRC_GOA_AMT" ]; then
|
||||||
|
printf '%s' "$SRC_GOA_AMT"
|
||||||
|
else
|
||||||
|
printf ''
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
copy_goa_amount() {
|
copy_goa_amount() {
|
||||||
local ctr="$1" dest="$2"
|
local ctr="$1" dest="$2" src="$3"
|
||||||
if [ -f "$SRC_GOA_AMT" ]; then
|
src=$(resolve_goa_amount "$src")
|
||||||
podman cp "$SRC_GOA_AMT" "${ctr}:${dest}/goa-amount.js"
|
if [ -n "$src" ] && [ -f "$src" ]; then
|
||||||
|
podman cp "$src" "${ctr}:${dest}/goa-amount.js"
|
||||||
|
echo " goa-amount.js ← $src"
|
||||||
|
else
|
||||||
|
echo " WARN: goa-amount.js missing for $ctr"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,7 +51,7 @@ if podman inspect -f '{{.State.Running}}' "$C_BANK" 2>/dev/null | grep -qx true;
|
||||||
if [ -f "$SRC_BANK/index.html" ]; then
|
if [ -f "$SRC_BANK/index.html" ]; then
|
||||||
podman cp "$SRC_BANK/index.html" "$C_BANK:/var/www/bank-landing/index.html"
|
podman cp "$SRC_BANK/index.html" "$C_BANK:/var/www/bank-landing/index.html"
|
||||||
fi
|
fi
|
||||||
copy_goa_amount "$C_BANK" /var/www/bank-landing
|
copy_goa_amount "$C_BANK" /var/www/bank-landing "$SRC_BANK/goa-amount.js"
|
||||||
else
|
else
|
||||||
echo "WARN: $C_BANK not running — skip bank landing files"
|
echo "WARN: $C_BANK not running — skip bank landing files"
|
||||||
fi
|
fi
|
||||||
|
|
@ -51,7 +67,7 @@ podman cp "$SRC_EX/index.html" "$C_EX:/var/www/exchange-landing/index.html"
|
||||||
if [ -f "$SRC_QR" ]; then
|
if [ -f "$SRC_QR" ]; then
|
||||||
podman cp "$SRC_QR" "$C_EX:/var/www/exchange-landing/qrcode.min.js"
|
podman cp "$SRC_QR" "$C_EX:/var/www/exchange-landing/qrcode.min.js"
|
||||||
fi
|
fi
|
||||||
copy_goa_amount "$C_EX" /var/www/exchange-landing
|
copy_goa_amount "$C_EX" /var/www/exchange-landing "$SRC_EX/goa-amount.js"
|
||||||
podman cp "$SRC_EX/nginx-landing.conf" "$C_EX:/etc/nginx/sites-available/exchange-landing"
|
podman cp "$SRC_EX/nginx-landing.conf" "$C_EX:/etc/nginx/sites-available/exchange-landing"
|
||||||
podman exec "$C_EX" bash -c '
|
podman exec "$C_EX" bash -c '
|
||||||
ln -sfn /etc/nginx/sites-available/exchange-landing /etc/nginx/sites-enabled/exchange-landing
|
ln -sfn /etc/nginx/sites-available/exchange-landing /etc/nginx/sites-enabled/exchange-landing
|
||||||
|
|
@ -72,7 +88,7 @@ podman exec "$C_EX" bash -c '
|
||||||
echo "=== merchant landing → $C_MER :9015 ==="
|
echo "=== merchant landing → $C_MER :9015 ==="
|
||||||
podman exec "$C_MER" mkdir -p /var/www/merchant-landing
|
podman exec "$C_MER" mkdir -p /var/www/merchant-landing
|
||||||
podman cp "$SRC_MER/index.html" "$C_MER:/var/www/merchant-landing/index.html"
|
podman cp "$SRC_MER/index.html" "$C_MER:/var/www/merchant-landing/index.html"
|
||||||
copy_goa_amount "$C_MER" /var/www/merchant-landing
|
copy_goa_amount "$C_MER" /var/www/merchant-landing "$SRC_MER/goa-amount.js"
|
||||||
podman cp "$SRC_MER/nginx-landing.conf" "$C_MER:/etc/nginx/sites-available/merchant-landing"
|
podman cp "$SRC_MER/nginx-landing.conf" "$C_MER:/etc/nginx/sites-available/merchant-landing"
|
||||||
podman exec "$C_MER" bash -c '
|
podman exec "$C_MER" bash -c '
|
||||||
ln -sfn /etc/nginx/sites-available/merchant-landing /etc/nginx/sites-enabled/merchant-landing
|
ln -sfn /etc/nginx/sites-available/merchant-landing /etc/nginx/sites-enabled/merchant-landing
|
||||||
|
|
|
||||||
|
|
@ -102,12 +102,24 @@ def format_amount_alt(
|
||||||
value_f = 0.0
|
value_f = 0.0
|
||||||
|
|
||||||
base_name = alt.get("0") or cur
|
base_name = alt.get("0") or cur
|
||||||
if val == 0:
|
# Never rename foreign currencies with a GOA alt map (merchant dual CHF+GOA).
|
||||||
disp = f"0 {base_name}"
|
cur_u = (cur or "").upper()
|
||||||
|
base_u = str(base_name).upper()
|
||||||
|
if cur_u and cur_u != "GOA" and (base_u == "GOA" or base_u.endswith("-GOA") or "GOA" in base_u):
|
||||||
return {
|
return {
|
||||||
"amount": base,
|
"amount": base,
|
||||||
"amount_alt": disp,
|
"amount_alt": base,
|
||||||
"amount_full": disp,
|
"amount_full": base,
|
||||||
|
"value": value_f,
|
||||||
|
"value_str": value_str,
|
||||||
|
}
|
||||||
|
|
||||||
|
if val == 0:
|
||||||
|
# Keep canonical CUR:0 (avoids "0 GOA" for empty foreign balances)
|
||||||
|
return {
|
||||||
|
"amount": base,
|
||||||
|
"amount_alt": base,
|
||||||
|
"amount_full": base,
|
||||||
"value": 0.0,
|
"value": 0.0,
|
||||||
"value_str": "0",
|
"value_str": "0",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
154
scripts/taler-landing/test-landing-stats.sh
Executable file
154
scripts/taler-landing/test-landing-stats.sh
Executable file
|
|
@ -0,0 +1,154 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Outside-in checks for bank / exchange / merchant landing stats + alt UI assets.
|
||||||
|
# Usage: ./test-landing-stats.sh
|
||||||
|
# Exit 0 only if all critical checks pass.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||||
|
PY="${PYTHON:-python3}"
|
||||||
|
BANK="${BANK_PUBLIC:-https://bank.hacktivism.ch}"
|
||||||
|
EX="${EXCHANGE_PUBLIC:-https://exchange.hacktivism.ch}"
|
||||||
|
MER="${MERCHANT_PUBLIC:-https://taler.hacktivism.ch}"
|
||||||
|
|
||||||
|
fail=0
|
||||||
|
pass=0
|
||||||
|
note() { printf ' %s\n' "$*"; }
|
||||||
|
ok() { pass=$((pass + 1)); printf ' [OK] %s\n' "$*"; }
|
||||||
|
bad() { fail=$((fail + 1)); printf ' [FAIL] %s\n' "$*"; }
|
||||||
|
|
||||||
|
http_code() {
|
||||||
|
curl -skS -m 15 -o /tmp/landing-test.body -w '%{http_code}' "$1" 2>/dev/null || echo 000
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "=== local repo checks ==="
|
||||||
|
for f in \
|
||||||
|
configs/shared/goa-amount.js \
|
||||||
|
configs/bank-landing/goa-amount.js \
|
||||||
|
configs/exchange-landing/goa-amount.js \
|
||||||
|
configs/merchant-landing/goa-amount.js \
|
||||||
|
configs/bank-landing/index.html \
|
||||||
|
configs/exchange-landing/index.html \
|
||||||
|
configs/merchant-landing/index.html \
|
||||||
|
scripts/taler-landing/goa_amounts.py \
|
||||||
|
scripts/taler-landing/collect_bank_stats.py
|
||||||
|
do
|
||||||
|
if [ -f "$ROOT/$f" ]; then ok "file $f"
|
||||||
|
else bad "missing $f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for html in bank-landing exchange-landing merchant-landing; do
|
||||||
|
if grep -q 'goa-amount.js' "$ROOT/configs/$html/index.html" \
|
||||||
|
&& grep -q 'GoaAmount' "$ROOT/configs/$html/index.html"; then
|
||||||
|
ok "$html index wires GoaAmount"
|
||||||
|
else
|
||||||
|
bad "$html index missing goa-amount / GoaAmount"
|
||||||
|
fi
|
||||||
|
if grep -q 'Fallback if goa-amount.js' "$ROOT/configs/$html/index.html"; then
|
||||||
|
ok "$html has offline fallback"
|
||||||
|
else
|
||||||
|
bad "$html missing offline GoaAmount fallback"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== unit: goa_amounts enrich (all three shapes) ==="
|
||||||
|
if "$PY" - <<PY
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, "$ROOT/scripts/taler-landing")
|
||||||
|
from goa_amounts import enrich_stats_tree, DEFAULT_ALT
|
||||||
|
|
||||||
|
bank = {
|
||||||
|
"ok": True,
|
||||||
|
"balance_explorer": "GOA:40614.67",
|
||||||
|
"withdraws": {"total_amount": "GOA:120944.66", "last_24h": {"amount": "GOA:9494.66"}},
|
||||||
|
"flow": {"withdraw": {"amount": "GOA:120944.66"}, "incoming": {"amount": "GOA:1000"}},
|
||||||
|
"recent_withdraws": [{"amount": "GOA:4503599627370495"}],
|
||||||
|
}
|
||||||
|
enrich_stats_tree(bank, DEFAULT_ALT)
|
||||||
|
assert "Kilo-GOA" in bank["withdraws"]["total_amount_alt"]
|
||||||
|
assert "Peta-GOA" in bank["recent_withdraws"][0]["amount_alt"]
|
||||||
|
|
||||||
|
ex = {
|
||||||
|
"ok": True,
|
||||||
|
"wire_in_amount": "GOA:1267008731299764.85",
|
||||||
|
"withdraw_amount": "GOA:1783661.57",
|
||||||
|
"coins_remaining_amount": "GOA:0",
|
||||||
|
"by_denom": [{"value": "GOA:1000"}],
|
||||||
|
}
|
||||||
|
enrich_stats_tree(ex, DEFAULT_ALT)
|
||||||
|
assert "Peta-GOA" in ex["wire_in_amount_alt"]
|
||||||
|
assert "Mega-GOA" in ex["withdraw_amount_alt"]
|
||||||
|
assert ex["coins_remaining_amount_alt"] in ("GOA:0", "0 GOA")
|
||||||
|
|
||||||
|
mer = {
|
||||||
|
"ok": True,
|
||||||
|
"by_currency": [
|
||||||
|
{"currency": "GOA", "amount_sum": "GOA:294.05", "amount_paid_sum": "GOA:294.05"},
|
||||||
|
{"currency": "CHF", "amount_sum": "CHF:64000", "amount_paid_sum": "CHF:64000"},
|
||||||
|
],
|
||||||
|
"recent_activity_by_currency": [
|
||||||
|
{"currency": "GOA", "items": [{"amount": "GOA:2500"}]},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
enrich_stats_tree(mer, DEFAULT_ALT)
|
||||||
|
# CHF must NOT become Kilo-GOA
|
||||||
|
assert "GOA" not in mer["by_currency"][1]["amount_paid_sum_alt"] or mer["by_currency"][1]["amount_paid_sum_alt"].startswith("CHF")
|
||||||
|
assert mer["by_currency"][1]["amount_paid_sum_alt"].startswith("CHF")
|
||||||
|
assert "Kilo-GOA" in mer["recent_activity_by_currency"][0]["items"][0]["amount_alt"]
|
||||||
|
print("unit ok")
|
||||||
|
PY
|
||||||
|
then ok "enrich shapes bank/exchange/merchant"
|
||||||
|
else bad "enrich unit failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== public HTTPS (live stack) ==="
|
||||||
|
for name_base in "bank|$BANK" "exchange|$EX" "merchant|$MER"; do
|
||||||
|
name="${name_base%%|*}"
|
||||||
|
base="${name_base#*|}"
|
||||||
|
echo "-- $name ($base) --"
|
||||||
|
code=$(http_code "$base/intro/")
|
||||||
|
if [ "$code" = "200" ]; then ok "$name /intro/ HTTP 200"
|
||||||
|
else bad "$name /intro/ HTTP $code"
|
||||||
|
fi
|
||||||
|
# live HTML may lag deploy — warn only if missing script after we expect it
|
||||||
|
if grep -q 'goa-amount.js' /tmp/landing-test.body 2>/dev/null; then
|
||||||
|
ok "$name live HTML references goa-amount.js"
|
||||||
|
else
|
||||||
|
note "[WARN] $name live HTML has no goa-amount.js yet (deploy pending)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
code=$(http_code "$base/intro/stats.json")
|
||||||
|
if [ "$code" = "200" ] && "$PY" -c 'import json,sys; d=json.load(open("/tmp/landing-test.body")); sys.exit(0 if d.get("ok") else 1)'; then
|
||||||
|
gen=$("$PY" -c 'import json; d=json.load(open("/tmp/landing-test.body")); print(d.get("generated_at_human") or d.get("generated_at") or "?")')
|
||||||
|
ok "$name stats.json ok (gen=$gen)"
|
||||||
|
# enrich live payload
|
||||||
|
if "$PY" "$ROOT/scripts/taler-landing/enrich_stats_alt.py" /tmp/landing-test.body -o /tmp/landing-test.enriched.json >/dev/null 2>&1; then
|
||||||
|
ok "$name live stats enrichable with amount_alt"
|
||||||
|
else
|
||||||
|
bad "$name live stats enrich failed"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
bad "$name stats.json HTTP $code / not ok"
|
||||||
|
fi
|
||||||
|
|
||||||
|
code=$(http_code "$base/intro/stats-run.json")
|
||||||
|
if [ "$code" = "200" ]; then ok "$name stats-run.json HTTP 200"
|
||||||
|
else bad "$name stats-run.json HTTP $code"
|
||||||
|
fi
|
||||||
|
|
||||||
|
code=$(http_code "$base/intro/goa-amount.js")
|
||||||
|
if [ "$code" = "200" ] && grep -q 'GoaAmount' /tmp/landing-test.body; then
|
||||||
|
ok "$name goa-amount.js live"
|
||||||
|
else
|
||||||
|
note "[WARN] $name goa-amount.js not live yet (HTTP $code) — deploy-landings.sh needed"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== result: pass=$pass fail=$fail ==="
|
||||||
|
if [ "$fail" -gt 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
Loading…
Add table
Add a link
Reference in a new issue