mirror of
https://github.com/lnbits/lnbits.git
synced 2025-06-27 17:23:12 +02:00
Mega-merge 2: Invoice/refactor description hash (WIP) (#814)
* description hashing in backend
This commit is contained in:
parent
c88e6b0e62
commit
f1ec7e33f0
@ -184,11 +184,13 @@ async def api_payments_create_invoice(data: CreateInvoiceData, wallet: Wallet):
|
|||||||
|
|
||||||
lnurl_response: Union[None, bool, str] = None
|
lnurl_response: Union[None, bool, str] = None
|
||||||
if data.lnurl_callback:
|
if data.lnurl_callback:
|
||||||
if "lnurl_balance_check" in data:
|
if data.lnurl_balance_check is not None:
|
||||||
assert (
|
|
||||||
data.lnurl_balance_check is not None
|
|
||||||
), "lnurl_balance_check is required"
|
|
||||||
await save_balance_check(wallet.id, data.lnurl_balance_check)
|
await save_balance_check(wallet.id, data.lnurl_balance_check)
|
||||||
|
else:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=HTTPStatus.BAD_REQUEST,
|
||||||
|
detail="lnurl_balance_check not set.",
|
||||||
|
)
|
||||||
|
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
try:
|
try:
|
||||||
|
@ -73,11 +73,9 @@ async def lnurl_callback(
|
|||||||
wallet_id=cp.wallet,
|
wallet_id=cp.wallet,
|
||||||
amount=int(amount_received / 1000),
|
amount=int(amount_received / 1000),
|
||||||
memo=cp.lnurl_title,
|
memo=cp.lnurl_title,
|
||||||
description_hash=hashlib.sha256(
|
description_hash=(
|
||||||
(
|
|
||||||
LnurlPayMetadata(json.dumps([["text/plain", str(cp.lnurl_title)]]))
|
LnurlPayMetadata(json.dumps([["text/plain", str(cp.lnurl_title)]]))
|
||||||
).encode("utf-8")
|
).encode("utf-8"),
|
||||||
).digest(),
|
|
||||||
extra={"tag": "copilot", "copilotid": cp.id, "comment": comment},
|
extra={"tag": "copilot", "copilotid": cp.id, "comment": comment},
|
||||||
)
|
)
|
||||||
payResponse = {"pr": payment_request, "routes": []}
|
payResponse = {"pr": payment_request, "routes": []}
|
||||||
|
@ -90,9 +90,7 @@ async def lnurl_callback(
|
|||||||
wallet_id=ls.wallet,
|
wallet_id=ls.wallet,
|
||||||
amount=int(amount_received / 1000),
|
amount=int(amount_received / 1000),
|
||||||
memo=await track.fullname(),
|
memo=await track.fullname(),
|
||||||
description_hash=hashlib.sha256(
|
description_hash=(await track.lnurlpay_metadata()).encode("utf-8"),
|
||||||
(await track.lnurlpay_metadata()).encode("utf-8")
|
|
||||||
).digest(),
|
|
||||||
extra={"tag": "livestream", "track": track.id, "comment": comment},
|
extra={"tag": "livestream", "track": track.id, "comment": comment},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -70,11 +70,9 @@ async def lnurl_callback(address_id, amount: int = Query(...)):
|
|||||||
json={
|
json={
|
||||||
"out": False,
|
"out": False,
|
||||||
"amount": int(amount_received / 1000),
|
"amount": int(amount_received / 1000),
|
||||||
"description_hash": hashlib.sha256(
|
"description_hash": (
|
||||||
(await address.lnurlpay_metadata(domain=domain.domain)).encode(
|
await address.lnurlpay_metadata(domain=domain.domain)
|
||||||
"utf-8"
|
).encode("utf-8"),
|
||||||
)
|
|
||||||
).hexdigest(),
|
|
||||||
"extra": {"tag": f"Payment to {address.username}@{domain.domain}"},
|
"extra": {"tag": f"Payment to {address.username}@{domain.domain}"},
|
||||||
},
|
},
|
||||||
timeout=40,
|
timeout=40,
|
||||||
|
@ -205,9 +205,7 @@ async def lnurl_callback(
|
|||||||
wallet_id=device.wallet,
|
wallet_id=device.wallet,
|
||||||
amount=lnurldevicepayment.sats / 1000,
|
amount=lnurldevicepayment.sats / 1000,
|
||||||
memo=device.title,
|
memo=device.title,
|
||||||
description_hash=hashlib.sha256(
|
description_hash=(await device.lnurlpay_metadata()).encode("utf-8"),
|
||||||
(await device.lnurlpay_metadata()).encode("utf-8")
|
|
||||||
).digest(),
|
|
||||||
extra={"tag": "PoS"},
|
extra={"tag": "PoS"},
|
||||||
)
|
)
|
||||||
lnurldevicepayment = await update_lnurldevicepayment(
|
lnurldevicepayment = await update_lnurldevicepayment(
|
||||||
|
@ -87,9 +87,7 @@ async def api_lnurl_callback(request: Request, link_id):
|
|||||||
wallet_id=link.wallet,
|
wallet_id=link.wallet,
|
||||||
amount=int(amount_received / 1000),
|
amount=int(amount_received / 1000),
|
||||||
memo=link.description,
|
memo=link.description,
|
||||||
description_hash=hashlib.sha256(
|
description_hash=link.lnurlpay_metadata.encode("utf-8"),
|
||||||
link.lnurlpay_metadata.encode("utf-8")
|
|
||||||
).digest(),
|
|
||||||
extra={
|
extra={
|
||||||
"tag": "lnurlp",
|
"tag": "lnurlp",
|
||||||
"link": link.id,
|
"link": link.id,
|
||||||
|
@ -73,9 +73,7 @@ async def lnurl_callback(request: Request, item_id: int):
|
|||||||
wallet_id=shop.wallet,
|
wallet_id=shop.wallet,
|
||||||
amount=int(amount_received / 1000),
|
amount=int(amount_received / 1000),
|
||||||
memo=item.name,
|
memo=item.name,
|
||||||
description_hash=hashlib.sha256(
|
description_hash=(await item.lnurlpay_metadata()).encode("utf-8"),
|
||||||
(await item.lnurlpay_metadata()).encode("utf-8")
|
|
||||||
).digest(),
|
|
||||||
extra={"tag": "offlineshop", "item": item.id},
|
extra={"tag": "offlineshop", "item": item.id},
|
||||||
)
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
@ -77,9 +77,7 @@ async def api_lnurlp_callback(
|
|||||||
wallet_id=link.wallet,
|
wallet_id=link.wallet,
|
||||||
amount=int(amount_received / 1000),
|
amount=int(amount_received / 1000),
|
||||||
memo="Satsdice bet",
|
memo="Satsdice bet",
|
||||||
description_hash=hashlib.sha256(
|
description_hash=link.lnurlpay_metadata.encode("utf-8"),
|
||||||
link.lnurlpay_metadata.encode("utf-8")
|
|
||||||
).digest(),
|
|
||||||
extra={"tag": "satsdice", "link": link.id, "comment": "comment"},
|
extra={"tag": "satsdice", "link": link.id, "comment": "comment"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
from os import getenv
|
from os import getenv
|
||||||
from typing import AsyncGenerator, Dict, Optional
|
from typing import AsyncGenerator, Dict, Optional
|
||||||
@ -47,9 +48,10 @@ class ClicheWallet(Wallet):
|
|||||||
description_hash: Optional[bytes] = None,
|
description_hash: Optional[bytes] = None,
|
||||||
) -> InvoiceResponse:
|
) -> InvoiceResponse:
|
||||||
if description_hash:
|
if description_hash:
|
||||||
|
description_hash_hashed = hashlib.sha256(description_hash).hexdigest()
|
||||||
ws = create_connection(self.endpoint)
|
ws = create_connection(self.endpoint)
|
||||||
ws.send(
|
ws.send(
|
||||||
f"create-invoice --msatoshi {amount*1000} --description_hash {description_hash.hex()}"
|
f"create-invoice --msatoshi {amount*1000} --description_hash {description_hash_hashed}"
|
||||||
)
|
)
|
||||||
r = ws.recv()
|
r = ws.recv()
|
||||||
else:
|
else:
|
||||||
|
@ -4,6 +4,7 @@ except ImportError: # pragma: nocover
|
|||||||
LightningRpc = None
|
LightningRpc = None
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import hashlib
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
from functools import partial, wraps
|
from functools import partial, wraps
|
||||||
@ -94,7 +95,7 @@ class CLightningWallet(Wallet):
|
|||||||
if not self.supports_description_hash:
|
if not self.supports_description_hash:
|
||||||
raise Unsupported("description_hash")
|
raise Unsupported("description_hash")
|
||||||
|
|
||||||
params = [msat, label, description_hash.hex()]
|
params = [msat, label, hashlib.sha256(description_hash).hexdigest()]
|
||||||
r = self.ln.call("invoicewithdescriptionhash", params)
|
r = self.ln.call("invoicewithdescriptionhash", params)
|
||||||
return InvoiceResponse(True, label, r["bolt11"], "")
|
return InvoiceResponse(True, label, r["bolt11"], "")
|
||||||
else:
|
else:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import base64
|
import base64
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from os import getenv
|
from os import getenv
|
||||||
@ -72,7 +73,7 @@ class EclairWallet(Wallet):
|
|||||||
|
|
||||||
data: Dict = {"amountMsat": amount * 1000}
|
data: Dict = {"amountMsat": amount * 1000}
|
||||||
if description_hash:
|
if description_hash:
|
||||||
data["description_hash"] = description_hash.hex()
|
data["description_hash"] = hashlib.sha256(description_hash).hexdigest()
|
||||||
else:
|
else:
|
||||||
data["description"] = memo or ""
|
data["description"] = memo or ""
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ class FakeWallet(Wallet):
|
|||||||
data["timestamp"] = datetime.now().timestamp()
|
data["timestamp"] = datetime.now().timestamp()
|
||||||
if description_hash:
|
if description_hash:
|
||||||
data["tags_set"] = ["h"]
|
data["tags_set"] = ["h"]
|
||||||
data["description_hash"] = description_hash.hex()
|
data["description_hash"] = description_hash.decode("utf-8")
|
||||||
else:
|
else:
|
||||||
data["tags_set"] = ["d"]
|
data["tags_set"] = ["d"]
|
||||||
data["memo"] = memo
|
data["memo"] = memo
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
from os import getenv
|
from os import getenv
|
||||||
from typing import AsyncGenerator, Dict, Optional
|
from typing import AsyncGenerator, Dict, Optional
|
||||||
@ -59,7 +60,7 @@ class LNbitsWallet(Wallet):
|
|||||||
) -> InvoiceResponse:
|
) -> InvoiceResponse:
|
||||||
data: Dict = {"out": False, "amount": amount}
|
data: Dict = {"out": False, "amount": amount}
|
||||||
if description_hash:
|
if description_hash:
|
||||||
data["description_hash"] = description_hash.hex()
|
data["description_hash"] = hashlib.sha256(description_hash).hexdigest()
|
||||||
else:
|
else:
|
||||||
data["memo"] = memo or ""
|
data["memo"] = memo or ""
|
||||||
|
|
||||||
|
@ -132,7 +132,9 @@ class LndWallet(Wallet):
|
|||||||
params: Dict = {"value": amount, "expiry": 600, "private": True}
|
params: Dict = {"value": amount, "expiry": 600, "private": True}
|
||||||
|
|
||||||
if description_hash:
|
if description_hash:
|
||||||
params["description_hash"] = description_hash # as bytes directly
|
params["description_hash"] = base64.b64encode(
|
||||||
|
hashlib.sha256(description_hash).digest()
|
||||||
|
) # as bytes directly
|
||||||
else:
|
else:
|
||||||
params["memo"] = memo or ""
|
params["memo"] = memo or ""
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import base64
|
import base64
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
from os import getenv
|
from os import getenv
|
||||||
from pydoc import describe
|
from pydoc import describe
|
||||||
@ -75,9 +76,9 @@ class LndRestWallet(Wallet):
|
|||||||
) -> InvoiceResponse:
|
) -> InvoiceResponse:
|
||||||
data: Dict = {"value": amount, "private": True}
|
data: Dict = {"value": amount, "private": True}
|
||||||
if description_hash:
|
if description_hash:
|
||||||
data["description_hash"] = base64.b64encode(description_hash).decode(
|
data["description_hash"] = base64.b64encode(
|
||||||
"ascii"
|
hashlib.sha256(description_hash).digest()
|
||||||
)
|
).decode("ascii")
|
||||||
else:
|
else:
|
||||||
data["memo"] = memo or ""
|
data["memo"] = memo or ""
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
from os import getenv
|
from os import getenv
|
||||||
@ -54,7 +55,7 @@ class LNPayWallet(Wallet):
|
|||||||
) -> InvoiceResponse:
|
) -> InvoiceResponse:
|
||||||
data: Dict = {"num_satoshis": f"{amount}"}
|
data: Dict = {"num_satoshis": f"{amount}"}
|
||||||
if description_hash:
|
if description_hash:
|
||||||
data["description_hash"] = description_hash.hex()
|
data["description_hash"] = hashlib.sha256(description_hash).hexdigest()
|
||||||
else:
|
else:
|
||||||
data["memo"] = memo or ""
|
data["memo"] = memo or ""
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
from os import getenv
|
from os import getenv
|
||||||
from typing import AsyncGenerator, Dict, Optional
|
from typing import AsyncGenerator, Dict, Optional
|
||||||
@ -54,7 +55,7 @@ class LntxbotWallet(Wallet):
|
|||||||
) -> InvoiceResponse:
|
) -> InvoiceResponse:
|
||||||
data: Dict = {"amt": str(amount)}
|
data: Dict = {"amt": str(amount)}
|
||||||
if description_hash:
|
if description_hash:
|
||||||
data["description_hash"] = description_hash.hex()
|
data["description_hash"] = hashlib.sha256(description_hash).hexdigest()
|
||||||
else:
|
else:
|
||||||
data["memo"] = memo or ""
|
data["memo"] = memo or ""
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
from os import getenv
|
from os import getenv
|
||||||
@ -101,7 +102,7 @@ class SparkWallet(Wallet):
|
|||||||
r = await self.invoicewithdescriptionhash(
|
r = await self.invoicewithdescriptionhash(
|
||||||
msatoshi=amount * 1000,
|
msatoshi=amount * 1000,
|
||||||
label=label,
|
label=label,
|
||||||
description_hash=description_hash.hex(),
|
description_hash=hashlib.sha256(description_hash).hexdigest(),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
r = await self.invoice(
|
r = await self.invoice(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user