abstract exchange rates code into a "util".

This commit is contained in:
fiatjaf
2021-03-14 20:43:39 -03:00
parent 5142f1e29f
commit adc3e62573
7 changed files with 272 additions and 107 deletions
-48
View File
@@ -1,57 +1,9 @@
import trio # type: ignore
import httpx
import base64
import struct
import hmac
import time
async def get_fiat_rate(currency: str):
assert currency == "USD", "Only USD is supported as fiat currency."
return await get_usd_rate()
async def get_usd_rate():
"""
Returns an average satoshi price from multiple sources.
"""
satoshi_prices = [None, None, None]
async def fetch_price(index, url, getter):
try:
async with httpx.AsyncClient() as client:
r = await client.get(url)
r.raise_for_status()
satoshi_price = int(100_000_000 / float(getter(r.json())))
satoshi_prices[index] = satoshi_price
except Exception:
pass
async with trio.open_nursery() as nursery:
nursery.start_soon(
fetch_price,
0,
"https://api.kraken.com/0/public/Ticker?pair=XXBTZUSD",
lambda d: d["result"]["XXBTCZUSD"]["c"][0],
)
nursery.start_soon(
fetch_price,
1,
"https://www.bitstamp.net/api/v2/ticker/btcusd",
lambda d: d["last"],
)
nursery.start_soon(
fetch_price,
2,
"https://api.coincap.io/v2/rates/bitcoin",
lambda d: d["data"]["rateUsd"],
)
satoshi_prices = [x for x in satoshi_prices if x]
return sum(satoshi_prices) / len(satoshi_prices)
def hotp(key, counter, digits=6, digest="sha1"):
key = base64.b32decode(key.upper() + "=" * ((8 - len(key)) % 8))
counter = struct.pack(">Q", counter)
+5 -6
View File
@@ -3,10 +3,10 @@ from quart import jsonify, url_for, request
from lnurl import LnurlPayResponse, LnurlPayActionResponse, LnurlErrorResponse # type: ignore
from lnbits.core.services import create_invoice
from lnbits.utils.exchange_rates import fiat_amount_as_satoshis
from . import offlineshop_ext
from .crud import get_shop, get_item
from .helpers import get_fiat_rate
@offlineshop_ext.route("/lnurl/<item_id>", methods=["GET"])
@@ -18,8 +18,7 @@ async def lnurl_response(item_id):
if not item.enabled:
return jsonify({"status": "ERROR", "reason": "Item disabled."})
rate = await get_fiat_rate(item.unit) if item.unit != "sat" else 1
price_msat = int(item.price * rate) * 1000
price_msat = (await fiat_amount_as_satoshis(item.price, item.unit) if item.unit != "sat" else item.price) * 1000
resp = LnurlPayResponse(
callback=url_for("offlineshop.lnurl_callback", item_id=item.id, _external=True),
@@ -41,10 +40,10 @@ async def lnurl_callback(item_id):
min = item.price * 1000
max = item.price * 1000
else:
rate = await get_fiat_rate(item.unit)
price = await fiat_amount_as_satoshis(item.price, item.unit)
# allow some fluctuation (the fiat price may have changed between the calls)
min = int(rate * item.price) * 995
max = int(rate * item.price) * 1010
min = price * 995
max = price * 1010
amount_received = int(request.args.get("amount"))
if amount_received < min: