mirror of
https://github.com/aljazceru/nutshell.git
synced 2026-02-02 23:34:21 +01:00
Wallet: add CLI flag --force-swap flag and force swapping all inactive keysets (#580)
* Wallet: add flag --force-swap to send command * Reame split to swap across codebase * rename remaining splits to swap * fix restore index with multiple keysets * fix wallet api restore
This commit is contained in:
@@ -222,19 +222,19 @@ class PostMeltRequest_deprecated(BaseModel):
|
||||
# ------- API: SPLIT -------
|
||||
|
||||
|
||||
class PostSplitRequest(BaseModel):
|
||||
class PostSwapRequest(BaseModel):
|
||||
inputs: List[Proof] = Field(..., max_items=settings.mint_max_request_length)
|
||||
outputs: List[BlindedMessage] = Field(
|
||||
..., max_items=settings.mint_max_request_length
|
||||
)
|
||||
|
||||
|
||||
class PostSplitResponse(BaseModel):
|
||||
class PostSwapResponse(BaseModel):
|
||||
signatures: List[BlindedSignature]
|
||||
|
||||
|
||||
# deprecated since 0.13.0
|
||||
class PostSplitRequest_Deprecated(BaseModel):
|
||||
class PostSwapRequest_Deprecated(BaseModel):
|
||||
proofs: List[Proof] = Field(..., max_items=settings.mint_max_request_length)
|
||||
amount: Optional[int] = None
|
||||
outputs: List[BlindedMessage_Deprecated] = Field(
|
||||
@@ -242,11 +242,11 @@ class PostSplitRequest_Deprecated(BaseModel):
|
||||
)
|
||||
|
||||
|
||||
class PostSplitResponse_Deprecated(BaseModel):
|
||||
class PostSwapResponse_Deprecated(BaseModel):
|
||||
promises: List[BlindedSignature] = []
|
||||
|
||||
|
||||
class PostSplitResponse_Very_Deprecated(BaseModel):
|
||||
class PostSwapResponse_Very_Deprecated(BaseModel):
|
||||
fst: List[BlindedSignature] = []
|
||||
snd: List[BlindedSignature] = []
|
||||
deprecated: str = "The amount field is deprecated since 0.13.0"
|
||||
|
||||
@@ -961,18 +961,18 @@ class Ledger(LedgerVerification, LedgerSpendingConditions, LedgerTasks, LedgerFe
|
||||
|
||||
return PostMeltQuoteResponse.from_melt_quote(melt_quote)
|
||||
|
||||
async def split(
|
||||
async def swap(
|
||||
self,
|
||||
*,
|
||||
proofs: List[Proof],
|
||||
outputs: List[BlindedMessage],
|
||||
keyset: Optional[MintKeyset] = None,
|
||||
):
|
||||
"""Consumes proofs and prepares new promises based on the amount split. Used for splitting tokens
|
||||
"""Consumes proofs and prepares new promises based on the amount swap. Used for swapping tokens
|
||||
Before sending or for redeeming tokens for new ones that have been received by another wallet.
|
||||
|
||||
Args:
|
||||
proofs (List[Proof]): Proofs to be invalidated for the split.
|
||||
proofs (List[Proof]): Proofs to be invalidated for the swap.
|
||||
outputs (List[BlindedMessage]): New outputs that should be signed in return.
|
||||
keyset (Optional[MintKeyset], optional): Keyset to use. Uses default keyset if not given. Defaults to None.
|
||||
|
||||
@@ -980,9 +980,9 @@ class Ledger(LedgerVerification, LedgerSpendingConditions, LedgerTasks, LedgerFe
|
||||
Exception: Validation of proofs or outputs failed
|
||||
|
||||
Returns:
|
||||
Tuple[List[BlindSignature],List[BlindSignature]]: Promises on both sides of the split.
|
||||
List[BlindedSignature]: New promises (signatures) for the outputs.
|
||||
"""
|
||||
logger.trace("split called")
|
||||
logger.trace("swap called")
|
||||
# verify spending inputs, outputs, and spending conditions
|
||||
await self.verify_inputs_and_outputs(proofs=proofs, outputs=outputs)
|
||||
await self.db_write._set_proofs_pending(proofs)
|
||||
@@ -991,13 +991,13 @@ class Ledger(LedgerVerification, LedgerSpendingConditions, LedgerTasks, LedgerFe
|
||||
await self._invalidate_proofs(proofs=proofs, conn=conn)
|
||||
promises = await self._generate_promises(outputs, keyset, conn)
|
||||
except Exception as e:
|
||||
logger.trace(f"split failed: {e}")
|
||||
logger.trace(f"swap failed: {e}")
|
||||
raise e
|
||||
finally:
|
||||
# delete proofs from pending list
|
||||
await self.db_write._unset_proofs_pending(proofs)
|
||||
|
||||
logger.trace("split successful")
|
||||
logger.trace("swap successful")
|
||||
return promises
|
||||
|
||||
async def restore(
|
||||
|
||||
@@ -21,8 +21,8 @@ from ..core.models import (
|
||||
PostMintResponse,
|
||||
PostRestoreRequest,
|
||||
PostRestoreResponse,
|
||||
PostSplitRequest,
|
||||
PostSplitResponse,
|
||||
PostSwapRequest,
|
||||
PostSwapResponse,
|
||||
)
|
||||
from ..core.settings import settings
|
||||
from ..mint.startup import ledger
|
||||
@@ -312,7 +312,7 @@ async def melt(request: Request, payload: PostMeltRequest) -> PostMeltQuoteRespo
|
||||
"/v1/swap",
|
||||
name="Swap tokens",
|
||||
summary="Swap inputs for outputs of the same value",
|
||||
response_model=PostSplitResponse,
|
||||
response_model=PostSwapResponse,
|
||||
response_description=(
|
||||
"An array of blinded signatures that can be used to create proofs."
|
||||
),
|
||||
@@ -320,20 +320,20 @@ async def melt(request: Request, payload: PostMeltRequest) -> PostMeltQuoteRespo
|
||||
@limiter.limit(f"{settings.mint_transaction_rate_limit_per_minute}/minute")
|
||||
async def swap(
|
||||
request: Request,
|
||||
payload: PostSplitRequest,
|
||||
) -> PostSplitResponse:
|
||||
payload: PostSwapRequest,
|
||||
) -> PostSwapResponse:
|
||||
"""
|
||||
Requests a set of Proofs to be split into two a new set of BlindedSignatures.
|
||||
Requests a set of Proofs to be swapped for another set of BlindSignatures.
|
||||
|
||||
This endpoint is used by Alice to split a set of proofs before making a payment to Carol.
|
||||
It is then used by Carol (by setting split=total) to redeem the tokens.
|
||||
This endpoint can be used by Alice to swap a set of proofs before making a payment to Carol.
|
||||
It can then used by Carol to redeem the tokens for new proofs.
|
||||
"""
|
||||
logger.trace(f"> POST /v1/swap: {payload}")
|
||||
assert payload.outputs, Exception("no outputs provided.")
|
||||
|
||||
signatures = await ledger.split(proofs=payload.inputs, outputs=payload.outputs)
|
||||
signatures = await ledger.swap(proofs=payload.inputs, outputs=payload.outputs)
|
||||
|
||||
return PostSplitResponse(signatures=signatures)
|
||||
return PostSwapResponse(signatures=signatures)
|
||||
|
||||
|
||||
@router.post(
|
||||
|
||||
@@ -22,9 +22,9 @@ from ..core.models import (
|
||||
PostMintResponse_deprecated,
|
||||
PostRestoreRequest_Deprecated,
|
||||
PostRestoreResponse,
|
||||
PostSplitRequest_Deprecated,
|
||||
PostSplitResponse_Deprecated,
|
||||
PostSplitResponse_Very_Deprecated,
|
||||
PostSwapRequest_Deprecated,
|
||||
PostSwapResponse_Deprecated,
|
||||
PostSwapResponse_Very_Deprecated,
|
||||
)
|
||||
from ..core.settings import settings
|
||||
from .limit import limiter
|
||||
@@ -270,7 +270,7 @@ async def check_fees(
|
||||
name="Split",
|
||||
summary="Split proofs at a specified amount",
|
||||
# response_model=Union[
|
||||
# PostSplitResponse_Very_Deprecated, PostSplitResponse_Deprecated
|
||||
# PostSwapResponse_Very_Deprecated, PostSwapResponse_Deprecated
|
||||
# ],
|
||||
response_description=(
|
||||
"A list of blinded signatures that can be used to create proofs."
|
||||
@@ -280,8 +280,8 @@ async def check_fees(
|
||||
@limiter.limit(f"{settings.mint_transaction_rate_limit_per_minute}/minute")
|
||||
async def split_deprecated(
|
||||
request: Request,
|
||||
payload: PostSplitRequest_Deprecated,
|
||||
# ) -> Union[PostSplitResponse_Very_Deprecated, PostSplitResponse_Deprecated]:
|
||||
payload: PostSwapRequest_Deprecated,
|
||||
# ) -> Union[PostSwapResponse_Very_Deprecated, PostSwapResponse_Deprecated]:
|
||||
):
|
||||
"""
|
||||
Requests a set of Proofs to be split into two a new set of BlindedSignatures.
|
||||
@@ -297,7 +297,7 @@ async def split_deprecated(
|
||||
for o in payload.outputs
|
||||
]
|
||||
# END BACKWARDS COMPATIBILITY < 0.14
|
||||
promises = await ledger.split(proofs=payload.proofs, outputs=outputs)
|
||||
promises = await ledger.swap(proofs=payload.proofs, outputs=outputs)
|
||||
|
||||
if payload.amount:
|
||||
# BEGIN backwards compatibility < 0.13
|
||||
@@ -319,10 +319,10 @@ async def split_deprecated(
|
||||
f" {sum([p.amount for p in frst_promises])} sat and send:"
|
||||
f" {len(scnd_promises)}: {sum([p.amount for p in scnd_promises])} sat"
|
||||
)
|
||||
return PostSplitResponse_Very_Deprecated(fst=frst_promises, snd=scnd_promises)
|
||||
return PostSwapResponse_Very_Deprecated(fst=frst_promises, snd=scnd_promises)
|
||||
# END backwards compatibility < 0.13
|
||||
else:
|
||||
return PostSplitResponse_Deprecated(promises=promises)
|
||||
return PostSwapResponse_Deprecated(promises=promises)
|
||||
|
||||
|
||||
@router_deprecated.post(
|
||||
|
||||
@@ -194,7 +194,7 @@ async def swap(
|
||||
if outgoing_wallet.available_balance < total_amount:
|
||||
raise Exception("balance too low")
|
||||
|
||||
_, send_proofs = await outgoing_wallet.split_to_send(
|
||||
_, send_proofs = await outgoing_wallet.swap_to_send(
|
||||
outgoing_wallet.proofs, total_amount, set_reserved=True
|
||||
)
|
||||
await outgoing_wallet.melt(
|
||||
@@ -433,7 +433,7 @@ async def restore(
|
||||
if to < 0:
|
||||
raise Exception("Counter must be positive")
|
||||
await wallet.load_mint()
|
||||
await wallet.restore_promises_from_to(0, to)
|
||||
await wallet.restore_promises_from_to(wallet.keyset_id, 0, to)
|
||||
await wallet.invalidate(wallet.proofs, check_spendable=True)
|
||||
return RestoreResponse(balance=wallet.available_balance)
|
||||
|
||||
|
||||
@@ -548,6 +548,14 @@ async def balance(ctx: Context, verbose):
|
||||
help="Include fees for receiving token.",
|
||||
type=bool,
|
||||
)
|
||||
@click.option(
|
||||
"--force-swap",
|
||||
"-s",
|
||||
default=False,
|
||||
is_flag=True,
|
||||
help="Force swap token.",
|
||||
type=bool,
|
||||
)
|
||||
@click.pass_context
|
||||
@coro
|
||||
async def send_command(
|
||||
@@ -562,6 +570,7 @@ async def send_command(
|
||||
yes: bool,
|
||||
offline: bool,
|
||||
include_fees: bool,
|
||||
force_swap: bool,
|
||||
):
|
||||
wallet: Wallet = ctx.obj["WALLET"]
|
||||
amount = int(amount * 100) if wallet.unit in [Unit.usd, Unit.eur] else int(amount)
|
||||
@@ -575,6 +584,7 @@ async def send_command(
|
||||
include_dleq=dleq,
|
||||
include_fees=include_fees,
|
||||
memo=memo,
|
||||
force_swap=force_swap,
|
||||
)
|
||||
else:
|
||||
await send_nostr(wallet, amount=amount, pubkey=nostr, verbose=verbose, yes=yes)
|
||||
|
||||
@@ -116,6 +116,7 @@ async def send(
|
||||
include_dleq: bool = False,
|
||||
include_fees: bool = False,
|
||||
memo: Optional[str] = None,
|
||||
force_swap: bool = False,
|
||||
):
|
||||
"""
|
||||
Prints token to send to stdout.
|
||||
@@ -144,13 +145,12 @@ async def send(
|
||||
await wallet.load_proofs()
|
||||
|
||||
await wallet.load_mint()
|
||||
if secret_lock:
|
||||
_, send_proofs = await wallet.split_to_send(
|
||||
if secret_lock or force_swap:
|
||||
_, send_proofs = await wallet.swap_to_send(
|
||||
wallet.proofs,
|
||||
amount,
|
||||
set_reserved=False, # we set reserved later
|
||||
secret_lock=secret_lock,
|
||||
include_fees=include_fees,
|
||||
)
|
||||
else:
|
||||
send_proofs, fees = await wallet.select_to_send(
|
||||
|
||||
@@ -61,7 +61,7 @@ class LightningWallet(Wallet):
|
||||
if self.available_balance < total_amount:
|
||||
print("Error: Balance too low.")
|
||||
return PaymentResponse(ok=False)
|
||||
_, send_proofs = await self.split_to_send(self.proofs, total_amount)
|
||||
_, send_proofs = await self.swap_to_send(self.proofs, total_amount)
|
||||
try:
|
||||
resp = await self.melt(send_proofs, pr, quote.fee_reserve, quote.quote)
|
||||
if resp.change:
|
||||
|
||||
@@ -62,7 +62,7 @@ async def send_nostr(
|
||||
pubkey = await nip5_to_pubkey(wallet, pubkey)
|
||||
await wallet.load_mint()
|
||||
await wallet.load_proofs()
|
||||
_, send_proofs = await wallet.split_to_send(
|
||||
_, send_proofs = await wallet.swap_to_send(
|
||||
wallet.proofs, amount, set_reserved=True, include_fees=False
|
||||
)
|
||||
token = await wallet.serialize_proofs(send_proofs, include_dleq=include_dleq)
|
||||
|
||||
@@ -148,6 +148,7 @@ class WalletProofs(SupportsDb, SupportsKeysets):
|
||||
try:
|
||||
_ = [bytes.fromhex(p.id) for p in proofs]
|
||||
except ValueError:
|
||||
logger.debug("Proof with base64 keyset, using legacy token serialization")
|
||||
legacy = True
|
||||
|
||||
if legacy:
|
||||
|
||||
@@ -105,27 +105,28 @@ class WalletSecrets(SupportsDb, SupportsKeysets):
|
||||
return hashlib.sha256(os.urandom(32)).hexdigest()
|
||||
|
||||
async def generate_determinstic_secret(
|
||||
self, counter: int
|
||||
self, counter: int, keyset_id: Optional[str] = None
|
||||
) -> Tuple[bytes, bytes, str]:
|
||||
"""
|
||||
Determinstically generates two secrets (one as the secret message,
|
||||
one as the blinding factor).
|
||||
"""
|
||||
assert self.bip32, "BIP32 not initialized yet."
|
||||
keyset_id = keyset_id or self.keyset_id
|
||||
# integer keyset id modulo max number of bip32 child keys
|
||||
try:
|
||||
keyest_id_int = int.from_bytes(bytes.fromhex(self.keyset_id), "big") % (
|
||||
keyest_id_int = int.from_bytes(bytes.fromhex(keyset_id), "big") % (
|
||||
2**31 - 1
|
||||
)
|
||||
except ValueError:
|
||||
# BEGIN: BACKWARDS COMPATIBILITY < 0.15.0 keyset id is not hex
|
||||
# calculate an integer keyset id from the base64 encoded keyset id
|
||||
keyest_id_int = int.from_bytes(base64.b64decode(self.keyset_id), "big") % (
|
||||
keyest_id_int = int.from_bytes(base64.b64decode(keyset_id), "big") % (
|
||||
2**31 - 1
|
||||
)
|
||||
# END: BACKWARDS COMPATIBILITY < 0.15.0 keyset id is not hex
|
||||
|
||||
logger.trace(f"keyset id: {self.keyset_id} becomes {keyest_id_int}")
|
||||
logger.trace(f"keyset id: {keyset_id} becomes {keyest_id_int}")
|
||||
token_derivation_path = f"m/129372'/0'/{keyest_id_int}'/{counter}'"
|
||||
# for secret
|
||||
secret_derivation_path = f"{token_derivation_path}/0"
|
||||
@@ -177,13 +178,14 @@ class WalletSecrets(SupportsDb, SupportsKeysets):
|
||||
return secrets, rs, derivation_paths
|
||||
|
||||
async def generate_secrets_from_to(
|
||||
self, from_counter: int, to_counter: int
|
||||
self, from_counter: int, to_counter: int, keyset_id: Optional[str] = None
|
||||
) -> Tuple[List[str], List[PrivateKey], List[str]]:
|
||||
"""Generates secrets and blinding factors from `from_counter` to `to_counter`
|
||||
|
||||
Args:
|
||||
from_counter (int): Start counter
|
||||
to_counter (int): End counter
|
||||
keyset_id (Optional[str], optional): Keyset id. Defaults to None.
|
||||
|
||||
Returns:
|
||||
Tuple[List[str], List[PrivateKey], List[str]]: Secrets, blinding factors, derivation paths
|
||||
@@ -196,7 +198,8 @@ class WalletSecrets(SupportsDb, SupportsKeysets):
|
||||
), "from_counter must be smaller than to_counter"
|
||||
secret_counters = [c for c in range(from_counter, to_counter + 1)]
|
||||
secrets_rs_derivationpaths = [
|
||||
await self.generate_determinstic_secret(s) for s in secret_counters
|
||||
await self.generate_determinstic_secret(s, keyset_id)
|
||||
for s in secret_counters
|
||||
]
|
||||
# secrets are supplied as str
|
||||
secrets = [s[0].hex() for s in secrets_rs_derivationpaths]
|
||||
|
||||
@@ -36,7 +36,7 @@ class WalletTransactions(SupportsDb, SupportsKeysets):
|
||||
def get_fees_for_proofs_ppk(self, proofs: List[Proof]) -> int:
|
||||
return sum([self.keysets[p.id].input_fee_ppk for p in proofs])
|
||||
|
||||
async def _select_proofs_to_send_(
|
||||
async def _select_proofs_to_send_legacy(
|
||||
self, proofs: List[Proof], amount_to_send: int, tolerance: int = 0
|
||||
) -> List[Proof]:
|
||||
send_proofs: List[Proof] = []
|
||||
@@ -63,9 +63,6 @@ class WalletTransactions(SupportsDb, SupportsKeysets):
|
||||
# compose the target amount from the remaining_proofs
|
||||
logger.debug(f"sorted_proofs: {[p.amount for p in sorted_proofs]}")
|
||||
for p in sorted_proofs:
|
||||
# logger.debug(f"send_proofs: {[p.amount for p in send_proofs]}")
|
||||
# logger.debug(f"target_amount: {target_amount}")
|
||||
# logger.debug(f"p.amount: {p.amount}")
|
||||
if sum_proofs(send_proofs) + p.amount <= target_amount + tolerance:
|
||||
send_proofs.append(p)
|
||||
target_amount = amount_to_send + self.get_fees_for_proofs(send_proofs)
|
||||
@@ -83,8 +80,19 @@ class WalletTransactions(SupportsDb, SupportsKeysets):
|
||||
proofs: List[Proof],
|
||||
amount_to_send: Union[int, float],
|
||||
*,
|
||||
include_fees: bool = True,
|
||||
include_fees: bool = False,
|
||||
) -> List[Proof]:
|
||||
"""Select proofs to send based on the amount to send and the proofs available. Implements a simple coin selection algorithm.
|
||||
Can be used for selecting proofs to send an offline transaction.
|
||||
|
||||
Args:
|
||||
proofs (List[Proof]): List of proofs to select from
|
||||
amount_to_send (Union[int, float]): Amount to select proofs for
|
||||
include_fees (bool, optional): Whether to include fees necessary to redeem the tokens in the selection. Defaults to False.
|
||||
|
||||
Returns:
|
||||
List[Proof]: _description_
|
||||
"""
|
||||
# check that enough spendable proofs exist
|
||||
if sum_proofs(proofs) < amount_to_send:
|
||||
return []
|
||||
@@ -136,7 +144,7 @@ class WalletTransactions(SupportsDb, SupportsKeysets):
|
||||
)
|
||||
return selected_proofs
|
||||
|
||||
async def _select_proofs_to_split(
|
||||
async def _select_proofs_to_swap(
|
||||
self, proofs: List[Proof], amount_to_send: int
|
||||
) -> Tuple[List[Proof], int]:
|
||||
"""
|
||||
@@ -147,9 +155,8 @@ class WalletTransactions(SupportsDb, SupportsKeysets):
|
||||
|
||||
Rules:
|
||||
1) Proofs that are not marked as reserved
|
||||
2) Proofs that have a different keyset than the activated keyset_id of the mint
|
||||
3) Include all proofs that have an older keyset than the current keyset of the mint (to get rid of old epochs).
|
||||
4) If the target amount is not reached, add proofs of the current keyset until it is.
|
||||
2) Include all proofs from inactive keysets (old epochs) to get rid of them
|
||||
3) If the target amount is not reached, add proofs of the current keyset until it is.
|
||||
|
||||
Args:
|
||||
proofs (List[Proof]): List of proofs to select from
|
||||
@@ -163,7 +170,7 @@ class WalletTransactions(SupportsDb, SupportsKeysets):
|
||||
Exception: If the balance is too low to send the amount
|
||||
"""
|
||||
logger.debug(
|
||||
f"_select_proofs_to_split - amounts we have: {amount_summary(proofs, self.unit)}"
|
||||
f"_select_proofs_to_swap - amounts we have: {amount_summary(proofs, self.unit)}"
|
||||
)
|
||||
send_proofs: List[Proof] = []
|
||||
|
||||
@@ -171,11 +178,9 @@ class WalletTransactions(SupportsDb, SupportsKeysets):
|
||||
if sum_proofs(proofs) < amount_to_send:
|
||||
raise Exception("balance too low.")
|
||||
|
||||
# add all proofs that have an older keyset than the current keyset of the mint
|
||||
proofs_old_epochs = [
|
||||
p for p in proofs if p.id != self.keysets[self.keyset_id].id
|
||||
]
|
||||
send_proofs += proofs_old_epochs
|
||||
# add all proofs from inactive keysets
|
||||
proofs_inactive_keysets = [p for p in proofs if not self.keysets[p.id].active]
|
||||
send_proofs += proofs_inactive_keysets
|
||||
|
||||
# coinselect based on amount only from the current keyset
|
||||
# start with the proofs with the largest amount and add them until the target amount is reached
|
||||
@@ -193,7 +198,7 @@ class WalletTransactions(SupportsDb, SupportsKeysets):
|
||||
send_proofs.append(proof_to_add)
|
||||
|
||||
logger.trace(
|
||||
f"_select_proofs_to_split – selected proof amounts: {[p.amount for p in send_proofs]}"
|
||||
f"_select_proofs_to_swap – selected proof amounts: {[p.amount for p in send_proofs]}"
|
||||
)
|
||||
fees = self.get_fees_for_proofs(send_proofs)
|
||||
return send_proofs, fees
|
||||
|
||||
@@ -39,8 +39,8 @@ from ..core.models import (
|
||||
PostMintRequest,
|
||||
PostMintResponse,
|
||||
PostRestoreResponse,
|
||||
PostSplitRequest,
|
||||
PostSplitResponse,
|
||||
PostSwapRequest,
|
||||
PostSwapResponse,
|
||||
)
|
||||
from ..core.settings import settings
|
||||
from ..tor.tor import TorProxy
|
||||
@@ -465,7 +465,7 @@ class LedgerAPI(LedgerAPIDeprecated, object):
|
||||
) -> List[BlindedSignature]:
|
||||
"""Consume proofs and create new promises based on amount split."""
|
||||
logger.debug("Calling split. POST /v1/swap")
|
||||
split_payload = PostSplitRequest(inputs=proofs, outputs=outputs)
|
||||
split_payload = PostSwapRequest(inputs=proofs, outputs=outputs)
|
||||
|
||||
# construct payload
|
||||
def _splitrequest_include_fields(proofs: List[Proof]):
|
||||
@@ -494,7 +494,7 @@ class LedgerAPI(LedgerAPIDeprecated, object):
|
||||
# END backwards compatibility < 0.15.0
|
||||
self.raise_on_error_request(resp)
|
||||
promises_dict = resp.json()
|
||||
mint_response = PostSplitResponse.parse_obj(promises_dict)
|
||||
mint_response = PostSwapResponse.parse_obj(promises_dict)
|
||||
promises = [BlindedSignature(**p.dict()) for p in mint_response.signatures]
|
||||
|
||||
if len(promises) == 0:
|
||||
|
||||
@@ -85,7 +85,7 @@ class Wallet(
|
||||
"""
|
||||
|
||||
keyset_id: str # holds current keyset id
|
||||
keysets: Dict[str, WalletKeyset] # holds keysets
|
||||
keysets: Dict[str, WalletKeyset] = {} # holds keysets
|
||||
# mint_keyset_ids: List[str] # holds active keyset ids of the mint
|
||||
unit: Unit
|
||||
mint_info: MintInfo # holds info about mint
|
||||
@@ -178,7 +178,7 @@ class Wallet(
|
||||
logger.debug(f"Mint info: {self.mint_info}")
|
||||
return self.mint_info
|
||||
|
||||
async def load_mint_keysets(self):
|
||||
async def load_mint_keysets(self, force_old_keysets=False):
|
||||
"""Loads all keyset of the mint and makes sure we have them all in the database.
|
||||
|
||||
Then loads all keysets from the database for the active mint and active unit into self.keysets.
|
||||
@@ -237,7 +237,7 @@ class Wallet(
|
||||
)
|
||||
|
||||
# BEGIN backwards compatibility: phase out keysets with base64 ID by treating them as inactive
|
||||
if settings.wallet_inactivate_legacy_keysets:
|
||||
if settings.wallet_inactivate_legacy_keysets and not force_old_keysets:
|
||||
keysets_in_db = await get_keysets(mint_url=self.url, db=self.db)
|
||||
for keyset in keysets_in_db:
|
||||
if not keyset.active:
|
||||
@@ -306,14 +306,19 @@ class Wallet(
|
||||
|
||||
logger.debug(f"Activated keyset {self.keyset_id}")
|
||||
|
||||
async def load_mint(self, keyset_id: str = "") -> None:
|
||||
async def load_mint(self, keyset_id: str = "", force_old_keysets=False) -> None:
|
||||
"""
|
||||
Loads the public keys of the mint. Either gets the keys for the specified
|
||||
`keyset_id` or gets the keys of the active keyset from the mint.
|
||||
Gets the active keyset ids of the mint and stores in `self.mint_keyset_ids`.
|
||||
|
||||
Args:
|
||||
keyset_id (str, optional): Keyset id to load. Defaults to "".
|
||||
force_old_keysets (bool, optional): If true, old deprecated base64 keysets are not ignored. This is necessary for restoring tokens from old base64 keysets.
|
||||
Defaults to False.
|
||||
"""
|
||||
logger.trace("Loading mint.")
|
||||
await self.load_mint_keysets()
|
||||
await self.load_mint_keysets(force_old_keysets)
|
||||
await self.activate_keyset(keyset_id)
|
||||
try:
|
||||
await self.load_mint_info()
|
||||
@@ -902,6 +907,7 @@ class Wallet(
|
||||
amounts: List[int],
|
||||
secrets: List[str],
|
||||
rs: List[PrivateKey] = [],
|
||||
keyset_id: Optional[str] = None,
|
||||
) -> Tuple[List[BlindedMessage], List[PrivateKey]]:
|
||||
"""Takes a list of amounts and secrets and returns outputs.
|
||||
Outputs are blinded messages `outputs` and blinding factors `rs`
|
||||
@@ -921,8 +927,8 @@ class Wallet(
|
||||
assert len(amounts) == len(
|
||||
secrets
|
||||
), f"len(amounts)={len(amounts)} not equal to len(secrets)={len(secrets)}"
|
||||
keyset_id = keyset_id or self.keyset_id
|
||||
outputs: List[BlindedMessage] = []
|
||||
|
||||
rs_ = [None] * len(amounts) if not rs else rs
|
||||
rs_return: List[PrivateKey] = []
|
||||
for secret, amount, r in zip(secrets, amounts, rs_):
|
||||
@@ -935,7 +941,7 @@ class Wallet(
|
||||
|
||||
rs_return.append(r)
|
||||
output = BlindedMessage(
|
||||
amount=amount, B_=B_.serialize().hex(), id=self.keyset_id
|
||||
amount=amount, B_=B_.serialize().hex(), id=keyset_id
|
||||
)
|
||||
outputs.append(output)
|
||||
logger.trace(f"Constructing output: {output}, r: {r.serialize()}")
|
||||
@@ -1049,7 +1055,7 @@ class Wallet(
|
||||
if not offline:
|
||||
logger.debug("Offline coin selection unsuccessful. Splitting proofs.")
|
||||
# we set the proofs as reserved later
|
||||
_, send_proofs = await self.split_to_send(
|
||||
_, send_proofs = await self.swap_to_send(
|
||||
proofs, amount, set_reserved=False
|
||||
)
|
||||
else:
|
||||
@@ -1061,7 +1067,7 @@ class Wallet(
|
||||
await self.set_reserved(send_proofs, reserved=True)
|
||||
return send_proofs, fees
|
||||
|
||||
async def split_to_send(
|
||||
async def swap_to_send(
|
||||
self,
|
||||
proofs: List[Proof],
|
||||
amount: int,
|
||||
@@ -1093,7 +1099,7 @@ class Wallet(
|
||||
raise Exception("balance too low.")
|
||||
|
||||
# coin selection for swapping
|
||||
# spendable_proofs, fees = await self._select_proofs_to_split(proofs, amount)
|
||||
# spendable_proofs, fees = await self._select_proofs_to_swap(proofs, amount)
|
||||
swap_proofs = await self._select_proofs_to_send(
|
||||
proofs, amount, include_fees=True
|
||||
)
|
||||
@@ -1195,31 +1201,41 @@ class Wallet(
|
||||
to (int, optional): The number of consecutive empty responses to stop restoring. Defaults to 2.
|
||||
batch (int, optional): The number of proofs to restore in one batch. Defaults to 25.
|
||||
"""
|
||||
stop_counter = 0
|
||||
empty_batches = 0
|
||||
# we get the current secret counter and restore from there on
|
||||
spendable_proofs = []
|
||||
counter_before = await bump_secret_derivation(
|
||||
db=self.db, keyset_id=keyset_id, by=0
|
||||
)
|
||||
if counter_before != 0:
|
||||
print("Keyset has already been used. Restoring from it's last state.")
|
||||
print("Keyset has already been used. Restoring from its last state.")
|
||||
i = counter_before
|
||||
n_last_restored_proofs = 0
|
||||
while stop_counter < to:
|
||||
print(f"Restoring token {i} to {i + batch}...")
|
||||
restored_proofs = await self.restore_promises_from_to(i, i + batch - 1)
|
||||
last_restore_count = 0
|
||||
while empty_batches < to:
|
||||
print(f"Restoring counter {i} to {i + batch} for keyset {keyset_id} ...")
|
||||
(
|
||||
next_restored_output_index,
|
||||
restored_proofs,
|
||||
) = await self.restore_promises_from_to(keyset_id, i, i + batch - 1)
|
||||
last_restore_count += next_restored_output_index
|
||||
i += batch
|
||||
if len(restored_proofs) == 0:
|
||||
stop_counter += 1
|
||||
empty_batches += 1
|
||||
continue
|
||||
spendable_proofs = await self.invalidate(
|
||||
restored_proofs, check_spendable=True
|
||||
)
|
||||
if len(spendable_proofs):
|
||||
n_last_restored_proofs = len(spendable_proofs)
|
||||
print(f"Restored {sum_proofs(restored_proofs)} sat")
|
||||
i += batch
|
||||
print(
|
||||
f"Restored {sum_proofs(spendable_proofs)} sat for keyset {keyset_id}."
|
||||
)
|
||||
else:
|
||||
logger.debug(
|
||||
f"None of the {len(restored_proofs)} restored proofs are spendable."
|
||||
)
|
||||
|
||||
# restore the secret counter to its previous value for the last round
|
||||
revert_counter_by = batch * to + n_last_restored_proofs
|
||||
revert_counter_by = i - last_restore_count
|
||||
logger.debug(f"Reverting secret counter by {revert_counter_by}")
|
||||
before = await bump_secret_derivation(
|
||||
db=self.db,
|
||||
@@ -1229,8 +1245,8 @@ class Wallet(
|
||||
logger.debug(
|
||||
f"Secret counter reverted from {before} to {before - revert_counter_by}"
|
||||
)
|
||||
if n_last_restored_proofs == 0:
|
||||
print("No tokens restored for keyset.")
|
||||
if last_restore_count == 0:
|
||||
print(f"No tokens restored for keyset {keyset_id}.")
|
||||
return
|
||||
|
||||
async def restore_wallet_from_mnemonic(
|
||||
@@ -1245,14 +1261,14 @@ class Wallet(
|
||||
batch (int, optional): The number of proofs to restore in one batch. Defaults to 25.
|
||||
"""
|
||||
await self._init_private_key(mnemonic)
|
||||
await self.load_mint()
|
||||
await self.load_mint(force_old_keysets=False)
|
||||
print("Restoring tokens...")
|
||||
for keyset_id in self.keysets.keys():
|
||||
await self.restore_tokens_for_keyset(keyset_id, to, batch)
|
||||
|
||||
async def restore_promises_from_to(
|
||||
self, from_counter: int, to_counter: int
|
||||
) -> List[Proof]:
|
||||
self, keyset_id: str, from_counter: int, to_counter: int
|
||||
) -> Tuple[int, List[Proof]]:
|
||||
"""Restores promises from a given range of counters. This is for restoring a wallet from a mnemonic.
|
||||
|
||||
Args:
|
||||
@@ -1260,18 +1276,20 @@ class Wallet(
|
||||
to_counter (int): Counter for the secret derivation to end at
|
||||
|
||||
Returns:
|
||||
List[Proof]: List of restored proofs
|
||||
Tuple[int, List[Proof]]: Index of the last restored output and list of restored proofs
|
||||
"""
|
||||
# we regenerate the secrets and rs for the given range
|
||||
secrets, rs, derivation_paths = await self.generate_secrets_from_to(
|
||||
from_counter, to_counter
|
||||
from_counter, to_counter, keyset_id=keyset_id
|
||||
)
|
||||
# we don't know the amount but luckily the mint will tell us so we use a dummy amount here
|
||||
amounts_dummy = [1] * len(secrets)
|
||||
# we generate outputs from deterministic secrets and rs
|
||||
regenerated_outputs, _ = self._construct_outputs(amounts_dummy, secrets, rs)
|
||||
regenerated_outputs, _ = self._construct_outputs(
|
||||
amounts_dummy, secrets, rs, keyset_id=keyset_id
|
||||
)
|
||||
# we ask the mint to reissue the promises
|
||||
proofs = await self.restore_promises(
|
||||
next_restored_output_index, proofs = await self.restore_promises(
|
||||
outputs=regenerated_outputs,
|
||||
secrets=secrets,
|
||||
rs=rs,
|
||||
@@ -1279,9 +1297,9 @@ class Wallet(
|
||||
)
|
||||
|
||||
await set_secret_derivation(
|
||||
db=self.db, keyset_id=self.keyset_id, counter=to_counter + 1
|
||||
db=self.db, keyset_id=keyset_id, counter=to_counter + 1
|
||||
)
|
||||
return proofs
|
||||
return next_restored_output_index, proofs
|
||||
|
||||
async def restore_promises(
|
||||
self,
|
||||
@@ -1289,7 +1307,7 @@ class Wallet(
|
||||
secrets: List[str],
|
||||
rs: List[PrivateKey],
|
||||
derivation_paths: List[str],
|
||||
) -> List[Proof]:
|
||||
) -> Tuple[int, List[Proof]]:
|
||||
"""Restores proofs from a list of outputs, secrets, rs and derivation paths.
|
||||
|
||||
Args:
|
||||
@@ -1299,10 +1317,26 @@ class Wallet(
|
||||
derivation_paths (List[str]): Derivation paths used for the secrets necessary to unblind the promises
|
||||
|
||||
Returns:
|
||||
List[Proof]: List of restored proofs
|
||||
Tuple[int, List[Proof]]: Index of the last restored output and list of restored proofs
|
||||
"""
|
||||
# restored_outputs is there so we can match the promises to the secrets and rs
|
||||
restored_outputs, restored_promises = await super().restore_promises(outputs)
|
||||
# determine the index in `outputs` of the last restored output from restored_outputs[-1].B_
|
||||
if not restored_outputs:
|
||||
next_restored_output_index = 0
|
||||
else:
|
||||
next_restored_output_index = (
|
||||
next(
|
||||
(
|
||||
idx
|
||||
for idx, val in enumerate(outputs)
|
||||
if val.B_ == restored_outputs[-1].B_
|
||||
),
|
||||
0,
|
||||
)
|
||||
+ 1
|
||||
)
|
||||
logger.trace(f"Last restored output index: {next_restored_output_index}")
|
||||
# now we need to filter out the secrets and rs that had a match
|
||||
matching_indices = [
|
||||
idx
|
||||
@@ -1311,9 +1345,12 @@ class Wallet(
|
||||
]
|
||||
secrets = [secrets[i] for i in matching_indices]
|
||||
rs = [rs[i] for i in matching_indices]
|
||||
logger.debug(
|
||||
f"Restored {len(restored_promises)} promises. Constructing proofs."
|
||||
)
|
||||
# now we can construct the proofs with the secrets and rs
|
||||
proofs = await self._construct_proofs(
|
||||
restored_promises, secrets, rs, derivation_paths
|
||||
)
|
||||
logger.debug(f"Restored {len(restored_promises)} promises")
|
||||
return proofs
|
||||
return next_restored_output_index, proofs
|
||||
|
||||
@@ -31,8 +31,8 @@ from ..core.models import (
|
||||
PostMintRequest_deprecated,
|
||||
PostMintResponse_deprecated,
|
||||
PostRestoreResponse,
|
||||
PostSplitRequest_Deprecated,
|
||||
PostSplitResponse_Deprecated,
|
||||
PostSwapRequest_Deprecated,
|
||||
PostSwapResponse_Deprecated,
|
||||
)
|
||||
from ..core.settings import settings
|
||||
from ..tor.tor import TorProxy
|
||||
@@ -348,7 +348,7 @@ class LedgerAPIDeprecated(SupportsHttpxClient, SupportsMintURL):
|
||||
"""Consume proofs and create new promises based on amount split."""
|
||||
logger.warning("Using deprecated API call: Calling split. POST /split")
|
||||
outputs_deprecated = [BlindedMessage_Deprecated(**o.dict()) for o in outputs]
|
||||
split_payload = PostSplitRequest_Deprecated(
|
||||
split_payload = PostSwapRequest_Deprecated(
|
||||
proofs=proofs, outputs=outputs_deprecated
|
||||
)
|
||||
|
||||
@@ -373,7 +373,7 @@ class LedgerAPIDeprecated(SupportsHttpxClient, SupportsMintURL):
|
||||
)
|
||||
self.raise_on_error(resp)
|
||||
promises_dict = resp.json()
|
||||
mint_response = PostSplitResponse_Deprecated.parse_obj(promises_dict)
|
||||
mint_response = PostSwapResponse_Deprecated.parse_obj(promises_dict)
|
||||
promises = [BlindedSignature(**p.dict()) for p in mint_response.promises]
|
||||
|
||||
if len(promises) == 0:
|
||||
|
||||
@@ -422,7 +422,7 @@ async def test_melt_external(ledger: Ledger, wallet: Wallet):
|
||||
assert quote.amount == 62
|
||||
assert quote.fee_reserve == 2
|
||||
|
||||
keep, send = await wallet.split_to_send(wallet.proofs, 64)
|
||||
keep, send = await wallet.swap_to_send(wallet.proofs, 64)
|
||||
inputs_payload = [p.to_dict() for p in send]
|
||||
|
||||
# outputs for change
|
||||
|
||||
@@ -123,7 +123,7 @@ async def test_split_with_fees(wallet1: Wallet, ledger: Ledger):
|
||||
assert fees == 1
|
||||
outputs = await wallet1.construct_outputs(amount_split(9))
|
||||
|
||||
promises = await ledger.split(proofs=send_proofs, outputs=outputs)
|
||||
promises = await ledger.swap(proofs=send_proofs, outputs=outputs)
|
||||
assert len(promises) == len(outputs)
|
||||
assert [p.amount for p in promises] == [p.amount for p in outputs]
|
||||
|
||||
@@ -141,7 +141,7 @@ async def test_split_with_high_fees(wallet1: Wallet, ledger: Ledger):
|
||||
assert fees == 3
|
||||
outputs = await wallet1.construct_outputs(amount_split(7))
|
||||
|
||||
promises = await ledger.split(proofs=send_proofs, outputs=outputs)
|
||||
promises = await ledger.swap(proofs=send_proofs, outputs=outputs)
|
||||
assert len(promises) == len(outputs)
|
||||
assert [p.amount for p in promises] == [p.amount for p in outputs]
|
||||
|
||||
@@ -161,7 +161,7 @@ async def test_split_not_enough_fees(wallet1: Wallet, ledger: Ledger):
|
||||
outputs = await wallet1.construct_outputs(amount_split(10))
|
||||
|
||||
await assert_err(
|
||||
ledger.split(proofs=send_proofs, outputs=outputs), "are not balanced"
|
||||
ledger.swap(proofs=send_proofs, outputs=outputs), "are not balanced"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ async def test_startup_regtest_pending_quote_pending(wallet: Wallet, ledger: Led
|
||||
# wallet pays the invoice
|
||||
quote = await wallet.melt_quote(invoice_payment_request)
|
||||
total_amount = quote.amount + quote.fee_reserve
|
||||
_, send_proofs = await wallet.split_to_send(wallet.proofs, total_amount)
|
||||
_, send_proofs = await wallet.swap_to_send(wallet.proofs, total_amount)
|
||||
asyncio.create_task(
|
||||
wallet.melt(
|
||||
proofs=send_proofs,
|
||||
@@ -297,7 +297,7 @@ async def test_startup_regtest_pending_quote_success(wallet: Wallet, ledger: Led
|
||||
# wallet pays the invoice
|
||||
quote = await wallet.melt_quote(invoice_payment_request)
|
||||
total_amount = quote.amount + quote.fee_reserve
|
||||
_, send_proofs = await wallet.split_to_send(wallet.proofs, total_amount)
|
||||
_, send_proofs = await wallet.swap_to_send(wallet.proofs, total_amount)
|
||||
asyncio.create_task(
|
||||
wallet.melt(
|
||||
proofs=send_proofs,
|
||||
@@ -347,7 +347,7 @@ async def test_startup_regtest_pending_quote_failure(wallet: Wallet, ledger: Led
|
||||
# wallet pays the invoice
|
||||
quote = await wallet.melt_quote(invoice_payment_request)
|
||||
total_amount = quote.amount + quote.fee_reserve
|
||||
_, send_proofs = await wallet.split_to_send(wallet.proofs, total_amount)
|
||||
_, send_proofs = await wallet.swap_to_send(wallet.proofs, total_amount)
|
||||
asyncio.create_task(
|
||||
wallet.melt(
|
||||
proofs=send_proofs,
|
||||
|
||||
@@ -60,7 +60,7 @@ async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
|
||||
assert not melt_quote_pre_payment.paid, "melt quote should not be paid"
|
||||
assert melt_quote_pre_payment.state == MeltQuoteState.unpaid
|
||||
|
||||
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, 64)
|
||||
keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 64)
|
||||
await ledger.melt(proofs=send_proofs, quote=melt_quote.quote)
|
||||
|
||||
melt_quote_post_payment = await ledger.get_melt_quote(melt_quote.quote)
|
||||
@@ -85,7 +85,7 @@ async def test_melt_external(wallet1: Wallet, ledger: Ledger):
|
||||
assert mint_quote.state == MeltQuoteState.unpaid.value
|
||||
|
||||
total_amount = mint_quote.amount + mint_quote.fee_reserve
|
||||
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, total_amount)
|
||||
keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, total_amount)
|
||||
melt_quote = await ledger.melt_quote(
|
||||
PostMeltQuoteRequest(request=invoice_payment_request, unit="sat")
|
||||
)
|
||||
@@ -169,13 +169,13 @@ async def test_split(wallet1: Wallet, ledger: Ledger):
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
|
||||
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, 10)
|
||||
keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10)
|
||||
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(len(send_proofs))
|
||||
outputs, rs = wallet1._construct_outputs(
|
||||
[p.amount for p in send_proofs], secrets, rs
|
||||
)
|
||||
|
||||
promises = await ledger.split(proofs=send_proofs, outputs=outputs)
|
||||
promises = await ledger.swap(proofs=send_proofs, outputs=outputs)
|
||||
assert len(promises) == len(outputs)
|
||||
assert [p.amount for p in promises] == [p.amount for p in outputs]
|
||||
|
||||
@@ -185,9 +185,9 @@ async def test_split_with_no_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 10, set_reserved=False)
|
||||
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10, set_reserved=False)
|
||||
await assert_err(
|
||||
ledger.split(proofs=send_proofs, outputs=[]),
|
||||
ledger.swap(proofs=send_proofs, outputs=[]),
|
||||
"no outputs provided",
|
||||
)
|
||||
|
||||
@@ -198,7 +198,7 @@ async def test_split_with_input_less_than_outputs(wallet1: Wallet, ledger: Ledge
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
|
||||
keep_proofs, send_proofs = await wallet1.split_to_send(
|
||||
keep_proofs, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 10, set_reserved=False
|
||||
)
|
||||
|
||||
@@ -213,7 +213,7 @@ async def test_split_with_input_less_than_outputs(wallet1: Wallet, ledger: Ledge
|
||||
)
|
||||
|
||||
await assert_err(
|
||||
ledger.split(proofs=send_proofs, outputs=outputs),
|
||||
ledger.swap(proofs=send_proofs, outputs=outputs),
|
||||
"are not balanced",
|
||||
)
|
||||
|
||||
@@ -237,7 +237,7 @@ async def test_split_with_input_more_than_outputs(wallet1: Wallet, ledger: Ledge
|
||||
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
|
||||
|
||||
await assert_err(
|
||||
ledger.split(proofs=inputs, outputs=outputs),
|
||||
ledger.swap(proofs=inputs, outputs=outputs),
|
||||
"are not balanced",
|
||||
)
|
||||
|
||||
@@ -262,11 +262,11 @@ async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
)
|
||||
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
|
||||
|
||||
await ledger.split(proofs=inputs1, outputs=outputs)
|
||||
await ledger.swap(proofs=inputs1, outputs=outputs)
|
||||
|
||||
# try to spend other proofs with the same outputs again
|
||||
await assert_err(
|
||||
ledger.split(proofs=inputs2, outputs=outputs),
|
||||
ledger.swap(proofs=inputs2, outputs=outputs),
|
||||
"outputs have already been signed before.",
|
||||
)
|
||||
|
||||
@@ -277,7 +277,7 @@ async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
)
|
||||
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
|
||||
|
||||
await ledger.split(proofs=inputs2, outputs=outputs)
|
||||
await ledger.swap(proofs=inputs2, outputs=outputs)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -396,7 +396,7 @@ async def test_check_proof_state(wallet1: Wallet, ledger: Ledger):
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
|
||||
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, 10)
|
||||
keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10)
|
||||
|
||||
proof_states = await ledger.db_read.get_proofs_states(Ys=[p.Y for p in send_proofs])
|
||||
assert all([p.state.value == "UNSPENT" for p in proof_states])
|
||||
|
||||
@@ -43,7 +43,7 @@ async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
|
||||
# wallet pays the invoice
|
||||
quote = await wallet.melt_quote(invoice_payment_request)
|
||||
total_amount = quote.amount + quote.fee_reserve
|
||||
_, send_proofs = await wallet.split_to_send(wallet.proofs, total_amount)
|
||||
_, send_proofs = await wallet.swap_to_send(wallet.proofs, total_amount)
|
||||
asyncio.create_task(ledger.melt(proofs=send_proofs, quote=quote.quote))
|
||||
# asyncio.create_task(
|
||||
# wallet.melt(
|
||||
|
||||
@@ -241,14 +241,14 @@ async def test_split(wallet1: Wallet):
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_to_send(wallet1: Wallet):
|
||||
async def test_swap_to_send(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
assert wallet1.balance == 64
|
||||
|
||||
# this will select 32 sats and them (nothing to keep)
|
||||
keep_proofs, send_proofs = await wallet1.split_to_send(
|
||||
keep_proofs, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 32, set_reserved=True
|
||||
)
|
||||
assert_amt(send_proofs, 32)
|
||||
@@ -307,7 +307,7 @@ async def test_melt(wallet1: Wallet):
|
||||
assert total_amount == 64
|
||||
assert quote.fee_reserve == 0
|
||||
|
||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, total_amount)
|
||||
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, total_amount)
|
||||
|
||||
melt_response = await wallet1.melt(
|
||||
proofs=send_proofs,
|
||||
@@ -343,12 +343,12 @@ async def test_melt(wallet1: Wallet):
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_to_send_more_than_balance(wallet1: Wallet):
|
||||
async def test_swap_to_send_more_than_balance(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
await assert_err(
|
||||
wallet1.split_to_send(wallet1.proofs, 128, set_reserved=True),
|
||||
wallet1.swap_to_send(wallet1.proofs, 128, set_reserved=True),
|
||||
"balance too low.",
|
||||
)
|
||||
assert wallet1.balance == 64
|
||||
@@ -405,7 +405,7 @@ async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
_, spendable_proofs = await wallet1.split_to_send(
|
||||
_, spendable_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 32, set_reserved=True
|
||||
)
|
||||
await wallet2.redeem(spendable_proofs)
|
||||
|
||||
@@ -74,7 +74,7 @@ async def test_htlc_split(wallet1: Wallet, wallet2: Wallet):
|
||||
preimage = "00000000000000000000000000000000"
|
||||
preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
|
||||
secret = await wallet1.create_htlc_lock(preimage=preimage)
|
||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
for p in send_proofs:
|
||||
assert HTLCSecret.deserialize(p.secret).data == preimage_hash
|
||||
|
||||
@@ -87,7 +87,7 @@ async def test_htlc_redeem_with_preimage(wallet1: Wallet, wallet2: Wallet):
|
||||
preimage = "00000000000000000000000000000000"
|
||||
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
|
||||
secret = await wallet1.create_htlc_lock(preimage=preimage)
|
||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
for p in send_proofs:
|
||||
p.witness = HTLCWitness(preimage=preimage).json()
|
||||
await wallet2.redeem(send_proofs)
|
||||
@@ -103,7 +103,7 @@ async def test_htlc_redeem_with_wrong_preimage(wallet1: Wallet, wallet2: Wallet)
|
||||
secret = await wallet1.create_htlc_lock(
|
||||
preimage=preimage[:-5] + "11111"
|
||||
) # wrong preimage
|
||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
for p in send_proofs:
|
||||
p.witness = HTLCWitness(preimage=preimage).json()
|
||||
await assert_err(
|
||||
@@ -122,7 +122,7 @@ async def test_htlc_redeem_with_no_signature(wallet1: Wallet, wallet2: Wallet):
|
||||
secret = await wallet1.create_htlc_lock(
|
||||
preimage=preimage, hashlock_pubkey=pubkey_wallet1
|
||||
)
|
||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
for p in send_proofs:
|
||||
p.witness = HTLCWitness(preimage=preimage).json()
|
||||
await assert_err(
|
||||
@@ -142,7 +142,7 @@ async def test_htlc_redeem_with_wrong_signature(wallet1: Wallet, wallet2: Wallet
|
||||
secret = await wallet1.create_htlc_lock(
|
||||
preimage=preimage, hashlock_pubkey=pubkey_wallet1
|
||||
)
|
||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
signatures = await wallet1.sign_p2pk_proofs(send_proofs)
|
||||
for p, s in zip(send_proofs, signatures):
|
||||
p.witness = HTLCWitness(
|
||||
@@ -166,7 +166,7 @@ async def test_htlc_redeem_with_correct_signature(wallet1: Wallet, wallet2: Wall
|
||||
secret = await wallet1.create_htlc_lock(
|
||||
preimage=preimage, hashlock_pubkey=pubkey_wallet1
|
||||
)
|
||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
|
||||
signatures = await wallet1.sign_p2pk_proofs(send_proofs)
|
||||
for p, s in zip(send_proofs, signatures):
|
||||
@@ -192,7 +192,7 @@ async def test_htlc_redeem_hashlock_wrong_signature_timelock_correct_signature(
|
||||
locktime_seconds=2,
|
||||
locktime_pubkey=pubkey_wallet1,
|
||||
)
|
||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
|
||||
signatures = await wallet1.sign_p2pk_proofs(send_proofs)
|
||||
for p, s in zip(send_proofs, signatures):
|
||||
@@ -226,7 +226,7 @@ async def test_htlc_redeem_hashlock_wrong_signature_timelock_wrong_signature(
|
||||
locktime_seconds=2,
|
||||
locktime_pubkey=pubkey_wallet1,
|
||||
)
|
||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||
|
||||
signatures = await wallet1.sign_p2pk_proofs(send_proofs)
|
||||
for p, s in zip(send_proofs, signatures):
|
||||
|
||||
@@ -74,7 +74,7 @@ async def test_p2pk(wallet1: Wallet, wallet2: Wallet):
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
# p2pk test
|
||||
secret_lock = await wallet1.create_p2pk_lock(pubkey_wallet2) # sender side
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
await wallet2.redeem(send_proofs)
|
||||
@@ -100,7 +100,7 @@ async def test_p2pk_sig_all(wallet1: Wallet, wallet2: Wallet):
|
||||
secret_lock = await wallet1.create_p2pk_lock(
|
||||
pubkey_wallet2, sig_all=True
|
||||
) # sender side
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
await wallet2.redeem(send_proofs)
|
||||
@@ -114,7 +114,7 @@ async def test_p2pk_receive_with_wrong_private_key(wallet1: Wallet, wallet2: Wal
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
|
||||
# sender side
|
||||
secret_lock = await wallet1.create_p2pk_lock(pubkey_wallet2) # sender side
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
# receiver side: wrong private key
|
||||
@@ -137,7 +137,7 @@ async def test_p2pk_short_locktime_receive_with_wrong_private_key(
|
||||
secret_lock = await wallet1.create_p2pk_lock(
|
||||
pubkey_wallet2, locktime_seconds=2
|
||||
) # sender side
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
# receiver side: wrong private key
|
||||
@@ -167,7 +167,7 @@ async def test_p2pk_locktime_with_refund_pubkey(wallet1: Wallet, wallet2: Wallet
|
||||
locktime_seconds=2, # locktime
|
||||
tags=Tags([["refund", pubkey_wallet2]]), # refund pubkey
|
||||
) # sender side
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
send_proofs_copy = copy.deepcopy(send_proofs)
|
||||
@@ -198,7 +198,7 @@ async def test_p2pk_locktime_with_wrong_refund_pubkey(wallet1: Wallet, wallet2:
|
||||
locktime_seconds=2, # locktime
|
||||
tags=Tags([["refund", garbage_pubkey_2.serialize().hex()]]), # refund pubkey
|
||||
) # sender side
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
send_proofs_copy = copy.deepcopy(send_proofs)
|
||||
@@ -235,7 +235,7 @@ async def test_p2pk_locktime_with_second_refund_pubkey(
|
||||
[["refund", pubkey_wallet2, pubkey_wallet1]]
|
||||
), # multiple refund pubkeys
|
||||
) # sender side
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
send_proofs_copy = copy.deepcopy(send_proofs)
|
||||
@@ -263,7 +263,7 @@ async def test_p2pk_multisig_2_of_2(wallet1: Wallet, wallet2: Wallet):
|
||||
pubkey_wallet2, tags=Tags([["pubkeys", pubkey_wallet1]]), n_sigs=2
|
||||
)
|
||||
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
# add signatures of wallet1
|
||||
@@ -285,7 +285,7 @@ async def test_p2pk_multisig_duplicate_signature(wallet1: Wallet, wallet2: Walle
|
||||
pubkey_wallet2, tags=Tags([["pubkeys", pubkey_wallet1]]), n_sigs=2
|
||||
)
|
||||
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
# add signatures of wallet2 – this is a duplicate signature
|
||||
@@ -308,7 +308,7 @@ async def test_p2pk_multisig_quorum_not_met_1_of_2(wallet1: Wallet, wallet2: Wal
|
||||
secret_lock = await wallet1.create_p2pk_lock(
|
||||
pubkey_wallet2, tags=Tags([["pubkeys", pubkey_wallet1]]), n_sigs=2
|
||||
)
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
await assert_err(
|
||||
@@ -330,7 +330,7 @@ async def test_p2pk_multisig_quorum_not_met_2_of_3(wallet1: Wallet, wallet2: Wal
|
||||
pubkey_wallet2, tags=Tags([["pubkeys", pubkey_wallet1]]), n_sigs=3
|
||||
)
|
||||
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
# add signatures of wallet1
|
||||
@@ -352,7 +352,7 @@ async def test_p2pk_multisig_with_duplicate_publickey(wallet1: Wallet, wallet2:
|
||||
secret_lock = await wallet1.create_p2pk_lock(
|
||||
pubkey_wallet2, tags=Tags([["pubkeys", pubkey_wallet2]]), n_sigs=2
|
||||
)
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
await assert_err(wallet2.redeem(send_proofs), "Mint Error: pubkeys must be unique.")
|
||||
@@ -377,7 +377,7 @@ async def test_p2pk_multisig_with_wrong_first_private_key(
|
||||
secret_lock = await wallet1.create_p2pk_lock(
|
||||
pubkey_wallet2, tags=Tags([["pubkeys", wrong_public_key_hex]]), n_sigs=2
|
||||
)
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
_, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
)
|
||||
# add signatures of wallet1
|
||||
|
||||
@@ -45,7 +45,7 @@ async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
|
||||
# wallet pays the invoice
|
||||
quote = await wallet.melt_quote(invoice_payment_request)
|
||||
total_amount = quote.amount + quote.fee_reserve
|
||||
_, send_proofs = await wallet.split_to_send(wallet.proofs, total_amount)
|
||||
_, send_proofs = await wallet.swap_to_send(wallet.proofs, total_amount)
|
||||
asyncio.create_task(
|
||||
wallet.melt(
|
||||
proofs=send_proofs,
|
||||
@@ -85,7 +85,7 @@ async def test_regtest_failed_quote(wallet: Wallet, ledger: Ledger):
|
||||
# wallet pays the invoice
|
||||
quote = await wallet.melt_quote(invoice_payment_request)
|
||||
total_amount = quote.amount + quote.fee_reserve
|
||||
_, send_proofs = await wallet.split_to_send(wallet.proofs, total_amount)
|
||||
_, send_proofs = await wallet.swap_to_send(wallet.proofs, total_amount)
|
||||
asyncio.create_task(
|
||||
wallet.melt(
|
||||
proofs=send_proofs,
|
||||
|
||||
@@ -164,7 +164,7 @@ async def test_restore_wallet_after_mint(wallet3: Wallet):
|
||||
await wallet3.load_proofs()
|
||||
wallet3.proofs = []
|
||||
assert wallet3.balance == 0
|
||||
await wallet3.restore_promises_from_to(0, 20)
|
||||
await wallet3.restore_promises_from_to(wallet3.keyset_id, 0, 20)
|
||||
assert wallet3.balance == 64
|
||||
|
||||
# expect that DLEQ proofs are restored
|
||||
@@ -185,7 +185,7 @@ async def test_restore_wallet_with_invalid_mnemonic(wallet3: Wallet):
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_restore_wallet_after_split_to_send(wallet3: Wallet):
|
||||
async def test_restore_wallet_after_swap_to_send(wallet3: Wallet):
|
||||
await wallet3._init_private_key(
|
||||
"half depart obvious quality work element tank gorilla view sugar picture"
|
||||
" humble"
|
||||
@@ -197,7 +197,7 @@ async def test_restore_wallet_after_split_to_send(wallet3: Wallet):
|
||||
await wallet3.mint(64, id=invoice.id)
|
||||
assert wallet3.balance == 64
|
||||
|
||||
_, spendable_proofs = await wallet3.split_to_send(
|
||||
_, spendable_proofs = await wallet3.swap_to_send(
|
||||
wallet3.proofs, 32, set_reserved=True
|
||||
) # type: ignore
|
||||
|
||||
@@ -205,7 +205,7 @@ async def test_restore_wallet_after_split_to_send(wallet3: Wallet):
|
||||
await wallet3.load_proofs()
|
||||
wallet3.proofs = []
|
||||
assert wallet3.balance == 0
|
||||
await wallet3.restore_promises_from_to(0, 100)
|
||||
await wallet3.restore_promises_from_to(wallet3.keyset_id, 0, 100)
|
||||
assert wallet3.balance == 96
|
||||
await wallet3.invalidate(wallet3.proofs, check_spendable=True)
|
||||
assert wallet3.balance == 64
|
||||
@@ -222,7 +222,7 @@ async def test_restore_wallet_after_send_and_receive(wallet3: Wallet, wallet2: W
|
||||
await wallet3.mint(64, id=invoice.id)
|
||||
assert wallet3.balance == 64
|
||||
|
||||
_, spendable_proofs = await wallet3.split_to_send(
|
||||
_, spendable_proofs = await wallet3.swap_to_send(
|
||||
wallet3.proofs, 32, set_reserved=True
|
||||
) # type: ignore
|
||||
|
||||
@@ -232,7 +232,7 @@ async def test_restore_wallet_after_send_and_receive(wallet3: Wallet, wallet2: W
|
||||
await wallet3.load_proofs(reload=True)
|
||||
assert wallet3.proofs == []
|
||||
assert wallet3.balance == 0
|
||||
await wallet3.restore_promises_from_to(0, 100)
|
||||
await wallet3.restore_promises_from_to(wallet3.keyset_id, 0, 100)
|
||||
assert wallet3.balance == 96
|
||||
await wallet3.invalidate(wallet3.proofs, check_spendable=True)
|
||||
assert wallet3.balance == 32
|
||||
@@ -265,7 +265,7 @@ async def test_restore_wallet_after_send_and_self_receive(wallet3: Wallet):
|
||||
await wallet3.mint(64, id=invoice.id)
|
||||
assert wallet3.balance == 64
|
||||
|
||||
_, spendable_proofs = await wallet3.split_to_send(
|
||||
_, spendable_proofs = await wallet3.swap_to_send(
|
||||
wallet3.proofs, 32, set_reserved=True
|
||||
) # type: ignore
|
||||
|
||||
@@ -275,7 +275,7 @@ async def test_restore_wallet_after_send_and_self_receive(wallet3: Wallet):
|
||||
await wallet3.load_proofs(reload=True)
|
||||
assert wallet3.proofs == []
|
||||
assert wallet3.balance == 0
|
||||
await wallet3.restore_promises_from_to(0, 100)
|
||||
await wallet3.restore_promises_from_to(wallet3.keyset_id, 0, 100)
|
||||
assert wallet3.balance == 128
|
||||
await wallet3.invalidate(wallet3.proofs, check_spendable=True)
|
||||
assert wallet3.balance == 64
|
||||
@@ -295,7 +295,7 @@ async def test_restore_wallet_after_send_twice(
|
||||
box.add(wallet3.proofs)
|
||||
assert wallet3.balance == 2
|
||||
|
||||
keep_proofs, spendable_proofs = await wallet3.split_to_send(
|
||||
keep_proofs, spendable_proofs = await wallet3.swap_to_send(
|
||||
wallet3.proofs, 1, set_reserved=True
|
||||
) # type: ignore
|
||||
box.add(wallet3.proofs)
|
||||
@@ -309,7 +309,7 @@ async def test_restore_wallet_after_send_twice(
|
||||
await wallet3.load_proofs(reload=True)
|
||||
assert wallet3.proofs == []
|
||||
assert wallet3.balance == 0
|
||||
await wallet3.restore_promises_from_to(0, 10)
|
||||
await wallet3.restore_promises_from_to(wallet3.keyset_id, 0, 10)
|
||||
box.add(wallet3.proofs)
|
||||
assert wallet3.balance == 4
|
||||
await wallet3.invalidate(wallet3.proofs, check_spendable=True)
|
||||
@@ -317,7 +317,7 @@ async def test_restore_wallet_after_send_twice(
|
||||
|
||||
# again
|
||||
|
||||
_, spendable_proofs = await wallet3.split_to_send(
|
||||
_, spendable_proofs = await wallet3.swap_to_send(
|
||||
wallet3.proofs, 1, set_reserved=True
|
||||
) # type: ignore
|
||||
box.add(wallet3.proofs)
|
||||
@@ -331,7 +331,7 @@ async def test_restore_wallet_after_send_twice(
|
||||
await wallet3.load_proofs(reload=True)
|
||||
assert wallet3.proofs == []
|
||||
assert wallet3.balance == 0
|
||||
await wallet3.restore_promises_from_to(0, 15)
|
||||
await wallet3.restore_promises_from_to(wallet3.keyset_id, 0, 15)
|
||||
box.add(wallet3.proofs)
|
||||
assert wallet3.balance == 6
|
||||
await wallet3.invalidate(wallet3.proofs, check_spendable=True)
|
||||
@@ -354,7 +354,7 @@ async def test_restore_wallet_after_send_and_self_receive_nonquadratic_value(
|
||||
box.add(wallet3.proofs)
|
||||
assert wallet3.balance == 64
|
||||
|
||||
keep_proofs, spendable_proofs = await wallet3.split_to_send(
|
||||
keep_proofs, spendable_proofs = await wallet3.swap_to_send(
|
||||
wallet3.proofs, 10, set_reserved=True
|
||||
) # type: ignore
|
||||
box.add(wallet3.proofs)
|
||||
@@ -368,7 +368,7 @@ async def test_restore_wallet_after_send_and_self_receive_nonquadratic_value(
|
||||
await wallet3.load_proofs(reload=True)
|
||||
assert wallet3.proofs == []
|
||||
assert wallet3.balance == 0
|
||||
await wallet3.restore_promises_from_to(0, 20)
|
||||
await wallet3.restore_promises_from_to(wallet3.keyset_id, 0, 20)
|
||||
box.add(wallet3.proofs)
|
||||
assert wallet3.balance == 84
|
||||
await wallet3.invalidate(wallet3.proofs, check_spendable=True)
|
||||
@@ -376,7 +376,7 @@ async def test_restore_wallet_after_send_and_self_receive_nonquadratic_value(
|
||||
|
||||
# again
|
||||
|
||||
_, spendable_proofs = await wallet3.split_to_send(
|
||||
_, spendable_proofs = await wallet3.swap_to_send(
|
||||
wallet3.proofs, 12, set_reserved=True
|
||||
) # type: ignore
|
||||
|
||||
@@ -388,7 +388,7 @@ async def test_restore_wallet_after_send_and_self_receive_nonquadratic_value(
|
||||
await wallet3.load_proofs(reload=True)
|
||||
assert wallet3.proofs == []
|
||||
assert wallet3.balance == 0
|
||||
await wallet3.restore_promises_from_to(0, 50)
|
||||
await wallet3.restore_promises_from_to(wallet3.keyset_id, 0, 50)
|
||||
assert wallet3.balance == 108
|
||||
await wallet3.invalidate(wallet3.proofs, check_spendable=True)
|
||||
assert wallet3.balance == 64
|
||||
|
||||
@@ -86,7 +86,7 @@ async def test_wallet_subscription_swap(wallet: Wallet):
|
||||
wallet.proofs, callback=callback
|
||||
)
|
||||
|
||||
_ = await wallet.split_to_send(wallet.proofs, 64)
|
||||
_ = await wallet.swap_to_send(wallet.proofs, 64)
|
||||
|
||||
wait = 1
|
||||
await asyncio.sleep(wait)
|
||||
|
||||
Reference in New Issue
Block a user