Skip to content

Commit 15ba15f

Browse files
committed
Merge opentimestamps#36: Switch to mustache for the template & add latest transactions
7c86bc1 added fees in the last week (Vincent Cloutier) 0c0c7d5 updated formula to only use the last week for the average (Vincent Cloutier) 9985a01 added average time between transactions (Vincent Cloutier) 1509975 fix typo in version (Vincent Cloutier) 3fb2715 moved back to inline template (Vincent Cloutier) 3ef9bc5 added latest transactions (Vincent Cloutier) 89a1a24 switched to mustache for templating (Vincent Cloutier) Pull request description: This refactors the current html in rpc.py into it's own file using [mustache](https://mustache.github.io/). This should make things much simpler to get a fancy dashboard with a lot of stats. I've also added a section with the latest timestamping transactions. Using mustache for lists is so much simpler than the built-in format(). Let me know if I should change anything for style/structure/logic/typos. Tree-SHA512: 5adc99f39295b83bd139deea326fcecaed5a2b0bbace649ea2ec3af60e338a0744aebb9f21cbffc4c686a65143f41fecd01c2f58ed4be76c50553886dc71e82f
2 parents 6607574 + f6a8fd5 commit 15ba15f

File tree

2 files changed

+50
-26
lines changed

2 files changed

+50
-26
lines changed

otsserver/rpc.py

+49-26
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515
import socketserver
1616
import threading
1717
import time
18+
import pystache
19+
import datetime
20+
from functools import reduce
1821

1922
import bitcoin.core
2023
from bitcoin.core import b2lx, b2x
2124

2225
import otsserver
2326
from opentimestamps.core.serialize import StreamSerializationContext
2427

25-
28+
renderer = pystache.Renderer()
2629
class RPCRequestHandler(http.server.BaseHTTPRequestHandler):
2730
MAX_DIGEST_LENGTH = 64
2831
"""Largest digest that can be POSTed for timestamping"""
@@ -154,42 +157,62 @@ def do_GET(self):
154157
# need to investigate further, but this seems to work.
155158
str_wallet_balance = str(proxy._call("getbalance"))
156159

157-
welcome_page = """\
158-
<html>
160+
transactions = proxy._call("listtransactions", "", 50)
161+
# We want only the confirmed txs containing an OP_RETURN, from most to least recent
162+
transactions = list(filter(lambda x: x["confirmations"] > 0 and x["amount"] == 0, transactions))
163+
a_week_ago = (datetime.date.today() - datetime.timedelta(days=7)).timetuple()
164+
a_week_ago_posix = time.mktime(a_week_ago)
165+
transactions_in_last_week = list(filter(lambda x: x["time"] > a_week_ago_posix, transactions))
166+
fees_in_last_week = reduce(lambda a,b: a-b["fee"], transactions_in_last_week, 0)
167+
time_between_transactions = round(168 / len(transactions_in_last_week)) # in hours based on 168 hours in a week
168+
transactions.sort(key=lambda x: x["confirmations"])
169+
homepage_template = """<html>
159170
<head>
160171
<title>OpenTimestamps Calendar Server</title>
161172
</head>
162173
<body>
163-
<p>This is an <a href="https://opentimestamps.org">OpenTimestamps</a> <a href="https://github.com/opentimestamps/opentimestamps-server">Calendar Server</a> (v%s)</p>
164-
174+
<p>This is an <a href="https://opentimestamps.org">OpenTimestamps</a> <a href="https://github.com/opentimestamps/opentimestamps-server">Calendar Server</a> (v{{ version }})</p>
165175
<p>
166-
Pending commitments: %d</br>
167-
Transactions waiting for confirmation: %d</br>
168-
Most recent timestamp tx: %s (%d prior versions)</br>
169-
Most recent merkle tree tip: %s</br>
170-
Best-block: %s, height %d</br>
176+
Pending commitments: {{ pending_commitments }}</br>
177+
Transactions waiting for confirmation: {{ txs_waiting_for_confirmation }}</br>
178+
Most recent timestamp tx: {{ most_recent_tx }} ({{ prior_versions }} prior versions)</br>
179+
Most recent merkle tree tip: {{ tip }}</br>
180+
Best-block: {{ best_block }}, height {{ block_height }}</br>
171181
</br>
172-
Wallet balance: %s BTC</br>
182+
Wallet balance: {{ balance }} BTC</br>
173183
</p>
174-
175184
<p>
176-
You can donate to the wallet by sending funds to: %s</br>
185+
You can donate to the wallet by sending funds to: {{ address }}</br>
177186
This address changes after every donation.
178187
</p>
179-
188+
<p>
189+
Average time between transactions in the last week: {{ time_between_transactions }} hour(s)</br>
190+
Fees used in the last week: {{ fees_in_last_week }} BTC</br>
191+
Latest transactions: </br>
192+
{{#transactions}}
193+
{{txid}} </br>
194+
{{/transactions}}
195+
</p>
180196
</body>
181-
</html>
182-
""" % (otsserver.__version__,
183-
len(self.calendar.stamper.pending_commitments),
184-
len(self.calendar.stamper.txs_waiting_for_confirmation),
185-
b2lx(self.calendar.stamper.unconfirmed_txs[-1].tx.GetTxid()) if self.calendar.stamper.unconfirmed_txs else 'None',
186-
max(0, len(self.calendar.stamper.unconfirmed_txs) - 1),
187-
b2x(self.calendar.stamper.unconfirmed_txs[-1].tip_timestamp.msg) if self.calendar.stamper.unconfirmed_txs else 'None',
188-
bitcoin.core.b2lx(proxy.getbestblockhash()), proxy.getblockcount(),
189-
str_wallet_balance,
190-
str(proxy.getaccountaddress('')))
191-
192-
self.wfile.write(welcome_page.encode())
197+
</html>"""
198+
199+
stats = { 'version': otsserver.__version__,
200+
'pending_commitments': len(self.calendar.stamper.pending_commitments),
201+
'txs_waiting_for_confirmation':len(self.calendar.stamper.txs_waiting_for_confirmation),
202+
'most_recent_tx': b2lx(self.calendar.stamper.unconfirmed_txs[-1].tx.GetTxid()) if self.calendar.stamper.unconfirmed_txs else 'None',
203+
'prior_versions': max(0, len(self.calendar.stamper.unconfirmed_txs) - 1),
204+
'tip': b2x(self.calendar.stamper.unconfirmed_txs[-1].tip_timestamp.msg) if self.calendar.stamper.unconfirmed_txs else 'None',
205+
'best_block': bitcoin.core.b2lx(proxy.getbestblockhash()),
206+
'block_height': proxy.getblockcount(),
207+
'balance': str_wallet_balance,
208+
'address': str(proxy.getaccountaddress('')),
209+
'transactions': transactions[:5],
210+
'time_between_transactions': time_between_transactions,
211+
'fees_in_last_week': fees_in_last_week,
212+
}
213+
welcome_page = renderer.render(homepage_template, stats)
214+
self.wfile.write(str.encode(welcome_page))
215+
193216

194217
elif self.path.startswith('/timestamp/'):
195218
self.get_timestamp()

requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ opentimestamps>=0.2.1
22
GitPython>=2.0.8
33
leveldb>=0.20
44
pysha3>=1.0.2
5+
pystache>=0.5

0 commit comments

Comments
 (0)