forked from bitcoinafterlife/bal-welist-website
Compare commits
1 Commits
f9ffc383a0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0ab7b458a4 |
153
README.md
153
README.md
@@ -1,153 +1,2 @@
|
|||||||
# Server Status: Complete Explanation and Reference Guide
|
welist html
|
||||||
|
|
||||||
This page explains all the **Will Executor server health statuses** used throughout the BAL Web Interface. Each status type provides critical information about server operation, health checks, and potential issues for administrators monitoring the Bitcoin After Life network.
|
|
||||||
|
|
||||||
## Status Code Overview
|
|
||||||
|
|
||||||
| Status | Description | When It Occurs |
|
|
||||||
|--------|-------------|----------------|
|
|
||||||
| `OK` | Health check passed | Server is online, functioning normally |
|
|
||||||
| `TIMEOUT: <message>` | Connection timeout | Server response took too long |
|
|
||||||
| `CONNECTION: <message>` | Connection error | Network connectivity issues |
|
|
||||||
| `STATUS: <code>` | HTTP error (from server) | Server returned non-200 status |
|
|
||||||
| `WRONG REPLY: <message>` | Invalid JSON response | Server response couldn't be parsed |
|
|
||||||
| `REQUEST: <message>` | Request error | Client-side request failed |
|
|
||||||
| `BODY: <message>` | Body read error | Failed to read response body |
|
|
||||||
| `DECODE: <message>` | Decode error | Failed to decode response content |
|
|
||||||
| `KO` | Generic error | Unknown or unspecified error |
|
|
||||||
|
|
||||||
## Status Types Explained
|
|
||||||
|
|
||||||
### 🟢 Good Statuses
|
|
||||||
**`OK`** - Everything is functioning correctly:
|
|
||||||
- Server is online and responding
|
|
||||||
- Health check completed successfully
|
|
||||||
- Ready for new registration/processing
|
|
||||||
|
|
||||||
### 🟡 Warning/Moderate Issues
|
|
||||||
**`TIMEOUT: <message>`** - Connection timed out:
|
|
||||||
- Server took too than expected to respond
|
|
||||||
- Could indicate server overload or network issues
|
|
||||||
- Requires attention but server may still be functional
|
|
||||||
|
|
||||||
**`CONNECTION: <message>`** - Connection error:
|
|
||||||
- Network connectivity problems
|
|
||||||
- Server might be reachable but cannot communicate
|
|
||||||
- Potential infrastructure or configuration issue
|
|
||||||
|
|
||||||
**`STATUS: <code>`** - HTTP error:
|
|
||||||
- Server responded with an error code (4xx or 5xx)
|
|
||||||
- Could indicate misconfiguration, maintenance, or issues |
|
|
||||||
- Different error codes mean different things
|
|
||||||
|
|
||||||
### 🔴 Critical Issues
|
|
||||||
**`WRONG REPLY`** - Invalid JSON response:
|
|
||||||
- Server response format is incorrect
|
|
||||||
- May indicate server software bug or corruption
|
|
||||||
- Prevents proper data processing
|
|
||||||
|
|
||||||
**`REQUEST`** - Request error:
|
|
||||||
- Client request failed
|
|
||||||
- Network or protocol issue
|
|
||||||
- Server may be unreachable
|
|
||||||
|
|
||||||
**`BODY`** - Body read error:
|
|
||||||
- Failed to read response body after successful connection
|
|
||||||
- Could indicate server processing issues
|
|
||||||
- Data corruption or transmission problems
|
|
||||||
|
|
||||||
**`DECODE`** - Decode error:
|
|
||||||
- Failed to decode response content
|
|
||||||
- Encoding mismatch or corrupted data
|
|
||||||
- Prevents proper data interpretation
|
|
||||||
|
|
||||||
**`KO`** - Generic error:
|
|
||||||
- Unknown or unspecified error
|
|
||||||
- Fallback for all other unidentified issues
|
|
||||||
- Indicates something went wrong but exact cause unknown
|
|
||||||
|
|
||||||
## Example Status Messages
|
|
||||||
|
|
||||||
### Normal Operations
|
|
||||||
```
|
|
||||||
Status: OK
|
|
||||||
Meaning: Health check passed
|
|
||||||
Display: Server is healthy and ready
|
|
||||||
```
|
|
||||||
|
|
||||||
### Network/Time Issues
|
|
||||||
```
|
|
||||||
Status: TIMEOUT: Connection timed out after 30 seconds
|
|
||||||
Meaning: Server took too long to respond
|
|
||||||
Display: "Connection timeout (Connection timed out after 30 seconds)"
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTTP Errors
|
|
||||||
```
|
|
||||||
Status: STATUS: 500
|
|
||||||
Meaning: Server returned HTTP 500 Internal Server Error
|
|
||||||
Display: "HTTP error (HTTP error)"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Response Processing Issues
|
|
||||||
```
|
|
||||||
Status: WRONG REPLY: Invalid JSON
|
|
||||||
Meaning: Server response could not be parsed as JSON
|
|
||||||
Display: "Invalid JSON response (Invalid JSON)"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Practical Usage Guide
|
|
||||||
|
|
||||||
### For Server Administrators
|
|
||||||
- **OK**: Check server resources and logs if needed
|
|
||||||
- **TIMEOUT/CONNECTION**: Check server network connectivity
|
|
||||||
- **STATUS**: Review server logs and restart if needed
|
|
||||||
- **WRONG REPLY/DECODE/REQUEST**: Investigate server software issues
|
|
||||||
- **KO**: Review server errors and restart
|
|
||||||
|
|
||||||
### For Users
|
|
||||||
- **OK**: Server is working correctly
|
|
||||||
- **TIMEOUT/CONNECTION**: Temporary issue, try again later
|
|
||||||
- **STATUS**: Server may be down for maintenance
|
|
||||||
- **Other errors**: Server issue, contact support if persistent
|
|
||||||
|
|
||||||
## Monitoring Tips
|
|
||||||
|
|
||||||
1. **Continuous Monitoring**: Regular checks of status codes help detect issues early
|
|
||||||
2. **Alert Setup**: Configure alerts for non-OK statuses
|
|
||||||
3. **Log Analysis**: Correlate status codes with server logs
|
|
||||||
4. **Capacity Planning**: Address persistent timeouts/connections with infrastructure improvements
|
|
||||||
|
|
||||||
## Status Processing Logic
|
|
||||||
|
|
||||||
### Status Code Processing
|
|
||||||
```javascript
|
|
||||||
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'
|
|
||||||
};
|
|
||||||
|
|
||||||
// Extract base status from status message
|
|
||||||
const st = (data.status||'').split(':')[0];
|
|
||||||
|
|
||||||
// Display only the description (e.g., "Connection timeout" instead of "TIMEOUT: Connection timeout")
|
|
||||||
statusDisplay = statusMap[st] || '—';
|
|
||||||
```
|
|
||||||
|
|
||||||
## Related Documentation
|
|
||||||
|
|
||||||
For more details on server setup, monitoring, and troubleshooting, refer to:
|
|
||||||
- [Server Administration Guide](./administration)
|
|
||||||
- [Status Monitoring Setup](./monitoring-setup)
|
|
||||||
- [Error Resolution Handbook](./error-resolve)
|
|
||||||
|
|
||||||
## Additional Information
|
|
||||||
|
|
||||||
This status system provides a clear, human-readable way to understand server health at a glance, making it easier for administrators to quickly identify and respond to issues.
|
|
||||||
111
index.html
111
index.html
@@ -139,11 +139,6 @@ 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)}
|
||||||
.btn-share{
|
|
||||||
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);
|
|
||||||
background:var(--panel);color:var(--accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.invoice{display:none}
|
.invoice{display:none}
|
||||||
.invoice.show{display:block}
|
.invoice.show{display:block}
|
||||||
@@ -151,18 +146,8 @@ tbody tr:hover{background:color-mix(in srgb,var(--accent-soft) 50%,transparent)}
|
|||||||
.invoice .row:last-child{border-bottom:0}
|
.invoice .row:last-child{border-bottom:0}
|
||||||
.invoice .row span:first-child{color:var(--muted)}
|
.invoice .row span:first-child{color:var(--muted)}
|
||||||
.invoice .row span:last-child{font-family:var(--mono);text-align:right;word-break:break-all}
|
.invoice .row span:last-child{font-family:var(--mono);text-align:right;word-break:break-all}
|
||||||
.invoice .row a{color:var(--accent);text-decoration:none}
|
#qrcode{margin:18px auto 4px;width:160px;height:160px}
|
||||||
.invoice .row a:hover{text-decoration:underline}
|
#qrcode img{width:160px;height:160px}
|
||||||
#qrcode{margin:18px auto 4px;width:160px}
|
|
||||||
#qrcode canvas,#qrcode img{width:160px!important;height:160px!important;max-width:100%}
|
|
||||||
#qr-overlay{
|
|
||||||
display:none;position:fixed;inset:0;z-index:999;
|
|
||||||
background:rgba(0,0,0,.7);cursor:pointer;
|
|
||||||
align-items:center;justify-content:center;
|
|
||||||
}
|
|
||||||
#qr-overlay.show{display:flex}
|
|
||||||
#qr-big{padding:24px;background:#fff;border-radius:12px}
|
|
||||||
#qr-big canvas,#qr-big img{width:280px!important;height:280px!important;max-width:90vw}
|
|
||||||
.ok-line{color:var(--ok);font-weight:600;font-size:14px;margin-bottom:14px}
|
.ok-line{color:var(--ok);font-weight:600;font-size:14px;margin-bottom:14px}
|
||||||
.err-line{color:#d32f2f;font-weight:600;font-size:14px;margin-bottom:14px}
|
.err-line{color:#d32f2f;font-weight:600;font-size:14px;margin-bottom:14px}
|
||||||
.terms-box{display:none;margin:16px 0;padding:20px;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius)}
|
.terms-box{display:none;margin:16px 0;padding:20px;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius)}
|
||||||
@@ -267,6 +252,7 @@ footer a{color:var(--accent);text-decoration:none}
|
|||||||
<th>Info</th>
|
<th>Info</th>
|
||||||
<th class="num">Fee</th>
|
<th class="num">Fee</th>
|
||||||
<th>Version</th>
|
<th>Version</th>
|
||||||
|
<th class="num">Balance</th>
|
||||||
<th class="num">Height</th>
|
<th class="num">Height</th>
|
||||||
<th class="num">Wins</th>
|
<th class="num">Wins</th>
|
||||||
<th class="num">Score</th>
|
<th class="num">Score</th>
|
||||||
@@ -288,12 +274,9 @@ footer a{color:var(--accent);text-decoration:none}
|
|||||||
<h2>Add your Will Executor</h2>
|
<h2>Add your Will Executor</h2>
|
||||||
<p class="lead">Enter your server URL. It will be checked online before it appears in the list.</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://bitcoin-after.life:9137">
|
||||||
|
<button class="btn" id="submit">Add server</button>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top:8px">
|
|
||||||
<input type="text" id="contact" placeholder="Email, npub or Telegram (optional)" style="width:100%;font:inherit;font-size:14px;padding:9px 12px;border:1px solid var(--line-strong);border-radius:8px;background:var(--panel);color:var(--ink)">
|
|
||||||
</div>
|
|
||||||
<button class="btn" id="submit" style="margin-top:8px">Add server</button>
|
|
||||||
|
|
||||||
<div class="ok-line" id="iv-status"></div>
|
<div class="ok-line" id="iv-status"></div>
|
||||||
|
|
||||||
@@ -311,21 +294,18 @@ footer a{color:var(--accent);text-decoration:none}
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="invoice" id="invoice">
|
<div class="invoice" id="invoice">
|
||||||
<div class="row"><span>Annual fee</span><span id="iv-min">—</span></div>
|
<div class="row"><span>Minimum amount</span><span id="iv-min">—</span></div>
|
||||||
<div class="row"><span>Chain</span><span id="iv-chain">—</span></div>
|
<div class="row"><span>Chain</span><span id="iv-chain">—</span></div>
|
||||||
<div class="row"><span>Address</span><span id="iv-addr">—</span></div>
|
<div class="row"><span>Address</span><span id="iv-addr">—</span></div>
|
||||||
<div class="row"><span>Balance</span><span id="iv-balance">—</span></div>
|
<div class="row"><span>Balance</span><span id="iv-balance">—</span></div>
|
||||||
<div class="row"><span>Status</span><span id="iv-status">—</span></div>
|
<div class="row"><span>Status</span><span id="iv-status2">—</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 id="qrcode"></div>
|
<div id="qrcode"></div>
|
||||||
<button class="btn-share" id="share-btn">Share invoice</button>
|
|
||||||
<p class="note">
|
|
||||||
<strong>Please make sure your server is online before you attempt to add it.</strong>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p class="note">
|
||||||
|
<strong>Please make sure your server is online before you attempt to add it.</strong>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
@@ -383,18 +363,6 @@ 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';
|
||||||
@@ -404,7 +372,7 @@ function getFiltered() {
|
|||||||
return allServers
|
return allServers
|
||||||
.filter(d => withTor ? true : !d.onion)
|
.filter(d => withTor ? true : !d.onion)
|
||||||
.filter(d => (d.url + " " + (d.info||"")).toLowerCase().includes(q.toLowerCase()))
|
.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||''));
|
.sort((a, b) => (b.balance||0) - (a.balance||0) || (a.base_fee||0) - (b.base_fee||0) || (b.points||0) - (a.points||0));
|
||||||
}
|
}
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
@@ -414,7 +382,7 @@ function render() {
|
|||||||
tb.innerHTML = ""; ml.innerHTML = "";
|
tb.innerHTML = ""; ml.innerHTML = "";
|
||||||
|
|
||||||
if (!list.length) {
|
if (!list.length) {
|
||||||
tb.innerHTML = '<tr><td colspan="8" style="padding:28px;text-align:center;color:var(--muted)">No servers found.</td></tr>';
|
tb.innerHTML = '<tr><td colspan="9" style="padding:28px;text-align:center;color:var(--muted)">No servers found.</td></tr>';
|
||||||
}
|
}
|
||||||
|
|
||||||
list.forEach((d, i) => {
|
list.forEach((d, i) => {
|
||||||
@@ -428,6 +396,7 @@ function render() {
|
|||||||
<td class="info">${DOMPurify.sanitize(d.info||'—')}</td>
|
<td class="info">${DOMPurify.sanitize(d.info||'—')}</td>
|
||||||
<td class="num">${fmt(d.base_fee)}</td>
|
<td class="num">${fmt(d.base_fee)}</td>
|
||||||
<td class="mono">${DOMPurify.sanitize(d.version||'—')}</td>
|
<td class="mono">${DOMPurify.sanitize(d.version||'—')}</td>
|
||||||
|
<td class="num">${fmt(d.balance)}</td>
|
||||||
<td class="num">${fmt(d.last_block)}</td>
|
<td class="num">${fmt(d.last_block)}</td>
|
||||||
<td class="num">${d.count_win != null ? d.count_win : '—'}</td>
|
<td class="num">${d.count_win != null ? d.count_win : '—'}</td>
|
||||||
<td class="num"><span class="score">${fmt(d.points)}</span></td>
|
<td class="num"><span class="score">${fmt(d.points)}</span></td>
|
||||||
@@ -442,6 +411,7 @@ function render() {
|
|||||||
<div><span>Score</span><b>${fmt(d.points)}</b></div>
|
<div><span>Score</span><b>${fmt(d.points)}</b></div>
|
||||||
<div><span>Wins</span><b>${d.count_win != null ? d.count_win : '—'}</b></div>
|
<div><span>Wins</span><b>${d.count_win != null ? d.count_win : '—'}</b></div>
|
||||||
<div><span>Fee</span><b>${fmt(d.base_fee)} sat</b></div>
|
<div><span>Fee</span><b>${fmt(d.base_fee)} sat</b></div>
|
||||||
|
<div><span>Balance</span><b>${fmt(d.balance)}</b></div>
|
||||||
<div><span>Version</span><b>${DOMPurify.sanitize(d.version||'—')}</b></div>
|
<div><span>Version</span><b>${DOMPurify.sanitize(d.version||'—')}</b></div>
|
||||||
<div><span>Height</span><b>${fmt(d.last_block)}</b></div>
|
<div><span>Height</span><b>${fmt(d.last_block)}</b></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -521,14 +491,9 @@ document.getElementById('submit').addEventListener('click', async () => {
|
|||||||
document.getElementById('iv-chain').textContent = '—';
|
document.getElementById('iv-chain').textContent = '—';
|
||||||
document.getElementById('iv-addr').textContent = '—';
|
document.getElementById('iv-addr').textContent = '—';
|
||||||
document.getElementById('iv-balance').textContent = '—';
|
document.getElementById('iv-balance').textContent = '—';
|
||||||
|
document.getElementById('iv-status2').textContent = '—';
|
||||||
document.getElementById('iv-url').textContent = '—';
|
document.getElementById('iv-url').textContent = '—';
|
||||||
document.getElementById('iv-contact').textContent = '—';
|
|
||||||
document.getElementById('iv-weinfo').href = '#';
|
|
||||||
document.getElementById('iv-weinfo').textContent = '—';
|
|
||||||
document.getElementById('qrcode').innerHTML = '';
|
document.getElementById('qrcode').innerHTML = '';
|
||||||
document.getElementById('qrcode').style.cursor = '';
|
|
||||||
document.getElementById('qr-overlay').classList.remove('show');
|
|
||||||
document.getElementById('share-btn').textContent = 'Share invoice';
|
|
||||||
document.getElementById('terms-box').classList.remove('show');
|
document.getElementById('terms-box').classList.remove('show');
|
||||||
document.getElementById('terms-check').checked = false;
|
document.getElementById('terms-check').checked = false;
|
||||||
document.getElementById('terms-accept').disabled = true;
|
document.getElementById('terms-accept').disabled = true;
|
||||||
@@ -537,7 +502,7 @@ document.getElementById('submit').addEventListener('click', async () => {
|
|||||||
const response = await fetch('/data', {
|
const response = await fetch('/data', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ url, chain, contact: document.getElementById('contact').value.trim() || undefined })
|
body: JSON.stringify({ url, chain })
|
||||||
});
|
});
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -549,48 +514,11 @@ document.getElementById('submit').addEventListener('click', async () => {
|
|||||||
document.getElementById('iv-chain').textContent = result.chain || chain;
|
document.getElementById('iv-chain').textContent = result.chain || chain;
|
||||||
document.getElementById('iv-addr').textContent = result.address || '—';
|
document.getElementById('iv-addr').textContent = result.address || '—';
|
||||||
document.getElementById('iv-balance').textContent = result.balance != null ? fmt(result.balance) : '—';
|
document.getElementById('iv-balance').textContent = result.balance != null ? fmt(result.balance) : '—';
|
||||||
const statusVal = result.status || '—';
|
document.getElementById('iv-status2').textContent = result.status || '—';
|
||||||
const st = (statusVal||'').split(':')[0];
|
const invoiceuri = `bitcoin:${result.address}?label=BAL&message=Order+For+url+%26+${encodeURIComponent(url)}`;
|
||||||
document.getElementById('iv-status').textContent = statusMap[st] || '—';
|
|
||||||
document.getElementById('iv-contact').textContent = document.getElementById('contact').value.trim() || '—';
|
|
||||||
const weLink = result.id ? `/weinfo/${result.chain || chain}/${result.id}` : null;
|
|
||||||
const weinfoEl = document.getElementById('iv-weinfo');
|
|
||||||
if (weLink) {
|
|
||||||
weinfoEl.href = weLink;
|
|
||||||
weinfoEl.textContent = 'View page';
|
|
||||||
} else {
|
|
||||||
weinfoEl.href = '#';
|
|
||||||
weinfoEl.textContent = '—';
|
|
||||||
}
|
|
||||||
const amountSats = result.amount != null ? result.amount : minAmount;
|
|
||||||
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 qrEl = document.getElementById('qrcode');
|
const qrEl = document.getElementById('qrcode');
|
||||||
qrEl.innerHTML = '';
|
qrEl.innerHTML = '';
|
||||||
new QRCode(qrEl, { text: invoiceuri, width: 160, height: 160 });
|
new QRCode(qrEl, invoiceuri);
|
||||||
qrEl.style.cursor = 'pointer';
|
|
||||||
qrEl.onclick = function () {
|
|
||||||
const overlay = document.getElementById('qr-overlay');
|
|
||||||
const big = document.getElementById('qr-big');
|
|
||||||
big.innerHTML = '';
|
|
||||||
new QRCode(big, { text: invoiceuri, width: 280, height: 280 });
|
|
||||||
overlay.classList.add('show');
|
|
||||||
};
|
|
||||||
document.getElementById('qr-overlay').onclick = function () {
|
|
||||||
this.classList.remove('show');
|
|
||||||
};
|
|
||||||
const shareBtn = document.getElementById('share-btn');
|
|
||||||
shareBtn.textContent = 'Share invoice';
|
|
||||||
shareBtn.onclick = function () {
|
|
||||||
if (navigator.share) {
|
|
||||||
navigator.share({ title: 'BAL Invoice', text: invoiceuri });
|
|
||||||
} else {
|
|
||||||
navigator.clipboard.writeText(invoiceuri).then(() => {
|
|
||||||
this.textContent = 'Copied!';
|
|
||||||
setTimeout(() => this.textContent = 'Share invoice', 2000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const serverUrl = result.url || url;
|
const serverUrl = result.url || url;
|
||||||
const infoUrl = serverUrl + '/' + (result.chain || chain) + '/info';
|
const infoUrl = serverUrl + '/' + (result.chain || chain) + '/info';
|
||||||
document.getElementById('iv-url').textContent = serverUrl;
|
document.getElementById('iv-url').textContent = serverUrl;
|
||||||
@@ -628,6 +556,5 @@ document.getElementById('url').addEventListener('keydown', e => {
|
|||||||
fetchMinAmount();
|
fetchMinAmount();
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<div id="qr-overlay"><div id="qr-big"></div></div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
93
weinfo.html
93
weinfo.html
@@ -1,8 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-<|begin▁of▁sentence|>8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-w, initial-scale=1.0" />
|
||||||
<title>Bal Server List</title>
|
<title>Bal Server List</title>
|
||||||
<link rel="icon" href="Logo_nero.ico" type="image/x-icon">
|
<link rel="icon" href="Logo_nero.ico" type="image/x-icon">
|
||||||
<script src="/qrcode.min.js"></script>
|
<script src="/qrcode.min.js"></script>
|
||||||
@@ -11,22 +11,22 @@
|
|||||||
</head>
|
</head>
|
||||||
<style>
|
<style>
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
th, td {
|
th, td {
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
th {
|
th {
|
||||||
background-color: #f2f2f2;
|
background-color: #f2f2f2;
|
||||||
}
|
}
|
||||||
tr:nth-child(even) {
|
tr:nth-child(even) {
|
||||||
background-color: #f9f9f9;
|
background-color: #f9f9f9;
|
||||||
}
|
}
|
||||||
span {
|
span{
|
||||||
margin-left:10px;
|
margin-left:10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -81,53 +81,38 @@
|
|||||||
const chain = path[1];
|
const chain = path[1];
|
||||||
const cdate=new Date().toISOString().replace(/[-:T.Z]/g, '').slice(0, 14);
|
const cdate=new Date().toISOString().replace(/[-:T.Z]/g, '').slice(0, 14);
|
||||||
fetchDataAndPopulateTable('/weinfodata/'+chain+"/"+we_id, new URLSearchParams(),(data) => {
|
fetchDataAndPopulateTable('/weinfodata/'+chain+"/"+we_id, new URLSearchParams(),(data) => {
|
||||||
document.getElementById('wename').innerHTML = DOMPurify.sanitize(data.url||'—');
|
document.getElementById('wename').innerHTML = DOMPurify.sanitize(data.url);
|
||||||
document.getElementById('wechain').innerHTML = DOMPurify.sanitize(data.chain||'—');
|
document.getElementById('wechain').innerHTML = DOMPurify.sanitize(data.chain);
|
||||||
document.getElementById('weinfo').innerHTML = DOMPurify.sanitize(data.info||'—');
|
document.getElementById('weinfo').innerHTML = DOMPurify.sanitize(data.info);
|
||||||
document.getElementById('wefees').innerHTML = data.base_fee != null ? data.base_fee : '—';
|
document.getElementById('wefees').innerHTML = data.base_fee;
|
||||||
document.getElementById('weheight').innerHTML = data.last_block != null ? data.last_block : '—';
|
document.getElementById('weheight').innerHTML = data.last_block;
|
||||||
document.getElementById('wepoints').innerHTML = data.points != null ? data.points : '—';
|
document.getElementById('wepoints').innerHTML = data.points;
|
||||||
document.getElementById('wewin').innerHTML = data.count_win != null ? data.count_win : '—';
|
document.getElementById('wewin').innerHTML = data.count_win;
|
||||||
document.getElementById('wetld').innerHTML = DOMPurify.sanitize(data.tld||'—');
|
document.getElementById('wetld').innerHTML = DOMPurify.sanitize(data.tld);
|
||||||
document.getElementById('webalance').innerHTML = data.balance != null ? data.balance : '—';
|
document.getElementById('webalance').innerHTML = data.balance;
|
||||||
document.getElementById('weversion').innerHTML = data.version||'—';
|
document.getElementById('weversion').innerHTML = data.version;;
|
||||||
const statusMap = {
|
document.getElementById('westatus').innerHTML = DOMPurify.sanitize(data.status);
|
||||||
'OK': 'Health check passed',
|
document.getElementById('weupdate').innerHTML = data.last_update;
|
||||||
'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'
|
|
||||||
};
|
|
||||||
const st = (data.status||'').split(':')[0];
|
|
||||||
document.getElementById('westatus').innerHTML = statusMap[st] || '—';
|
|
||||||
|
|
||||||
const tableBody = document.querySelector('#wetimes tbody');
|
const tableBody = document.querySelector('#wetimes tbody');
|
||||||
tableBody.innerHTML ='';
|
tableBody.innerHTML ='';
|
||||||
if (data.times && data.times.length) {
|
Object.entries(data.times).forEach(([key,wetime]) => {
|
||||||
Object.entries(data.times).forEach(([key,wetime]) => {
|
const row = document.createElement('tr');
|
||||||
const row = document.createElement('tr');
|
const d = new Date(wetime.time/1000);
|
||||||
const d = new Date(wetime.time/1000);
|
row.innerHTML = `
|
||||||
row.innerHTML = `
|
<td>${wetime.blockHeight}</td>
|
||||||
<td>${wetime.blockHeight != null ? wetime.blockHeight : '—'}</td>
|
<td>${DOMPurify.sanitize(wetime.blockHash)}</td>
|
||||||
<td>${DOMPurify.sanitize(wetime.blockHash||'—')}</td>
|
<td>${d}</td>
|
||||||
<td>${d}</td>
|
<td>${wetime.diff/1000000} s</td>
|
||||||
<td>${wetime.diff != null ? wetime.diff/1000000 + ' s' : '—'}</td>
|
<td>${wetime.position+1}</td>
|
||||||
<td>${wetime.position != null ? wetime.position+1 : '—'}</td>
|
<td>${wetime.participants}</td>
|
||||||
<td>${wetime.participants != null ? wetime.participants : '—'}</td>
|
<td>${wetime.points}</td>
|
||||||
<td>${wetime.points != null ? wetime.points : '—'}</td>
|
`;
|
||||||
`;
|
tableBody.appendChild(row);
|
||||||
tableBody.appendChild(row);
|
})
|
||||||
});
|
|
||||||
} else {
|
|
||||||
tableBody.innerHTML = '<tr><td colspan="7" style="padding:20px;text-align:center;color:#999">No rounds yet.</td></tr>';
|
|
||||||
}
|
|
||||||
var prev=0;
|
var prev=0;
|
||||||
var next=0;
|
var next=0;
|
||||||
if (data.times && data.times.length > 0){
|
if (data.times.length > 0){
|
||||||
prev = data.times[0].blockHeight+data.times.length;
|
prev = data.times[0].blockHeight+data.times.length;
|
||||||
next = data.times[data.times.length-1].blockHeight;
|
next = data.times[data.times.length-1].blockHeight;
|
||||||
if (prev < 0 ){
|
if (prev < 0 ){
|
||||||
@@ -141,6 +126,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
getWeInfo();
|
getWeInfo();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user