mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-23 19:54:18 +01:00
Allow arbitrary denominations in wallet minting (#684)
- Update `mint` method to use allowed amounts from the mint - Add `get_allowed_amounts` method to fetch supported denominations - Modify `test_mint_amounts_wrong_order` to expect new error message Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
This commit is contained in:
@@ -111,6 +111,21 @@ class WalletTransactions(SupportsDb, SupportsKeysets):
|
|||||||
proofs_send = self.coinselect(proofs, amount, include_fees=True)
|
proofs_send = self.coinselect(proofs, amount, include_fees=True)
|
||||||
return self.get_fees_for_proofs(proofs_send)
|
return self.get_fees_for_proofs(proofs_send)
|
||||||
|
|
||||||
|
def get_allowed_amounts(self):
|
||||||
|
"""
|
||||||
|
Infer the allowed amounts from the current keyset's public keys.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List[int]: A sorted list of allowed token amounts for the current keyset.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
Exception: If no active keyset is set.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not self.keyset_id or self.keyset_id not in self.keysets:
|
||||||
|
raise Exception("No active keyset")
|
||||||
|
return sorted(list(self.keysets[self.keyset_id].public_keys.keys()))
|
||||||
|
|
||||||
def split_wallet_state(self, amount: int) -> List[int]:
|
def split_wallet_state(self, amount: int) -> List[int]:
|
||||||
"""This function produces an amount split for outputs based on the current state of the wallet.
|
"""This function produces an amount split for outputs based on the current state of the wallet.
|
||||||
Its objective is to fill up the wallet so that it reaches `n_target` coins of each amount.
|
Its objective is to fill up the wallet so that it reaches `n_target` coins of each amount.
|
||||||
@@ -125,8 +140,9 @@ class WalletTransactions(SupportsDb, SupportsKeysets):
|
|||||||
n_target = settings.wallet_target_amount_count
|
n_target = settings.wallet_target_amount_count
|
||||||
amounts_we_have = [p.amount for p in self.proofs if p.reserved is not True]
|
amounts_we_have = [p.amount for p in self.proofs if p.reserved is not True]
|
||||||
amounts_we_have.sort()
|
amounts_we_have.sort()
|
||||||
# NOTE: Do not assume 2^n here
|
|
||||||
all_possible_amounts: list[int] = [2**i for i in range(settings.max_order)]
|
all_possible_amounts = self.get_allowed_amounts()
|
||||||
|
|
||||||
amounts_we_want_ll = [
|
amounts_we_want_ll = [
|
||||||
[a] * max(0, n_target - amounts_we_have.count(a))
|
[a] * max(0, n_target - amounts_we_have.count(a))
|
||||||
for a in all_possible_amounts
|
for a in all_possible_amounts
|
||||||
|
|||||||
@@ -519,6 +519,8 @@ class Wallet(
|
|||||||
await store_bolt11_mint_quote(db=self.db, quote=quote)
|
await store_bolt11_mint_quote(db=self.db, quote=quote)
|
||||||
return quote
|
return quote
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def mint(
|
async def mint(
|
||||||
self,
|
self,
|
||||||
amount: int,
|
amount: int,
|
||||||
@@ -529,7 +531,7 @@ class Wallet(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
amount (int): Total amount of tokens to be minted
|
amount (int): Total amount of tokens to be minted
|
||||||
id (str): Id for looking up the paid Lightning invoice.
|
quote_id (str): Id for looking up the paid Lightning invoice.
|
||||||
split (Optional[List[str]], optional): List of desired amount splits to be minted. Total must sum to `amount`.
|
split (Optional[List[str]], optional): List of desired amount splits to be minted. Total must sum to `amount`.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -543,11 +545,11 @@ class Wallet(
|
|||||||
if split:
|
if split:
|
||||||
logger.trace(f"Mint with split: {split}")
|
logger.trace(f"Mint with split: {split}")
|
||||||
assert sum(split) == amount, "split must sum to amount"
|
assert sum(split) == amount, "split must sum to amount"
|
||||||
allowed_amounts = [2**i for i in range(settings.max_order)]
|
allowed_amounts = self.get_allowed_amounts() # Get allowed amounts from the mint
|
||||||
for a in split:
|
for a in split:
|
||||||
if a not in allowed_amounts:
|
if a not in allowed_amounts:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
f"Can only mint amounts with 2^n up to {2**settings.max_order}."
|
f"Can only mint amounts supported by the mint: {allowed_amounts}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# split based on our wallet state
|
# split based on our wallet state
|
||||||
|
|||||||
@@ -221,9 +221,10 @@ async def test_mint_amounts_wrong_order(wallet1: Wallet):
|
|||||||
"""Mint amount that is not part in 2^n"""
|
"""Mint amount that is not part in 2^n"""
|
||||||
amts = [1, 2, 3]
|
amts = [1, 2, 3]
|
||||||
mint_quote = await wallet1.request_mint(sum(amts))
|
mint_quote = await wallet1.request_mint(sum(amts))
|
||||||
|
allowed_amounts = wallet1.get_allowed_amounts()
|
||||||
await assert_err(
|
await assert_err(
|
||||||
wallet1.mint(amount=sum(amts), split=[1, 2, 3], quote_id=mint_quote.quote),
|
wallet1.mint(amount=sum(amts), split=[1, 2, 3], quote_id=mint_quote.quote),
|
||||||
f"Can only mint amounts with 2^n up to {2**settings.max_order}.",
|
f"Can only mint amounts supported by the mint: {allowed_amounts}",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user