mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-22 11:24:19 +01:00
wallet: mint specific amounts (#121)
* wallet: mint specific amounts * make format
This commit is contained in:
@@ -376,7 +376,7 @@ class Ledger:
|
|||||||
|
|
||||||
for amount in amounts:
|
for amount in amounts:
|
||||||
if amount not in [2**i for i in range(MAX_ORDER)]:
|
if amount not in [2**i for i in range(MAX_ORDER)]:
|
||||||
raise Exception(f"Can only mint amounts up to {2**MAX_ORDER}.")
|
raise Exception(f"Can only mint amounts with 2^n up to {2**MAX_ORDER}.")
|
||||||
|
|
||||||
promises = await self._generate_promises(B_s, keyset)
|
promises = await self._generate_promises(B_s, keyset)
|
||||||
return promises
|
return promises
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ from cashu.core.script import (
|
|||||||
step2_carol_sign_tx,
|
step2_carol_sign_tx,
|
||||||
)
|
)
|
||||||
from cashu.core.secp import PublicKey
|
from cashu.core.secp import PublicKey
|
||||||
from cashu.core.settings import DEBUG, SOCKS_HOST, SOCKS_PORT, TOR, VERSION
|
from cashu.core.settings import DEBUG, MAX_ORDER, SOCKS_HOST, SOCKS_PORT, TOR, VERSION
|
||||||
from cashu.core.split import amount_split
|
from cashu.core.split import amount_split
|
||||||
from cashu.tor.tor import TorProxy
|
from cashu.tor.tor import TorProxy
|
||||||
from cashu.wallet.crud import (
|
from cashu.wallet.crud import (
|
||||||
@@ -110,7 +110,7 @@ class LedgerAPI:
|
|||||||
self, promises: List[BlindedSignature], secrets: List[str], rs: List[str]
|
self, promises: List[BlindedSignature], secrets: List[str], rs: List[str]
|
||||||
):
|
):
|
||||||
"""Returns proofs of promise from promises. Wants secrets and blinding factors rs."""
|
"""Returns proofs of promise from promises. Wants secrets and blinding factors rs."""
|
||||||
proofs = []
|
proofs: List[Proof] = []
|
||||||
for promise, secret, r in zip(promises, secrets, rs):
|
for promise, secret, r in zip(promises, secrets, rs):
|
||||||
C_ = PublicKey(bytes.fromhex(promise.C_), raw=True)
|
C_ = PublicKey(bytes.fromhex(promise.C_), raw=True)
|
||||||
C = b_dhke.step3_alice(C_, r, self.keys[promise.amount])
|
C = b_dhke.step3_alice(C_, r, self.keys[promise.amount])
|
||||||
@@ -439,6 +439,18 @@ class Wallet(LedgerAPI):
|
|||||||
return invoice
|
return invoice
|
||||||
|
|
||||||
async def mint(self, amount: int, payment_hash: Optional[str] = None):
|
async def mint(self, amount: int, payment_hash: Optional[str] = None):
|
||||||
|
"""Mint tokens of a specific amount after an invoice has been paid.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
amount (int): Total amount of tokens to be minted
|
||||||
|
payment_hash (Optional[str], optional): Hash of the paid Lightning invoice. Defaults to None (for testing with LIGHTNING=False).
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
Exception: Raises exception if no proofs have been provided
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List[Proof]: Newly minted proofs.
|
||||||
|
"""
|
||||||
split = amount_split(amount)
|
split = amount_split(amount)
|
||||||
proofs = await super().mint(split, payment_hash)
|
proofs = await super().mint(split, payment_hash)
|
||||||
if proofs == []:
|
if proofs == []:
|
||||||
@@ -451,6 +463,35 @@ class Wallet(LedgerAPI):
|
|||||||
self.proofs += proofs
|
self.proofs += proofs
|
||||||
return proofs
|
return proofs
|
||||||
|
|
||||||
|
async def mint_amounts(
|
||||||
|
self, amounts: List[int], payment_hash: Optional[str] = None
|
||||||
|
):
|
||||||
|
"""Similar to wallet.mint() but accepts a predefined list of amount to be minted.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
amounts (List[int]): List of amounts requested
|
||||||
|
payment_hash (Optional[str], optional): Hash of the paid Lightning invoice. Defaults to None (for testing with LIGHTNING=False).
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
Exception: Newly minted proofs.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List[Proof]: Newly minted proofs.
|
||||||
|
"""
|
||||||
|
for amount in amounts:
|
||||||
|
if amount not in [2**i for i in range(MAX_ORDER)]:
|
||||||
|
raise Exception(f"Can only mint amounts with 2^n up to {2**MAX_ORDER}.")
|
||||||
|
proofs = await super().mint(amounts, payment_hash)
|
||||||
|
if proofs == []:
|
||||||
|
raise Exception("received no proofs.")
|
||||||
|
await self._store_proofs(proofs)
|
||||||
|
if payment_hash:
|
||||||
|
await update_lightning_invoice(
|
||||||
|
db=self.db, hash=payment_hash, paid=True, time_paid=int(time.time())
|
||||||
|
)
|
||||||
|
self.proofs += proofs
|
||||||
|
return proofs
|
||||||
|
|
||||||
async def redeem(
|
async def redeem(
|
||||||
self,
|
self,
|
||||||
proofs: List[Proof],
|
proofs: List[Proof],
|
||||||
@@ -704,10 +745,12 @@ class Wallet(LedgerAPI):
|
|||||||
def available_balance(self):
|
def available_balance(self):
|
||||||
return sum_proofs([p for p in self.proofs if not p.reserved])
|
return sum_proofs([p for p in self.proofs if not p.reserved])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def proof_amounts(self):
|
||||||
|
"""Returns a sorted list of amounts of all proofs"""
|
||||||
|
return [p.amount for p in sorted(self.proofs, key=lambda p: p.amount)]
|
||||||
|
|
||||||
def status(self):
|
def status(self):
|
||||||
# print(
|
|
||||||
# f"Balance: {self.balance} sat (available: {self.available_balance} sat in {len([p for p in self.proofs if not p.reserved])} tokens)"
|
|
||||||
# )
|
|
||||||
print(f"Balance: {self.available_balance} sat")
|
print(f"Balance: {self.available_balance} sat")
|
||||||
|
|
||||||
def balance_per_keyset(self):
|
def balance_per_keyset(self):
|
||||||
@@ -729,6 +772,3 @@ class Wallet(LedgerAPI):
|
|||||||
for key, proofs in balances.items()
|
for key, proofs in balances.items()
|
||||||
}
|
}
|
||||||
return dict(sorted(balances_return.items(), key=lambda item: item[1]["available"], reverse=True)) # type: ignore
|
return dict(sorted(balances_return.items(), key=lambda item: item[1]["available"], reverse=True)) # type: ignore
|
||||||
|
|
||||||
def proof_amounts(self):
|
|
||||||
return [p["amount"] for p in sorted(self.proofs, key=lambda p: p["amount"])]
|
|
||||||
|
|||||||
@@ -85,6 +85,23 @@ async def test_mint(wallet1: Wallet):
|
|||||||
assert wallet1.balance == 64
|
assert wallet1.balance == 64
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_mint_amounts(wallet1: Wallet):
|
||||||
|
"""Mint predefined amounts"""
|
||||||
|
await wallet1.mint_amounts([1, 1, 1, 2, 2, 4, 16])
|
||||||
|
assert wallet1.balance == 27
|
||||||
|
assert wallet1.proof_amounts == [1, 1, 1, 2, 2, 4, 16]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_mint_amounts_wrong_order(wallet1: Wallet):
|
||||||
|
"""Mint amount that is not part in 2^n"""
|
||||||
|
await assert_err(
|
||||||
|
wallet1.mint_amounts([1, 2, 3]),
|
||||||
|
f"Can only mint amounts with 2^n up to {2**MAX_ORDER}.",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_split(wallet1: Wallet):
|
async def test_split(wallet1: Wallet):
|
||||||
await wallet1.mint(64)
|
await wallet1.mint(64)
|
||||||
|
|||||||
Reference in New Issue
Block a user