mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-20 10:34:20 +01:00
refactor
This commit is contained in:
@@ -1,9 +1,15 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
from functools import partial, wraps
|
from functools import partial, wraps
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from cashu.core.base import Proof
|
||||||
from cashu.core.settings import LIGHTNING_FEE_PERCENT, LIGHTNING_RESERVE_FEE_MIN
|
from cashu.core.settings import LIGHTNING_FEE_PERCENT, LIGHTNING_RESERVE_FEE_MIN
|
||||||
|
|
||||||
|
|
||||||
|
def sum_proofs(proofs: List[Proof]):
|
||||||
|
return sum([p.amount for p in proofs])
|
||||||
|
|
||||||
|
|
||||||
def async_wrap(func):
|
def async_wrap(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
async def run(*args, loop=None, executor=None, **kwargs):
|
async def run(*args, loop=None, executor=None, **kwargs):
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from cashu.core.base import (
|
|||||||
)
|
)
|
||||||
from cashu.core.crypto import derive_keys, derive_keyset_id, derive_pubkeys
|
from cashu.core.crypto import derive_keys, derive_keyset_id, derive_pubkeys
|
||||||
from cashu.core.db import Database
|
from cashu.core.db import Database
|
||||||
from cashu.core.helpers import fee_reserve
|
from cashu.core.helpers import fee_reserve, sum_proofs
|
||||||
from cashu.core.script import verify_script
|
from cashu.core.script import verify_script
|
||||||
from cashu.core.secp import PublicKey
|
from cashu.core.secp import PublicKey
|
||||||
from cashu.core.settings import LIGHTNING, MAX_ORDER
|
from cashu.core.settings import LIGHTNING, MAX_ORDER
|
||||||
@@ -45,6 +45,7 @@ class Ledger:
|
|||||||
self.db: Database = Database("mint", db)
|
self.db: Database = Database("mint", db)
|
||||||
|
|
||||||
async def load_used_proofs(self):
|
async def load_used_proofs(self):
|
||||||
|
"""Load all used proofs from database."""
|
||||||
self.proofs_used = set(await get_proofs_used(db=self.db))
|
self.proofs_used = set(await get_proofs_used(db=self.db))
|
||||||
|
|
||||||
async def init_keysets(self):
|
async def init_keysets(self):
|
||||||
@@ -93,12 +94,8 @@ class Ledger:
|
|||||||
"""Checks whether the proof was already spent."""
|
"""Checks whether the proof was already spent."""
|
||||||
return not proof.secret in self.proofs_used
|
return not proof.secret in self.proofs_used
|
||||||
|
|
||||||
def _verify_secret_or_script(self, proof: Proof):
|
|
||||||
if proof.secret and proof.script:
|
|
||||||
raise Exception("secret and script present at the same time.")
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _verify_secret_criteria(self, proof: Proof):
|
def _verify_secret_criteria(self, proof: Proof):
|
||||||
|
"""Verifies that a secret is present"""
|
||||||
if proof.secret is None or proof.secret == "":
|
if proof.secret is None or proof.secret == "":
|
||||||
raise Exception("no secret in proof.")
|
raise Exception("no secret in proof.")
|
||||||
return True
|
return True
|
||||||
@@ -213,7 +210,7 @@ class Ledger:
|
|||||||
invoice: Invoice = await get_lightning_invoice(payment_hash, db=self.db)
|
invoice: Invoice = await get_lightning_invoice(payment_hash, db=self.db)
|
||||||
if invoice.issued:
|
if invoice.issued:
|
||||||
raise Exception("tokens already issued for this invoice.")
|
raise Exception("tokens already issued for this invoice.")
|
||||||
total_requested = sum([amount for amount in amounts])
|
total_requested = sum(amounts)
|
||||||
if total_requested > invoice.amount:
|
if total_requested > invoice.amount:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
f"Requested amount too high: {total_requested}. Invoice amount: {invoice.amount}"
|
f"Requested amount too high: {total_requested}. Invoice amount: {invoice.amount}"
|
||||||
@@ -287,7 +284,7 @@ class Ledger:
|
|||||||
if not all([self._verify_proof(p) for p in proofs]):
|
if not all([self._verify_proof(p) for p in proofs]):
|
||||||
raise Exception("could not verify proofs.")
|
raise Exception("could not verify proofs.")
|
||||||
|
|
||||||
total_provided = sum([p["amount"] for p in proofs])
|
total_provided = sum_proofs(proofs)
|
||||||
invoice_obj = bolt11.decode(invoice)
|
invoice_obj = bolt11.decode(invoice)
|
||||||
amount = math.ceil(invoice_obj.amount_msat / 1000)
|
amount = math.ceil(invoice_obj.amount_msat / 1000)
|
||||||
fees_msat = await self.check_fees(invoice)
|
fees_msat = await self.check_fees(invoice)
|
||||||
@@ -319,7 +316,7 @@ class Ledger:
|
|||||||
self, proofs: List[Proof], amount: int, outputs: List[BlindedMessage]
|
self, proofs: List[Proof], amount: int, outputs: List[BlindedMessage]
|
||||||
):
|
):
|
||||||
"""Consumes proofs and prepares new promises based on the amount split."""
|
"""Consumes proofs and prepares new promises based on the amount split."""
|
||||||
total = sum([p.amount for p in proofs])
|
total = sum_proofs(proofs)
|
||||||
|
|
||||||
# verify that amount is kosher
|
# verify that amount is kosher
|
||||||
self._verify_split_amount(amount)
|
self._verify_split_amount(amount)
|
||||||
|
|||||||
@@ -81,11 +81,17 @@ async def melt(payload: MeltRequest):
|
|||||||
|
|
||||||
@router.post("/check")
|
@router.post("/check")
|
||||||
async def check_spendable(payload: CheckRequest):
|
async def check_spendable(payload: CheckRequest):
|
||||||
|
"""Check whether a secret has been spent already or not."""
|
||||||
return await ledger.check_spendable(payload.proofs)
|
return await ledger.check_spendable(payload.proofs)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/checkfees")
|
@router.post("/checkfees")
|
||||||
async def check_fees(payload: CheckFeesRequest):
|
async def check_fees(payload: CheckFeesRequest):
|
||||||
|
"""
|
||||||
|
Responds with the fees necessary to pay a Lightning invoice.
|
||||||
|
Used by wallets for figuring out the fees they need to supply.
|
||||||
|
This is can be useful for checking whether an invoice is internal (Cashu-to-Cashu).
|
||||||
|
"""
|
||||||
fees_msat = await ledger.check_fees(payload.pr)
|
fees_msat = await ledger.check_fees(payload.pr)
|
||||||
return CheckFeesResponse(fee=fees_msat / 1000)
|
return CheckFeesResponse(fee=fees_msat / 1000)
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from loguru import logger
|
|||||||
import cashu.core.bolt11 as bolt11
|
import cashu.core.bolt11 as bolt11
|
||||||
from cashu.core.base import Proof
|
from cashu.core.base import Proof
|
||||||
from cashu.core.bolt11 import Invoice, decode
|
from cashu.core.bolt11 import Invoice, decode
|
||||||
from cashu.core.helpers import fee_reserve
|
from cashu.core.helpers import fee_reserve, sum_proofs
|
||||||
from cashu.core.migrations import migrate_databases
|
from cashu.core.migrations import migrate_databases
|
||||||
from cashu.core.settings import CASHU_DIR, DEBUG, ENV_FILE, LIGHTNING, MINT_URL, VERSION
|
from cashu.core.settings import CASHU_DIR, DEBUG, ENV_FILE, LIGHTNING, MINT_URL, VERSION
|
||||||
from cashu.wallet import migrations
|
from cashu.wallet import migrations
|
||||||
@@ -267,7 +267,7 @@ async def pending(ctx):
|
|||||||
int(grouped_proofs[0].time_reserved)
|
int(grouped_proofs[0].time_reserved)
|
||||||
).strftime("%Y-%m-%d %H:%M:%S")
|
).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
print(
|
print(
|
||||||
f"#{i} Amount: {sum([p['amount'] for p in grouped_proofs])} sat Time: {reserved_date} ID: {key}\n"
|
f"#{i} Amount: {sum_proofs(grouped_proofs)} sat Time: {reserved_date} ID: {key}\n"
|
||||||
)
|
)
|
||||||
print(f"With secret: {coin}\n\nSecretless: {coin_hidden_secret}\n")
|
print(f"With secret: {coin}\n\nSecretless: {coin_hidden_secret}\n")
|
||||||
print(f"--------------------------\n")
|
print(f"--------------------------\n")
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ from cashu.core.base import (
|
|||||||
WalletKeyset,
|
WalletKeyset,
|
||||||
)
|
)
|
||||||
from cashu.core.db import Database
|
from cashu.core.db import Database
|
||||||
|
from cashu.core.helpers import sum_proofs
|
||||||
from cashu.core.script import (
|
from cashu.core.script import (
|
||||||
step0_carol_checksig_redeemscrip,
|
step0_carol_checksig_redeemscrip,
|
||||||
step0_carol_privkey,
|
step0_carol_privkey,
|
||||||
@@ -190,7 +191,7 @@ class LedgerAPI:
|
|||||||
If scnd_secret is provided, the wallet will create blinded secrets with those to attach a
|
If scnd_secret is provided, the wallet will create blinded secrets with those to attach a
|
||||||
predefined spending condition to the tokens they want to send."""
|
predefined spending condition to the tokens they want to send."""
|
||||||
|
|
||||||
total = sum([p["amount"] for p in proofs])
|
total = sum_proofs(proofs)
|
||||||
frst_amt, scnd_amt = total - amount, amount
|
frst_amt, scnd_amt = total - amount, amount
|
||||||
frst_outputs = amount_split(frst_amt)
|
frst_outputs = amount_split(frst_amt)
|
||||||
scnd_outputs = amount_split(scnd_amt)
|
scnd_outputs = amount_split(scnd_amt)
|
||||||
@@ -312,12 +313,6 @@ class Wallet(LedgerAPI):
|
|||||||
for proof in proofs:
|
for proof in proofs:
|
||||||
await store_proof(proof, db=self.db)
|
await store_proof(proof, db=self.db)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _sum_proofs(proofs: List[Proof], available_only=False):
|
|
||||||
if available_only:
|
|
||||||
return sum([p.amount for p in proofs if not p.reserved])
|
|
||||||
return sum([p.amount for p in proofs])
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_proofs_per_keyset(proofs: List[Proof]):
|
def _get_proofs_per_keyset(proofs: List[Proof]):
|
||||||
return {key: list(group) for key, group in groupby(proofs, lambda p: p.id)}
|
return {key: list(group) for key, group in groupby(proofs, lambda p: p.id)}
|
||||||
@@ -345,7 +340,7 @@ class Wallet(LedgerAPI):
|
|||||||
# attach unlock scripts to proofs
|
# attach unlock scripts to proofs
|
||||||
for p in proofs:
|
for p in proofs:
|
||||||
p.script = P2SHScript(script=scnd_script, signature=scnd_siganture)
|
p.script = P2SHScript(script=scnd_script, signature=scnd_siganture)
|
||||||
return await self.split(proofs, sum(p["amount"] for p in proofs))
|
return await self.split(proofs, sum_proofs(proofs))
|
||||||
|
|
||||||
async def split(
|
async def split(
|
||||||
self,
|
self,
|
||||||
@@ -405,7 +400,7 @@ class Wallet(LedgerAPI):
|
|||||||
if scnd_secret:
|
if scnd_secret:
|
||||||
logger.debug(f"Spending conditions: {scnd_secret}")
|
logger.debug(f"Spending conditions: {scnd_secret}")
|
||||||
spendable_proofs = await self._get_spendable_proofs(proofs)
|
spendable_proofs = await self._get_spendable_proofs(proofs)
|
||||||
if sum([p.amount for p in spendable_proofs]) < amount:
|
if sum_proofs(spendable_proofs) < amount:
|
||||||
raise Exception("balance too low.")
|
raise Exception("balance too low.")
|
||||||
return await self.split(
|
return await self.split(
|
||||||
[p for p in spendable_proofs if not p.reserved], amount, scnd_secret
|
[p for p in spendable_proofs if not p.reserved], amount, scnd_secret
|
||||||
@@ -453,11 +448,11 @@ class Wallet(LedgerAPI):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def balance(self):
|
def balance(self):
|
||||||
return sum(p["amount"] for p in self.proofs)
|
return sum_proofs(self.proofs)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available_balance(self):
|
def available_balance(self):
|
||||||
return sum(p["amount"] for p in self.proofs if not p.reserved)
|
return sum_proofs([p for p in self.proofs if not p.reserved])
|
||||||
|
|
||||||
def status(self):
|
def status(self):
|
||||||
print(
|
print(
|
||||||
@@ -467,8 +462,8 @@ class Wallet(LedgerAPI):
|
|||||||
def balance_per_keyset(self):
|
def balance_per_keyset(self):
|
||||||
return {
|
return {
|
||||||
key: {
|
key: {
|
||||||
"balance": self._sum_proofs(proofs),
|
"balance": sum_proofs(proofs),
|
||||||
"available": self._sum_proofs(proofs, available_only=True),
|
"available": sum_proofs([p for p in proofs if not p.reserved]),
|
||||||
}
|
}
|
||||||
for key, proofs in self._get_proofs_per_keyset(self.proofs).items()
|
for key, proofs in self._get_proofs_per_keyset(self.proofs).items()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user