Added details of data update times

Added details of data update times
This commit is contained in:
2026-07-17 10:10:46 +00:00
parent e4707b7fd7
commit e71051d869

View File

@@ -117,8 +117,7 @@ tbody tr:hover{background:color-mix(in srgb,var(--accent-soft) 50%,transparent)}
.num{font-family:var(--mono);font-variant-numeric:tabular-nums} .num{font-family:var(--mono);font-variant-numeric:tabular-nums}
.score{font-family:var(--display);font-weight:600;font-size:15px} .score{font-family:var(--display);font-weight:600;font-size:15px}
.add-grid{display:grid;grid-template-columns:1.3fr 1fr;gap:24px;margin:40px 0;align-items:stretch} .add-grid{display:grid;grid-template-columns:1.3fr 1fr;gap:24px;margin:40px 0;align-items:start}
.add-grid>.panel{display:flex;flex-direction:column}
.panel{ .panel{
background:var(--panel);border:1px solid var(--line); background:var(--panel);border:1px solid var(--line);
border-radius:var(--radius);padding:24px;box-shadow:var(--shadow); border-radius:var(--radius);padding:24px;box-shadow:var(--shadow);
@@ -140,6 +139,12 @@ tbody tr:hover{background:color-mix(in srgb,var(--accent-soft) 50%,transparent)}
.btn:disabled{opacity:.45;cursor:not-allowed;filter:none} .btn:disabled{opacity:.45;cursor:not-allowed;filter:none}
.note{font-size:13px;color:var(--muted);margin-top:16px;line-height:1.55} .note{font-size:13px;color:var(--muted);margin-top:16px;line-height:1.55}
.note strong{color:var(--ink)} .note strong{color:var(--ink)}
.freshness-note{
font-size:12px;line-height:1.4;color:var(--muted);
background:var(--accent-soft);border:1px solid var(--line);border-radius:8px;
padding:7px 12px;margin:0 0 12px;
}
.freshness-note strong{color:var(--ink)}
.btn-share{ .btn-share{
display:block;margin:0 auto 8px;font:inherit;font-size:13px;cursor:pointer; display:block;margin:0 auto 8px;font:inherit;font-size:13px;cursor:pointer;
padding:8px 16px;border-radius:8px;border:1px solid var(--line-strong); padding:8px 16px;border-radius:8px;border:1px solid var(--line-strong);
@@ -259,6 +264,13 @@ footer a{color:var(--accent);text-decoration:none}
<a class="btn-ghost" id="download" href="#" download="willexecutors.json">↓ JSON</a> <a class="btn-ghost" id="download" href="#" download="willexecutors.json">↓ JSON</a>
</div> </div>
<!-- Data-freshness note: server-reported fields (fee/info/version) refresh
once a day on a per-server timer, while Bitcoin deposits (and therefore
listing/renewal) are picked up as soon as they reach 3 confirmations. -->
<p class="freshness-note">
<strong>Fee/description/version</strong> refresh about once a day (timing varies). <strong>Deposits</strong> are credited instantly after 3 confirmations (~30 min).
</p>
<div class="table-card"> <div class="table-card">
<table id="tbl"> <table id="tbl">
<thead> <thead>
@@ -287,7 +299,7 @@ footer a{color:var(--accent);text-decoration:none}
<div class="add-grid"> <div class="add-grid">
<div class="panel"> <div class="panel">
<h2>Add your Will Executor</h2> <h2>Add your Will Executor</h2>
<p class="lead">Enter your server URL. It will appear in the list once your deposit is confirmed (typically about 30 minutes).</p> <p class="lead">Enter your server URL. It will be checked online before it appears in the list.</p>
<div class="form-row"> <div class="form-row">
<input type="text" id="url" placeholder="https://we.bitcoin-after.life"> <input type="text" id="url" placeholder="https://we.bitcoin-after.life">
</div> </div>
@@ -301,7 +313,7 @@ footer a{color:var(--accent);text-decoration:none}
<div class="terms-box" id="terms-box"> <div class="terms-box" id="terms-box">
<p class="lead">You are about to add this server:</p> <p class="lead">You are about to add this server:</p>
<p><a id="terms-url" href="#" target="_blank" rel="noopener" class="mono"></a></p> <p><a id="terms-url" href="#" target="_blank" rel="noopener" class="mono"></a></p>
<p style="font-size:13px;margin-top:4px"><strong>Make sure the link above works correctly before paying. No refunds after payment. URL changes require proof of ownership — see the <a href="/terms.html" target="_blank">Terms</a>.</strong></p> <p style="font-size:13px;margin-top:4px"><strong>Make sure the link above works correctly before paying. No refunds or URL changes after payment.</strong></p>
<p style="font-size:14px"> <p style="font-size:14px">
<label> <label>
<input type="checkbox" id="terms-check"> <input type="checkbox" id="terms-check">
@@ -320,7 +332,7 @@ footer a{color:var(--accent);text-decoration:none}
<div class="row"><span>Contact</span><span id="iv-contact"></span></div> <div class="row"><span>Contact</span><span id="iv-contact"></span></div>
<div class="row"><span>Server</span><span id="iv-url"></span></div> <div class="row"><span>Server</span><span id="iv-url"></span></div>
<div class="row"><span>Will Executor</span><span><a id="iv-weinfo" href="#" target="_blank"></a></span></div> <div class="row"><span>Will Executor</span><span><a id="iv-weinfo" href="#" target="_blank"></a></span></div>
<div class="row" id="iv-nextdep-row" style="display:none"><span>Next renewal</span><span id="iv-nextdep"></span></div> <div class="row" id="iv-nextdep-row" style="display:none"><span>Next deposit</span><span id="iv-nextdep"></span></div>
<div id="qrcode"></div> <div id="qrcode"></div>
<button class="btn-share" id="share-btn">Share invoice</button> <button class="btn-share" id="share-btn">Share invoice</button>
<p class="note"> <p class="note">
@@ -332,11 +344,10 @@ footer a{color:var(--accent);text-decoration:none}
<div class="panel"> <div class="panel">
<h2>How ranking works</h2> <h2>How ranking works</h2>
<p class="lead">Ordered by excess donated, then total paid, then base fee (lower first), then WeTime points.</p> <p class="lead">Bid-based ranking: higher contributions rank higher.</p>
<div style="display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--line);font-size:13px"><span style="color:var(--muted)">Yearly fee</span><b class="mono"><span id="thr-min">50,000</span> sats</b></div> <div style="display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--line);font-size:13px"><span style="color:var(--muted)">Deposit threshold</span><b class="mono"><span id="thr-min">50,000</span> sats</b></div>
<div style="display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--line);font-size:13px"><span style="color:var(--muted)">Listing period</span><b>365 days</b></div> <div style="display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--line);font-size:13px"><span style="color:var(--muted)">Plugin integration</span><b>automatic</b></div>
<div style="display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--line);font-size:13px"><span style="color:var(--muted)">Renewal window</span><b>from 6 months before expiry</b></div> <div style="display:flex;justify-content:space-between;padding:8px 0;font-size:13px"><span style="color:var(--muted)">Early-adopter guarantee</span><b>12 months</b></div>
<div style="display:flex;justify-content:space-between;padding:8px 0;font-size:13px"><span style="color:var(--muted)">Plugin integration</span><b>automatic</b></div>
</div> </div>
</div> </div>
@@ -351,13 +362,13 @@ footer a{color:var(--accent);text-decoration:none}
<div class="info-block"> <div class="info-block">
<span class="ic">02</span> <span class="ic">02</span>
<h3>Ranking System</h3> <h3>Ranking System</h3>
<p>This leaderboard is ordered by excess donated (over the yearly fee), then total amount paid, then lower base fee, then WeTime points.</p> <p>This leaderboard operates on a bid-based ranking system where higher contributions result in better positioning.</p>
</div> </div>
<div class="info-block"> <div class="info-block">
<span class="ic">03</span> <span class="ic">03</span>
<h3>Listing &amp; Renewal</h3> <h3>Early Adopter Incentives</h3>
<p>A flat yearly fee buys 365 days of presence in the list, starting when your payment reaches 3 confirmations. You can renew for one additional year at any time from 6 months before expiry; listings that are not renewed are removed at expiry. See the <a href="/terms.html" target="_blank">Terms</a> for details.</p> <p>To support the project's initial launch phase, we plan to maintain the first Will Executor servers for a minimum of 12 months, rewarding early participants. Subsequently, premium positions will be available through an auction system based on protocol revenue generation.</p>
</div> </div>
<div class="info-block"> <div class="info-block">
@@ -374,7 +385,6 @@ footer a{color:var(--accent);text-decoration:none}
<div class="wrap"> <div class="wrap">
<span>Bitcoin After Life — Will Executor List</span> <span>Bitcoin After Life — Will Executor List</span>
<a href="mailto:welist@bitcoin-after.life">welist@bitcoin-after.life</a> <a href="mailto:welist@bitcoin-after.life">welist@bitcoin-after.life</a>
<a href="/terms.html">Terms</a>
<a class="mono" id="commit-link" href="https://bitcoin-after.life/gitea/bitcoinafterlife/bal-welist-website/commit/COMMIT_HASH_PLACEHOLDER">COMMIT_HASH_PLACEHOLDER</a> <a class="mono" id="commit-link" href="https://bitcoin-after.life/gitea/bitcoinafterlife/bal-welist-website/commit/COMMIT_HASH_PLACEHOLDER">COMMIT_HASH_PLACEHOLDER</a>
</div> </div>
</footer> </footer>
@@ -387,6 +397,18 @@ let minAmount = 50000;
const fmt = n => (n != null ? Number(n).toLocaleString('en-US') : '—'); const fmt = n => (n != null ? Number(n).toLocaleString('en-US') : '—');
const trunc = (s, m=40) => s && s.length > m ? s.slice(0, m) + '…' : s; const trunc = (s, m=40) => s && s.length > m ? s.slice(0, m) + '…' : s;
const statusMap = {
'OK': 'Health check passed',
'TIMEOUT': 'Connection timeout',
'CONNECTION': 'Connection error',
'STATUS': 'HTTP error',
'WRONG REPLY': 'Invalid JSON response',
'REQUEST': 'Request error',
'BODY': 'Body read error',
'DECODE': 'Decode error',
'KO': 'Generic error'
};
function getChain() { function getChain() {
const btn = document.querySelector('#chainSeg [aria-pressed="true"]'); const btn = document.querySelector('#chainSeg [aria-pressed="true"]');
return btn ? btn.dataset.c : 'bitcoin'; return btn ? btn.dataset.c : 'bitcoin';
@@ -394,7 +416,9 @@ function getChain() {
function getFiltered() { function getFiltered() {
return allServers return allServers
.filter(d => (d.url + " " + (d.info||"")).toLowerCase().includes(q.toLowerCase())); .filter(d => withTor ? true : !d.onion)
.filter(d => (d.url + " " + (d.info||"")).toLowerCase().includes(q.toLowerCase()))
.sort((a, b) => (b.last_block||0) - (a.last_block||0) || (b.points||0) - (a.points||0) || (b.count_win||0) - (a.count_win||0) || (a.base_fee||0) - (b.base_fee||0) || (b.version||'').localeCompare(a.version||''));
} }
function render() { function render() {
@@ -438,12 +462,11 @@ function render() {
</div>`); </div>`);
}); });
const online = allServers.filter(d => d.status === "OK").length; const online = allServers.filter(d => d.status === "online" || d.status === "OK").length;
document.getElementById('s-online').textContent = online; document.getElementById('s-online').textContent = online;
document.getElementById('s-total').textContent = allServers.length; document.getElementById('s-total').textContent = allServers.length;
// Highest known block across all servers (the list is ranked by fee/points, not by height) const top = getFiltered()[0];
const maxBlock = allServers.reduce((m, d) => Math.max(m, d.last_block || 0), 0); document.getElementById('s-block').textContent = top ? fmt(top.last_block) : '—';
document.getElementById('s-block').textContent = maxBlock ? fmt(maxBlock) : '—';
} }
async function fetchData() { async function fetchData() {
@@ -569,7 +592,7 @@ document.getElementById('terms-accept').addEventListener('click', async function
const balStr = result.balance != null ? fmt(result.balance) : null; const balStr = result.balance != null ? fmt(result.balance) : null;
const uncStr = result.unconfirmed_balance != null ? fmt(result.unconfirmed_balance) : null; const uncStr = result.unconfirmed_balance != null ? fmt(result.unconfirmed_balance) : null;
document.getElementById('iv-balance').textContent = balStr ? (uncStr ? balStr + ' (' + uncStr + ')' : balStr) : '—'; document.getElementById('iv-balance').textContent = balStr ? (uncStr ? balStr + ' (' + uncStr + ')' : balStr) : '—';
document.getElementById('iv-donations').textContent = result.donation != null ? fmt(result.donation) : '—'; document.getElementById('iv-donations').textContent = result.donations != null ? fmt(result.donations) : '—';
document.getElementById('iv-contact').textContent = document.getElementById('contact').value.trim() || '—'; document.getElementById('iv-contact').textContent = document.getElementById('contact').value.trim() || '—';
const weLink = result.id ? `/weinfo/${result.chain || chain}/${result.id}` : null; const weLink = result.id ? `/weinfo/${result.chain || chain}/${result.id}` : null;
const weinfoEl = document.getElementById('iv-weinfo'); const weinfoEl = document.getElementById('iv-weinfo');
@@ -590,13 +613,13 @@ document.getElementById('terms-accept').addEventListener('click', async function
document.getElementById('iv-nextdep').textContent = result.next_deposit_date || '—'; document.getElementById('iv-nextdep').textContent = result.next_deposit_date || '—';
document.getElementById('iv-nextdep-row').style.display = 'flex'; document.getElementById('iv-nextdep-row').style.display = 'flex';
document.getElementById('iv-status').className = 'ok-line'; document.getElementById('iv-status').className = 'ok-line';
document.getElementById('iv-status').textContent = 'Server is already listed. Next renewal: ' + (result.next_deposit_date || '—'); document.getElementById('iv-status').textContent = 'Server is already listed. Next deposit: ' + (result.next_deposit_date || '—');
const inv = document.getElementById('invoice'); const inv = document.getElementById('invoice');
inv.classList.add('show'); inv.classList.add('show');
inv.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); inv.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
return; return;
} }
const amountSats = result.min_amount != null ? result.min_amount : minAmount; const amountSats = result.amount != null ? result.amount : minAmount;
const amountBtc = (amountSats / 1e8).toFixed(8).replace(/\.?0+$/, ''); const amountBtc = (amountSats / 1e8).toFixed(8).replace(/\.?0+$/, '');
const invoiceuri = `bitcoin:${result.address}?amount=${amountBtc}&label=BAL&message=Order+For+url+%26+${encodeURIComponent(url)}`; const invoiceuri = `bitcoin:${result.address}?amount=${amountBtc}&label=BAL&message=Order+For+url+%26+${encodeURIComponent(url)}`;
const qrEl = document.getElementById('qrcode'); const qrEl = document.getElementById('qrcode');
@@ -626,7 +649,7 @@ document.getElementById('terms-accept').addEventListener('click', async function
} }
}; };
document.getElementById('iv-status').className = 'ok-line'; document.getElementById('iv-status').className = 'ok-line';
document.getElementById('iv-status').textContent = '✓ Server verified: ' + serverUrl + '. Pay the invoice — it will be listed after 3 confirmations.'; document.getElementById('iv-status').textContent = '✓ Server added: ' + serverUrl + '. Pay the invoice to complete.';
const inv = document.getElementById('invoice'); const inv = document.getElementById('invoice');
inv.classList.add('show'); inv.classList.add('show');
inv.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); inv.scrollIntoView({ behavior: 'smooth', block: 'nearest' });