This commit is contained in:
2025-11-21 17:15:05 +01:00
parent e3894f9577
commit 23e2a82f5c
29 changed files with 9131 additions and 132 deletions

View File

@@ -3,17 +3,16 @@ const fs = require('fs');
module.exports = { module.exports = {
bfx: async function() { bfx: async function() {
const eurrate = 0.92 // approximate EUR/USD rate const btcDataURL = "https://api-pub.bitfinex.com/v2/ticker/tBTCEUR"
const btcDataURL = "https://api-pub.bitfinex.com/v2/ticker/tBTCUSD"
const response = await axios.get(btcDataURL) const response = await axios.get(btcDataURL)
const data = response.data const data = response.data
//console.log(data[6]) //console.log(data[6])
const satDenominator = 100000000 const satDenominator = 100000000
// see docs : https://docs.bitfinex.com/reference#rest-public-ticker // see docs : https://docs.bitfinex.com/reference#rest-public-ticker
btcLastPrice = data[6] const btcLastPrice = data[6] // LAST_PRICE in EUR
const sateur = Math.round((1 / btcLastPrice) * satDenominator * eurrate) const sateur = Math.round(satDenominator / btcLastPrice)
//console.log("bitfinex last price: ", btcLastPrice, "current satEUR: ", sateur) //console.log("bitfinex last price: ", btcLastPrice, "current satEUR: ", sateur)
return sateur return sateur
}, },
@@ -28,22 +27,34 @@ module.exports = {
hist_entries = [] hist_entries = []
let datelist = [] let datelist = []
// get all the years you need from 1 - 10 // Get all years from 2011 to previous year (skip current year since it's shown at top)
for (let i = 1; i < 11; i++) { const currentDate = new Date()
const targetDate = new Date(new Date().setFullYear(new Date().getFullYear() - i)) const currentYear = currentDate.getFullYear()
const targetDateStr = targetDate.toISOString().slice(0, 10) const previousYear = currentYear - 1
const startYear = 2011
// Find the closest date in historical data for (let year = startYear; year <= previousYear; year++) {
let targetDate
let targetDateStr
// For all years, use January 1st (or close to it) to find historical data
targetDate = new Date(year, 0, 1) // January 1st of target year
targetDateStr = targetDate.toISOString().slice(0, 10)
// Find the closest date in historical data for this specific year
let closestEntry = null let closestEntry = null
let minDiff = Infinity let minDiff = Infinity
for (let j = 0; j < historical.length; j++) { for (let j = 0; j < historical.length; j++) {
const entryDate = new Date(historical[j]['date']) const entryDate = new Date(historical[j]['date'])
const diff = Math.abs(entryDate - targetDate) // Only consider entries from the target year
if (entryDate.getFullYear() === year) {
const diff = Math.abs(entryDate - targetDate)
if (diff < minDiff) { if (diff < minDiff) {
minDiff = diff minDiff = diff
closestEntry = historical[j] closestEntry = historical[j]
}
} }
} }
@@ -71,7 +82,7 @@ module.exports = {
percentage = (-100 * ((rawsat - today_sats) / rawsat)).toFixed(3) percentage = (-100 * ((rawsat - today_sats) / rawsat)).toFixed(3)
final_list.push({ "year": date.toLocaleDateString(), "sats": rawsat.toLocaleString("en-US"), "percent": percentage }); final_list.push({ "year": date.toLocaleDateString(), "sats": rawsat.toLocaleString("en-US"), "percent": percentage });
} }
return final_list.reverse() return final_list
} catch (error) { } catch (error) {
console.error("Error trying to read file ", error) console.error("Error trying to read file ", error)
} }

View File

@@ -8,7 +8,7 @@ const path = require('path');
const app = express(); const app = express();
const handlebars = require('express-handlebars'); const handlebars = require('express-handlebars');
const port = 3000; const port = process.env.PORT || 3000;
const calculate = require('./calculate') const calculate = require('./calculate')
const enjson = require('./locales/en-eur.json'); const enjson = require('./locales/en-eur.json');
@@ -54,8 +54,102 @@ app.use('/static', express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public', 'css'))); app.use(express.static(path.join(__dirname, 'public', 'css')));
// Language mapping from browser codes to app routes
const languageMap = {
'en': '/en-eur',
'en-US': '/en-eur',
'en-GB': '/en-eur',
'de': '/de',
'de-DE': '/de',
'de-AT': '/de',
'de-CH': '/de',
'fr': '/fr',
'fr-FR': '/fr',
'fr-CA': '/fr',
'fr-BE': '/fr',
'es': '/es',
'es-ES': '/es',
'es-MX': '/es',
'es-AR': '/es',
'it': '/it',
'it-IT': '/it',
'nl': '/nl',
'nl-NL': '/nl',
'nl-BE': '/nl',
'pt': '/pt',
'pt-PT': '/pt',
'pt-BR': '/pt',
'pl': '/pl',
'pl-PL': '/pl',
'bg': '/bg',
'bg-BG': '/bg',
'hr': '/hr',
'hr-HR': '/hr',
'cs': '/cs',
'cs-CZ': '/cs',
'da': '/da',
'da-DK': '/da',
'et': '/et',
'et-EE': '/et',
'fi': '/fi',
'fi-FI': '/fi',
'el': '/el',
'el-GR': '/el',
'hu': '/hu',
'hu-HU': '/hu',
'ga': '/ga',
'ga-IE': '/ga',
'lv': '/lv',
'lv-LV': '/lv',
'lt': '/lt',
'lt-LT': '/lt',
'mt': '/mt',
'mt-MT': '/mt',
'ro': '/ro',
'ro-RO': '/ro',
'sk': '/sk',
'sk-SK': '/sk',
'sl': '/sl',
'sl-SI': '/sl',
'sv': '/sv',
'sv-SE': '/sv'
};
function getLanguageFromHeader(acceptLanguage) {
if (!acceptLanguage) return '/en-eur';
// Parse Accept-Language header
const languages = acceptLanguage.split(',').map(lang => {
const [locale, quality = 'q=1.0'] = lang.trim().split(';');
const q = quality.split('=')[1] || '1.0';
return { locale, q: parseFloat(q) };
});
// Sort by quality (highest first)
languages.sort((a, b) => b.q - a.q);
// Find first supported language
for (const { locale } of languages) {
// Check exact match first
if (languageMap[locale]) {
return languageMap[locale];
}
// Check primary language (e.g., 'en' from 'en-US')
const primaryLang = locale.split('-')[0];
if (languageMap[primaryLang]) {
return languageMap[primaryLang];
}
}
// Default to English if no supported language found
return '/en-eur';
}
app.get('/', function(req, res) { app.get('/', function(req, res) {
res.redirect('/en-eur'); const acceptLanguage = req.headers['accept-language'];
const targetLanguage = getLanguageFromHeader(acceptLanguage);
res.redirect(targetLanguage);
}); });
// EUR routes // EUR routes

View File

@@ -14,10 +14,9 @@
"date": "Дата", "date": "Дата",
"price": "Цена", "price": "Цена",
"percentchange": "Процентна Промяна", "percentchange": "Процентна Промяна",
"footnote": "източник на данни от usdsat.com, адаптиран за EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Datum", "date": "Datum",
"price": "Cena", "price": "Cena",
"percentchange": "Procentní Změna", "percentchange": "Procentní Změna",
"footnote": "zdroj dat z usdsat.com, přizpůsobeno pro EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Dato", "date": "Dato",
"price": "Pris", "price": "Pris",
"percentchange": "Procentvis Ændring", "percentchange": "Procentvis Ændring",
"footnote": "datakilde fra usdsat.com, tilpasset til EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Datum", "date": "Datum",
"price": "Preis", "price": "Preis",
"percentchange": "Prozentuale Änderung", "percentchange": "Prozentuale Änderung",
"footnote": "Datenquelle von usdsat.com, angepasst für EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/fr/", "lang2_link": "/fr/",

View File

@@ -14,10 +14,9 @@
"date": "Ημερομηνία", "date": "Ημερομηνία",
"price": "Τιμή", "price": "Τιμή",
"percentchange": "Ποσοστιαία Αλλαγή", "percentchange": "Ποσοστιαία Αλλαγή",
"footnote": "πηγή δεδομένων από usdsat.com, προσαρμοσμένο για EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Date", "date": "Date",
"price": "Price", "price": "Price",
"percentchange": "Percent Change", "percentchange": "Percent Change",
"footnote": "data source from usdsat.com, adapted for EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/de/", "lang1_link": "/de/",
"lang1": "Deutsch", "lang1": "Deutsch",
"lang2_link": "/fr/", "lang2_link": "/fr/",

View File

@@ -14,10 +14,9 @@
"date": "Fecha", "date": "Fecha",
"price": "Precio", "price": "Precio",
"percentchange": "Cambio Porcentual", "percentchange": "Cambio Porcentual",
"footnote": "fuente de datos de usdsat.com, adaptado para EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Kuupäev", "date": "Kuupäev",
"price": "Hind", "price": "Hind",
"percentchange": "Protsentuaalne Muutus", "percentchange": "Protsentuaalne Muutus",
"footnote": "andmete allikas usdsat.com, kohandatud EUR jaoks", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Päivämäärä", "date": "Päivämäärä",
"price": "Hinta", "price": "Hinta",
"percentchange": "Prosentuaalinen Muutos", "percentchange": "Prosentuaalinen Muutos",
"footnote": "tietolähde usdsat.com, mukautettu EUR:lle", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Date", "date": "Date",
"price": "Prix", "price": "Prix",
"percentchange": "Variation en Pourcentage", "percentchange": "Variation en Pourcentage",
"footnote": "source de données de usdsat.com, adaptée pour EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Dáta", "date": "Dáta",
"price": "Praghas", "price": "Praghas",
"percentchange": "Athrú Céatadáin", "percentchange": "Athrú Céatadáin",
"footnote": "foinse sonraí ó usdsat.com, curtha in oiriúint d'EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Datum", "date": "Datum",
"price": "Cijena", "price": "Cijena",
"percentchange": "Postotna Promjena", "percentchange": "Postotna Promjena",
"footnote": "izvor podataka od usdsat.com, prilagođeno za EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Dátum", "date": "Dátum",
"price": "Ár", "price": "Ár",
"percentchange": "Százalékos Változás", "percentchange": "Százalékos Változás",
"footnote": "adatforrás usdsat.com, adaptálva EUR-ra", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Data", "date": "Data",
"price": "Prezzo", "price": "Prezzo",
"percentchange": "Variazione Percentuale", "percentchange": "Variazione Percentuale",
"footnote": "fonte dati da usdsat.com, adattato per EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Data", "date": "Data",
"price": "Kaina", "price": "Kaina",
"percentchange": "Procentinis Pokytis", "percentchange": "Procentinis Pokytis",
"footnote": "duomenų šaltinis iš usdsat.com, pritaikytas EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Datums", "date": "Datums",
"price": "Cena", "price": "Cena",
"percentchange": "Procentuālā Izmaiņa", "percentchange": "Procentuālā Izmaiņa",
"footnote": "datu avots no usdsat.com, pielāgots EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Data", "date": "Data",
"price": "Prezz", "price": "Prezz",
"percentchange": "Bidla Perċentwali", "percentchange": "Bidla Perċentwali",
"footnote": "sors tad-dejta minn usdsat.com, adattat għal EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Datum", "date": "Datum",
"price": "Prijs", "price": "Prijs",
"percentchange": "Procentuele Verandering", "percentchange": "Procentuele Verandering",
"footnote": "gegevensbron van usdsat.com, aangepast voor EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Data", "date": "Data",
"price": "Cena", "price": "Cena",
"percentchange": "Zmiana Procentowa", "percentchange": "Zmiana Procentowa",
"footnote": "źródło danych z usdsat.com, dostosowane dla EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Data", "date": "Data",
"price": "Preço", "price": "Preço",
"percentchange": "Variação Percentual", "percentchange": "Variação Percentual",
"footnote": "fonte de dados de usdsat.com, adaptado para EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Data", "date": "Data",
"price": "Preț", "price": "Preț",
"percentchange": "Schimbare Procentuală", "percentchange": "Schimbare Procentuală",
"footnote": "sursa de date de la usdsat.com, adaptată pentru EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Dátum", "date": "Dátum",
"price": "Cena", "price": "Cena",
"percentchange": "Percentuálna Zmena", "percentchange": "Percentuálna Zmena",
"footnote": "zdroj údajov z usdsat.com, prispôsobené pre EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Datum", "date": "Datum",
"price": "Cena", "price": "Cena",
"percentchange": "Odstotna Sprememba", "percentchange": "Odstotna Sprememba",
"footnote": "vir podatkov iz usdsat.com, prilagojen za EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -14,10 +14,9 @@
"date": "Datum", "date": "Datum",
"price": "Pris", "price": "Pris",
"percentchange": "Procentuell Förändring", "percentchange": "Procentuell Förändring",
"footnote": "datakälla från usdsat.com, anpassad för EUR", "footnote": "",
"data_file": "historical", "data_file": "historical",
"rate_field": "sateur_rate", "rate_field": "sateur_rate",
"exchange_rate": "0.92",
"lang1_link": "/en-eur/", "lang1_link": "/en-eur/",
"lang1": "English", "lang1": "English",
"lang2_link": "/de/", "lang2_link": "/de/",

View File

@@ -4,7 +4,11 @@
"description": "EUR/Sats historical chart - Deploy express js to vercel.", "description": "EUR/Sats historical chart - Deploy express js to vercel.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start": "node index.js" "start": "node index.js",
"dev": "node index.js",
"port8080": "PORT=8080 node index.js",
"port5000": "PORT=5000 node index.js",
"port8000": "PORT=8000 node index.js"
}, },
"engines": { "engines": {
"node": ">=22" "node": ">=22"

File diff suppressed because one or more lines are too long

View File

@@ -12,7 +12,18 @@
<script src="/static/chart.min.js"></script> <script src="/static/chart.min.js"></script>
<script src="/static/chartjs-adapter-date-fns.min.js"></script> <script src="/static/chartjs-adapter-date-fns.min.js"></script>
<script src="/static/chartjs-plugin-annotation.min.js"></script> <script src="/static/chartjs-plugin-annotation.min.js"></script>
<script async src="https://analytics.umami.is/script.js" data-website-id="d35ba036-3531-422c-be04-74711c97799c"></script> <script>
// Auto-detect domain for Plausible Analytics
document.addEventListener('DOMContentLoaded', function() {
const domain = window.location.hostname;
const script = document.createElement('script');
script.async = true;
script.defer = true;
script.setAttribute('data-domain', domain);
script.src = 'https://your-plausible-instance.com/js/script.js';
document.head.appendChild(script);
});
</script>
<!-- JavaScript Bundle with Popper --> <!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-p34f1UUtsS3wqzfto5wAAmdvj+osOnFyQFpp4Ua3gs/ZVWx6oOypYoCJhGGScy+8" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-p34f1UUtsS3wqzfto5wAAmdvj+osOnFyQFpp4Ua3gs/ZVWx6oOypYoCJhGGScy+8" crossorigin="anonymous"></script>
<style> <style>
@@ -25,42 +36,7 @@
<body> <body>
<header class="p-1 bg-dark text-white"> <div class="container" style="margin-top: 20px;">
<nav class="navbar navbar-expand-lg navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="http://bitcoin.org.hk">
<img src="/static/bahk-logo-big-white.svg" alt="Bitcoin HK Logo" width="60">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="true" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active px-2 text-secondary" aria-current="page" href="http://sats.bitcoin.org.hk">Sats</a>
</li>
<li class="nav-item">
<a class="nav-link px-2 text-white" href="http://blocks.bitcoin.org.hk">Blocks</a>
</li>
<li class="nav-item">
<a class="nav-link px-2 text-white" href="https://rates.bitcoin.org.hk">Rates</a>
</li>
<li class="nav-item">
<a class="nav-link px-2 text-white" href="http://stack.bitcoin.org.hk/">Stack</a>
</li>
<li class="nav-item">
<a class="nav-link px-2 text-white" href="https://laisee.org">Laisee</a>
</li>
</ul>
<span class="navbar-item" style="color: #fff">
<a class="px-2" href="{{ lang1_link }}" style="color: rgb(6, 168, 231)"> {{ lang1 }} </a>{{#if lang2}} | <a class="px-2" href="{{ lang2_link }}" style="color: rgb(6, 168, 231)"> {{ lang2 }}</a>{{/if}}{{#if lang3}} | <a class="px-2" href="{{ lang3_link }}" style="color: rgb(6, 168, 231)"> {{ lang3 }}</a>{{/if}}{{#if lang4}} | <a class="px-2" href="{{ lang4_link }}" style="color: rgb(6, 168, 231)"> {{ lang4 }}</a>{{/if}}{{#if lang5}} | <a class="px-2" href="{{ lang5_link }}" style="color: rgb(6, 168, 231)"> {{ lang5 }}</a>{{/if}}{{#if lang6}} | <a class="px-2" href="{{ lang6_link }}" style="color: rgb(6, 168, 231)"> {{ lang6 }}</a>{{/if}}{{#if lang7}} | <a class="px-2" href="{{ lang7_link }}" style="color: rgb(6, 168, 231)"> {{ lang7 }}</a>{{/if}}
</span>
</div>
</div>
</nav>
</header>
<div class="container" style="margin-top: 40px;">
<div class="row"> <div class="row">
<center> <center>
<h3> {{ Title }} <span id="current"></span> sats</h3> <h3> {{ Title }} <span id="current"></span> sats</h3>
@@ -77,12 +53,12 @@
t = new WebSocket("wss://api-pub.bitfinex.com/ws/2"); t = new WebSocket("wss://api-pub.bitfinex.com/ws/2");
t.onmessage = function(e) { t.onmessage = function(e) {
var i = JSON.parse(e.data); var msg = JSON.parse(e.data);
if (i.event === 'subscribed' && i.channel == 'ticker') { if (msg.event === 'subscribed' && msg.channel == 'ticker') {
ws_ticker_id = i.chanId; ws_ticker_id = msg.chanId;
} }
if (ws_ticker_id == i[0]) { if (Array.isArray(msg) && msg[0] === ws_ticker_id && Array.isArray(msg[1])) {
updatePrice(i); updatePrice(msg[1]);
} }
} }
@@ -91,7 +67,7 @@
t.send(JSON.stringify({ t.send(JSON.stringify({
"event": "subscribe", "event": "subscribe",
"channel": "ticker", "channel": "ticker",
"symbol": "BTCUSD" "symbol": "tBTCEUR"
})); }));
setPingTimer(); setPingTimer();
} }
@@ -114,18 +90,12 @@
}, 10000); }, 10000);
} }
function updatePrice(i) { function updatePrice(tickerArray) {
if (Array.isArray(i)) { // Bitfinex ticker format: [ BID, BID_SIZE, ASK, ASK_SIZE, DAILY_CHANGE, DAILY_CHANGE_PERC, LAST_PRICE, VOLUME, HIGH, LOW ]
i.forEach(function(item) { var lastPriceEur = tickerArray[6];
if (Array.isArray(item)) { currentPrice = Math.round(100000000 / lastPriceEur); // sats per EUR
var btc_price = item[0]; document.title = currentPrice.toLocaleString() + " sats";
currentPrice = Math.round((1 / btc_price) * 100000000 / {{ exchange_rate }}); // satoshis per currency unit document.querySelector('#current').textContent = currentPrice.toLocaleString();
document.title = currentPrice.toLocaleString() + " sats";
document.querySelector('#current').textContent = currentPrice.toLocaleString();
}
});
}
} }
</script> </script>
@@ -155,10 +125,7 @@
</table> </table>
<p style="font-size: small;"> </div>
* {{ footnote }}
</p>
</div>
<script> <script>
// Load data and initialize chart // Load data and initialize chart
fetch('/{{ data_file }}') fetch('/{{ data_file }}')
@@ -176,9 +143,9 @@
const minValue = Math.min(...values); const minValue = Math.min(...values);
const maxValue = Math.max(...values); const maxValue = Math.max(...values);
// Add padding for logarithmic scale (multiply/divide by factor) // Add more padding for better visualization, especially at bottom
const yAxisMin = Math.floor(minValue / 2); const yAxisMin = Math.floor(minValue / 50); // Much more padding at bottom
const yAxisMax = Math.ceil(maxValue * 2); const yAxisMax = Math.ceil(maxValue * 2.5); // Less padding at top for flatter look
// Calculate responsive height // Calculate responsive height
const windowWidth = window.innerWidth; const windowWidth = window.innerWidth;
@@ -197,10 +164,6 @@
const qeLink = () => window.open('https://en.wikipedia.org/wiki/Quantitative_easing', '_blank'); const qeLink = () => window.open('https://en.wikipedia.org/wiki/Quantitative_easing', '_blank');
const markers = [{ const markers = [{
date: new Date('2008-11-25T00:00:00.000Z'),
label: 'QE1',
click: qeLink,
}, {
date: new Date('2010-11-03T00:00:00.000Z'), date: new Date('2010-11-03T00:00:00.000Z'),
label: 'QE2', label: 'QE2',
click: qeLink, click: qeLink,