async def api_payments_decode(): try: if g.data["data"][:5] == "LNURL": url = lnurl.decode(g.data["data"]) return ( jsonify({"domain": url}), HTTPStatus.OK, ) else: invoice = bolt11.decode(g.data["data"]) return ( jsonify( { "payment_hash": invoice.payment_hash, "amount_msat": invoice.amount_msat, "description": invoice.description, "description_hash": invoice.description_hash, "payee": invoice.payee, "date": invoice.date, "expiry": invoice.expiry, "secret": invoice.secret, "route_hints": invoice.route_hints, "min_final_cltv_expiry": invoice.min_final_cltv_expiry, } ), HTTPStatus.OK, ) except: return jsonify({"message": "Failed to decode"}), HTTPStatus.BAD_REQUEST
async def api_lnurlscan(code: str): try: url = lnurl.decode(code) domain = urlparse(url).netloc except: # parse internet identifier ([email protected]) name_domain = code.split("@") if len(name_domain) == 2 and len(name_domain[1].split(".")) >= 2: name, domain = name_domain url = (("http://" if domain.endswith(".onion") else "https://") + domain + "/.well-known/lnurlp/" + name.lower()) # will proceed with these values else: return jsonify({"message": "invalid lnurl"}), HTTPStatus.BAD_REQUEST # params is what will be returned to the client params: Dict = {"domain": domain} if "tag=login" in url: params.update(kind="auth") params.update(callback=url) # with k1 already in it lnurlauth_key = g.wallet.lnurlauth_key(domain) params.update( pubkey=lnurlauth_key.verifying_key.to_string("compressed").hex()) else: async with httpx.AsyncClient() as client: r = await client.get(url, timeout=5) if r.is_error: return ( jsonify({ "domain": domain, "message": "failed to get parameters" }), HTTPStatus.SERVICE_UNAVAILABLE, ) try: data = json.loads(r.text) except json.decoder.JSONDecodeError: return ( jsonify({ "domain": domain, "message": f"got invalid response '{r.text[:200]}'", }), HTTPStatus.SERVICE_UNAVAILABLE, ) try: tag = data["tag"] if tag == "channelRequest": return ( jsonify({ "domain": domain, "kind": "channel", "message": "unsupported" }), HTTPStatus.BAD_REQUEST, ) params.update(**data) if tag == "withdrawRequest": params.update(kind="withdraw") params.update( fixed=data["minWithdrawable"] == data["maxWithdrawable"]) # callback with k1 already in it parsed_callback: ParseResult = urlparse(data["callback"]) qs: Dict = parse_qs(parsed_callback.query) qs["k1"] = data["k1"] # balanceCheck/balanceNotify if "balanceCheck" in data: params.update(balanceCheck=data["balanceCheck"]) # format callback url and send to client parsed_callback = parsed_callback._replace( query=urlencode(qs, doseq=True)) params.update(callback=urlunparse(parsed_callback)) if tag == "payRequest": params.update(kind="pay") params.update(fixed=data["minSendable"] == data["maxSendable"]) params.update(description_hash=hashlib.sha256( data["metadata"].encode("utf-8")).hexdigest()) metadata = json.loads(data["metadata"]) for [k, v] in metadata: if k == "text/plain": params.update(description=v) if k == "image/jpeg;base64" or k == "image/png;base64": data_uri = "data:" + k + "," + v params.update(image=data_uri) if k == "text/email" or k == "text/identifier": params.update(targetUser=v) params.update(commentAllowed=data.get("commentAllowed", 0)) except KeyError as exc: return ( jsonify({ "domain": domain, "message": f"lnurl JSON response invalid: {exc}", }), HTTPStatus.SERVICE_UNAVAILABLE, ) return jsonify(params)