summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPiotr Dobrowolski <admin@tastycode.pl>2017-01-16 23:40:41 +0100
committerPiotr Dobrowolski <admin@tastycode.pl>2017-01-16 23:40:41 +0100
commit69f66c2f62082acc6b9d163a20a06794bc92b3a7 (patch)
tree7ee53c382d702f0e43031486214d0b557a1b024c
parent0d60acf4c9257738cf6370f8871cae04eaa2e3d2 (diff)
downloadbitvend-69f66c2f62082acc6b9d163a20a06794bc92b3a7.tar.gz
bitvend-69f66c2f62082acc6b9d163a20a06794bc92b3a7.tar.bz2
bitvend-69f66c2f62082acc6b9d163a20a06794bc92b3a7.tar.xz
bitvend-69f66c2f62082acc6b9d163a20a06794bc92b3a7.zip
Render QRCodes in separate requests, migrate to blockcypher
-rw-r--r--bitvend.py20
-rw-r--r--bitvend/default_settings.py2
-rw-r--r--bitvend/mdb.py5
-rw-r--r--bitvend/processor.py53
-rw-r--r--mdb/backend.py6
-rw-r--r--mdb/device.py2
-rw-r--r--templates/index.html4
7 files changed, 63 insertions, 29 deletions
diff --git a/bitvend.py b/bitvend.py
index b2985c3..9174e2e 100644
--- a/bitvend.py
+++ b/bitvend.py
@@ -1,7 +1,10 @@
import logging
import threading
+import urllib.parse
import flask
-from flask_qrcode import QRcode
+import qrcode
+import qrcode.image.svg
+import six
from bitvend.mdb import BitvendCashlessMDBDevice
from bitvend.utils import to_local_currency, from_local_currency, format_btc, \
@@ -19,8 +22,6 @@ app.config.from_object('bitvend.default_settings')
db.init_app(app)
-QRcode(app)
-
dev = BitvendCashlessMDBDevice()
dev.init_app(app)
@@ -49,6 +50,17 @@ def reclaim(tx_hash):
flask.abort(404)
+@app.route('/qrcode')
+def qrcode_gen():
+ bio = six.BytesIO()
+ qr = qrcode.QRCode(border=0, box_size=50)
+ qr.add_data(flask.request.args['data'])
+ img = qr.make_image(image_factory=qrcode.image.svg.SvgPathFillImage)
+ img.save(bio)
+ return bio.getvalue(), {
+ 'Content-Type': 'image/svg+xml'
+ }
+
@app.context_processor
def ctx_utils():
return {
@@ -56,6 +68,8 @@ def ctx_utils():
'to_local_currency': to_local_currency,
'format_btc': format_btc,
'sat_to_btc': sat_to_btc,
+ 'qrcode': lambda data: flask.url_for('qrcode_gen') + '?' + urllib.parse.urlencode({
+ 'data': data})
}
if __name__ == "__main__":
diff --git a/bitvend/default_settings.py b/bitvend/default_settings.py
index 5c79f21..a22d421 100644
--- a/bitvend/default_settings.py
+++ b/bitvend/default_settings.py
@@ -4,6 +4,8 @@ SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_DATABASE_URI = 'sqlite:///storage-%s.db' % (platform.node(),)
INPUT_ADDRESS = '12fkW5EBb3uBy1zD8pan4TcbabP5Fjato7'
+BLOCKCYPHER_CHAIN = 'btc/main'
+
TEMPLATES_AUTO_RELOAD = True
ITEMS = [
{
diff --git a/bitvend/mdb.py b/bitvend/mdb.py
index acf4b69..9e8dd20 100644
--- a/bitvend/mdb.py
+++ b/bitvend/mdb.py
@@ -20,10 +20,13 @@ class BitvendCashlessMDBDevice(CashlessMDBDevice):
super(BitvendCashlessMDBDevice, self).begin_session(amount)
def vend_request(self, product, value):
- #self.logger.info('got vend request: %r', self.current_tx_hash)
+ # FIXME we report success here, because database write takes too much
+ # time to respond in 5ms.
self.send([0x05, 0x00, 0xff])
self.current_request.processed = True
+ self.logger.info('got vend request: %r', self.current_tx_hash)
+
if self.current_tx_hash:
with self.app.app_context():
tx = Transaction.query.filter_by(tx_hash=self.current_tx_hash).first()
diff --git a/bitvend/processor.py b/bitvend/processor.py
index 8b7c9f1..73f5c17 100644
--- a/bitvend/processor.py
+++ b/bitvend/processor.py
@@ -15,10 +15,11 @@ class PaymentProcessor(threading.Thread):
last_pong = None
app = None
- def __init__(self, device, input_address=None, app=None):
+ def __init__(self, device, input_address=None, chain_id=None, app=None):
super(PaymentProcessor, self).__init__()
self.device = device
self.input_address = input_address
+ self.chain_id = chain_id
self.logger = logging.getLogger(type(self).__name__)
if app:
@@ -29,28 +30,32 @@ class PaymentProcessor(threading.Thread):
if not self.input_address:
self.input_address = self.app.config['INPUT_ADDRESS']
+ self.chain_id = self.app.config['BLOCKCYPHER_CHAIN']
def run(self):
self.logger.info('Starting...')
- ws = websocket.WebSocketApp(
- "wss://ws.blockchain.info/inv",
- on_message=self.on_message,
- on_error=self.on_error,
- on_close=self.on_close)
-
- ws.on_open = self.on_open
while True:
- ws.run_forever()
+ try:
+ ws = websocket.WebSocketApp(
+ "wss://socket.blockcypher.com/v1/%s" % self.chain_id,
+ on_message=self.on_message,
+ on_error=self.on_error,
+ on_close=self.on_close)
+
+ ws.on_open = self.on_open
+ ws.run_forever(ping_timeout=20, ping_interval=30)
+ except:
+ self.logger.exception('run_forever failed')
+ time.sleep(1)
def process_transaction(self, tx):
- tx_size = tx['x']['size']
- tx_hash = tx['x']['hash']
+ tx_size = tx['size']
+ tx_hash = tx['hash']
tx_value = sum([
- o['value'] for o in tx['x']['out'] if o['addr'] == self.input_address
+ o['value'] for o in tx['outputs'] if self.input_address in o['addresses']
], 0)
- fee = sum([i['prev_out']['value'] for i in tx['x']['inputs']]) - \
- sum([o['value'] for o in tx['x']['out']])
+ fee = tx['fees']
fee_byte = fee / tx_size
@@ -67,7 +72,7 @@ class PaymentProcessor(threading.Thread):
self.logger.warning('Whyyyy so low...')
return
- if fee_byte < 50:
+ if fee_byte < 15:
self.logger.warning('Fee too low...')
return
@@ -81,10 +86,11 @@ class PaymentProcessor(threading.Thread):
def on_message(self, ws, message):
#print message
data = json.loads(message)
+ self.logger.info('msg: %r', data)
- if data['op'] == 'utx':
+ if 'inputs' in data:
self.process_transaction(data)
- elif data['op'] == 'pong':
+ elif data.get('event') == 'pong':
self.last_pong = time.time()
def on_error(self, ws, error):
@@ -94,11 +100,12 @@ class PaymentProcessor(threading.Thread):
self.logger.info('Connection closed')
def on_open(self, ws):
- self.logger.info('Connected')
+ self.logger.info('Connected, registering for: %r', self.input_address)
ws.send(json.dumps({
- "op": "addr_sub",
- "addr": self.input_address
+ "event": "tx-confidence",
+ "address": self.input_address,
+ "confidence": 0.9,
}))
threading.Thread(target=self.keepalive, args=(ws,), daemon=True).start()
@@ -109,9 +116,11 @@ class PaymentProcessor(threading.Thread):
while True:
# FIXME check last ping time
ws.send(json.dumps({
- "op": "ping"
+ "event": "ping"
}))
time.sleep(20)
- if time.time() - self.last_pong > 60:
+ if time.time() - self.last_pong > 30:
+ self.logger.warning('Closing socket for inactivity')
ws.close()
+ return
diff --git a/mdb/backend.py b/mdb/backend.py
index 256c836..91be573 100644
--- a/mdb/backend.py
+++ b/mdb/backend.py
@@ -26,12 +26,18 @@ class Backend(object):
pass
+#
+# Dummy backend driver, for testing purposes only
+#
class DummyBackend(Backend):
def read(self):
time.sleep(0.005)
return b''
+#
+# Backend driver for raspberry pi pigpio library
+#
class RaspiBackend(Backend):
def __init__(self, rx_pin=RX_PIN, tx_pin=TX_PIN):
self.rx_pin = rx_pin
diff --git a/mdb/device.py b/mdb/device.py
index 2dce894..7b23afe 100644
--- a/mdb/device.py
+++ b/mdb/device.py
@@ -209,7 +209,7 @@ class CashlessMDBDevice(MDBDevice):
self.logger.warning('VEND: unknown command %r', req)
elif req.command == CASHLESS_EXP and req.data[0] == CASHLESS_EXP_ID:
- self.logger.info('EXP_ID request')
+ self.logger.info('EXP_ID request: %r', req)
return (
bytearray([0x09]) + # peripheral ID
bytearray(self.manufacturer.rjust(3, ' ').encode('ascii')) +
diff --git a/templates/index.html b/templates/index.html
index 4474f17..b8f2e6e 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -12,7 +12,7 @@
<div class="col-md-12">
<div class="pull-right">
<span class="label label-info">{{ '%.2fzł'|format(item.value/100) }}</span>
- <span class="label label-primary">{{ format_btc(from_local_currency(item.value*1.1)) }}</span>
+ <span class="label label-primary">{{ format_btc(from_local_currency(item.value*1.03)) }}</span>
</div>
<h3>{{ item.name }}</h3>
</div>
@@ -20,7 +20,7 @@
<img src="{{ item.image }}" class="img-responsive center-block" />
</div>
<div class="col-xs-6 text-center">
- {% with btc_uri = 'bitcoin:%s?amount=%s' % (config['INPUT_ADDRESS'], sat_to_btc(from_local_currency(item.value*1.1))) %}
+ {% with btc_uri = 'bitcoin:%s?amount=%s' % (config['INPUT_ADDRESS'], sat_to_btc(from_local_currency(item.value*1.03))) %}
<a href="{{ btc_uri }}">
<img src="{{ qrcode(btc_uri) }}" class="img-responsive center-block"/>
<code><small>{{ config['INPUT_ADDRESS'] }}</small></code>