FEAT: Add flake8 (#267)

* init flake8

* exclude nostr client, and add ds_store to gitignore

* fix flake8 F811 issue, redefinition of unused variables

* add flake8 to workflow

* F401 unused imports

* F541 f-string is missing placeholders

* E501 line too long > 150 characters

* E722 no bare except

* E402 module level import not at top of file

* F405 no star imports

* E712 comparison to False should be 'if cond is False:'

* F841 local variable is assigned to but never used

* E266 too many leading '#' for block comment

* E265, E261

* E713 test for membership should be 'not in'

* E711, E741

E741 ambiguous variable name 'l'
E711 comparison to None should be 'if cond is None:'

* flake config

* isort

* refactor makefile flake8 usage

* reflaking the rebase

* black

* fix tests?

* black

* fix line lenght it test_cli

* sort out makefile

* fix strings

* reintroduce black-check

* reflake and mypy

* isort

* Update cashu/wallet/wallet.py

Co-authored-by: Angus Pearson <angus@toaster.cc>

* Update cashu/mint/ledger.py

Co-authored-by: Angus Pearson <angus@toaster.cc>

---------

Co-authored-by: Angus Pearson <angus@toaster.cc>
This commit is contained in:
dni ⚡
2023-07-28 18:42:16 +02:00
committed by GitHub
parent 4c1ff8b353
commit e3ed00640f
41 changed files with 338 additions and 425 deletions

8
.flake8 Normal file
View File

@@ -0,0 +1,8 @@
[flake8]
max-line-length = 150
exclude = cashu/nostr, cashu/core/bolt11.py
ignore =
# E203 whitespace before ':' black does not like it
E203,
# W503: line break before binary operator
W503,

View File

@@ -49,3 +49,5 @@ jobs:
run: yes | poetry run mypy cashu --install-types || true
- name: Run mypy
run: poetry run mypy cashu --ignore-missing
- name: Run flake8
run: poetry run flake8

3
.gitignore vendored
View File

@@ -133,3 +133,6 @@ tor.pid
# Default data directory
/data
# MacOS
.DS_Store

View File

@@ -8,16 +8,18 @@ black:
poetry run black . --exclude cashu/nostr
black-check:
poetry run black --check . --exclude cashu/nostr
format:
make isort
make black
make mypy
poetry run black . --exclude cashu/nostr --check
mypy:
poetry run mypy cashu --ignore-missing
flake8:
poetry run flake8
format: isort black
check: mypy flake8 isort-check black-check
clean:
rm -r cashu.egg-info/ || true
find . -name ".DS_Store" -exec rm -f {} \; || true

View File

@@ -10,7 +10,8 @@ from pydantic import BaseModel
from .crypto.keys import derive_keys, derive_keyset_id, derive_pubkeys
from .crypto.secp import PrivateKey, PublicKey
from .legacy import derive_keys_backwards_compatible_insecure_pre_0_12
from .p2pk import sign_p2pk_sign
# from .p2pk import sign_p2pk_sign
# ------- PROOFS -------

View File

@@ -45,7 +45,7 @@ def hash_to_curve(message: bytes) -> PublicKey:
_hash = hashlib.sha256(msg_to_hash).digest()
try:
point = PublicKey(b"\x02" + _hash, raw=True)
except:
except Exception:
msg_to_hash = _hash
return point
@@ -74,7 +74,7 @@ def verify(a: PrivateKey, C: PublicKey, secret_msg: str) -> bool:
return C == Y.mult(a) # type: ignore
### Below is a test of a simple positive and negative case
# Below is a test of a simple positive and negative case
# # Alice's keys
# a = PrivateKey()

View File

@@ -1,7 +1,7 @@
import base64
import hashlib
import random
from typing import Dict, List
from typing import Dict
from ..settings import settings
from .secp import PrivateKey, PublicKey

View File

@@ -102,7 +102,7 @@ class Database(Compat):
def _parse_timestamp(value, _):
f = "%Y-%m-%d %H:%M:%S.%f"
if not "." in value:
if "." not in value:
f = "%Y-%m-%d %H:%M:%S"
return time.mktime(datetime.datetime.strptime(value, f).timetuple())

View File

@@ -22,7 +22,7 @@ def hash_to_point_pre_0_3_3(secret_msg):
_hash[0] = 0x02 # set first byte to represent even y coord
_hash = bytes(_hash)
point = PublicKey(_hash, raw=True)
except:
except Exception:
msg = _hash
return point

View File

@@ -27,7 +27,7 @@ async def migrate_databases(db: Database, migrations_module):
logger.debug(f"Migrating {db_name} db: {key}")
await migrate(db)
if db.schema == None:
if db.schema is None:
await set_migration_version(db, db_name, version)
else:
async with db.connect() as conn:

View File

@@ -2,13 +2,8 @@ import base64
import hashlib
import random
COIN = 100_000_000
TXID = "bff785da9f8169f49be92fa95e31f0890c385bfb1bd24d6b94d7900057c617ae"
SEED = b"__not__used"
from bitcoin.core import CMutableTxIn, CMutableTxOut, COutPoint, CTransaction, lx
from bitcoin.core.script import *
from bitcoin.core.script import CScript
from bitcoin.core.script import OP_CHECKSIG, SIGHASH_ALL, CScript, SignatureHash
from bitcoin.core.scripteval import (
SCRIPT_VERIFY_P2SH,
EvalScriptError,
@@ -17,6 +12,10 @@ from bitcoin.core.scripteval import (
)
from bitcoin.wallet import CBitcoinSecret, P2SHBitcoinAddress
COIN = 100_000_000
TXID = "bff785da9f8169f49be92fa95e31f0890c385bfb1bd24d6b94d7900057c617ae"
SEED = b"__not__used"
def step0_carol_privkey():
"""Private key"""

View File

@@ -1,3 +1,3 @@
# type: ignore
from .fake import FakeWallet
from .lnbits import LNbitsWallet
from .fake import FakeWallet # noqa: F401
from .lnbits import LNbitsWallet # noqa: F401

View File

@@ -1,5 +1,5 @@
from abc import ABC, abstractmethod
from typing import AsyncGenerator, Coroutine, NamedTuple, Optional
from typing import Coroutine, NamedTuple, Optional
class StatusResponse(NamedTuple):
@@ -34,14 +34,14 @@ class PaymentStatus(NamedTuple):
@property
def failed(self) -> bool:
return self.paid == False
return self.paid is False
def __str__(self) -> str:
if self.paid == True:
if self.paid is True:
return "settled"
elif self.paid == False:
elif self.paid is False:
return "failed"
elif self.paid == None:
elif self.paid is None:
return "still pending"
else:
return "unknown (should never happen)"

View File

@@ -34,7 +34,7 @@ class LNbitsWallet(Wallet):
try:
data = r.json()
except:
except Exception:
return StatusResponse(
f"Failed to connect to {self.endpoint}, got: '{r.text[:200]}...'", 0
)
@@ -61,7 +61,7 @@ class LNbitsWallet(Wallet):
url=f"{self.endpoint}/api/v1/payments", json=data
)
r.raise_for_status()
except:
except Exception:
return InvoiceResponse(False, None, None, r.json()["detail"])
ok, checking_id, payment_request, error_message = (
True,
@@ -83,20 +83,13 @@ class LNbitsWallet(Wallet):
timeout=None,
)
r.raise_for_status()
except:
except Exception:
error_message = r.json()["detail"]
return PaymentResponse(None, None, None, None, error_message)
if r.status_code > 299:
return PaymentResponse(None, None, None, None, f"HTTP status: {r.reason}")
if "detail" in r.json():
return PaymentResponse(None, None, None, None, r.json()["detail"])
ok, checking_id, fee_msat, preimage, error_message = (
True,
None,
None,
None,
None,
)
data = r.json()
checking_id = data["payment_hash"]
@@ -104,7 +97,7 @@ class LNbitsWallet(Wallet):
# we do this to get the fee and preimage
payment: PaymentStatus = await self.get_payment_status(checking_id)
return PaymentResponse(ok, checking_id, payment.fee_msat, payment.preimage)
return PaymentResponse(True, checking_id, payment.fee_msat, payment.preimage)
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
try:
@@ -112,7 +105,7 @@ class LNbitsWallet(Wallet):
url=f"{self.endpoint}/api/v1/payments/{checking_id}"
)
r.raise_for_status()
except:
except Exception:
return PaymentStatus(None)
if r.json().get("detail"):
return PaymentStatus(None)
@@ -124,7 +117,7 @@ class LNbitsWallet(Wallet):
url=f"{self.endpoint}/api/v1/payments/{checking_id}"
)
r.raise_for_status()
except:
except Exception:
return PaymentStatus(None)
data = r.json()
if "paid" not in data and "details" not in data:

View File

@@ -1 +0,0 @@

View File

@@ -8,10 +8,8 @@ from fastapi.responses import JSONResponse
# from fastapi_profiler import PyInstrumentProfilerMiddleware
from loguru import logger
from starlette.middleware import Middleware
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.middleware.cors import CORSMiddleware
from starlette.requests import Request
from starlette.responses import Response
from ..core.errors import CashuError
from ..core.settings import settings
@@ -40,7 +38,10 @@ def create_app(config_object="core.settings") -> FastAPI:
self.padding = 0
self.minimal_fmt: str = "<green>{time:YYYY-MM-DD HH:mm:ss.SS}</green> | <level>{level}</level> | <level>{message}</level>\n"
if settings.debug:
self.fmt: str = "<green>{time:YYYY-MM-DD HH:mm:ss.SS}</green> | <level>{level: <4}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> | <level>{message}</level>\n"
self.fmt: str = (
"<green>{time:YYYY-MM-DD HH:mm:ss.SS}</green> | <level>{level: <4}</level> | <cyan>{name}</cyan>:<cyan>"
"{function}</cyan>:<cyan>{line}</cyan> | <level>{message}</level>\n"
)
else:
self.fmt: str = self.minimal_fmt
@@ -113,7 +114,7 @@ async def catch_exceptions(request: Request, call_next):
except Exception as e:
try:
err_message = str(e)
except:
except Exception:
err_message = e.args[0] if e.args else "Unknown error"
if isinstance(e, CashuError):

View File

@@ -1,4 +1,3 @@
import time
from typing import Any, List, Optional
from ..core.base import BlindedSignature, Invoice, MintKeyset, Proof

View File

@@ -5,7 +5,7 @@ from typing import Dict, List, Literal, Optional, Set, Tuple, Union
from loguru import logger
from ..core import bolt11, legacy
from ..core import bolt11
from ..core.base import (
BlindedMessage,
BlindedSignature,
@@ -67,7 +67,7 @@ class Ledger:
async def load_used_proofs(self):
"""Load all used proofs from database."""
logger.trace(f"crud: loading used proofs")
logger.trace("crud: loading used proofs")
proofs_used = await self.crud.get_proofs_used(db=self.db)
logger.trace(f"crud: loaded {len(proofs_used)} used proofs")
self.proofs_used = set(proofs_used)
@@ -128,7 +128,7 @@ class Ledger:
generated from `self.derivation_path`. Defaults to True.
"""
# load all past keysets from db
logger.trace(f"crud: loading keysets")
logger.trace("crud: loading keysets")
tmp_keysets: List[MintKeyset] = await self.crud.get_keyset(db=self.db)
logger.trace(f"crud: loaded {len(tmp_keysets)} keysets")
# add keysets from db to current keysets
@@ -199,7 +199,7 @@ class Ledger:
def _check_spendable(self, proof: Proof):
"""Checks whether the proof was already spent."""
return not proof.secret in self.proofs_used
return proof.secret not in self.proofs_used
async def _check_pending(self, proofs: List[Proof]):
"""Checks whether the proof is still pending."""
@@ -250,7 +250,7 @@ class Ledger:
secret = Secret.deserialize(proof.secret)
logger.trace(f"proof.secret: {proof.secret}")
logger.trace(f"secret: {secret}")
except Exception as e:
except Exception:
# secret is not a spending condition so we treat is a normal secret
return True
if secret.kind == SecretKind.P2SH:
@@ -285,7 +285,7 @@ class Ledger:
if secret.kind == SecretKind.P2PK:
# check if locktime is in the past
pubkeys = secret.get_p2pk_pubkey_from_secret()
assert len(set(pubkeys)) == len(pubkeys), f"pubkeys must be unique."
assert len(set(pubkeys)) == len(pubkeys), "pubkeys must be unique."
logger.trace(f"pubkeys: {pubkeys}")
# we will get an empty list if the locktime has passed and no refund pubkey is present
if not pubkeys:
@@ -369,7 +369,7 @@ class Ledger:
pubkeys_per_proof.append(secret.get_p2pk_pubkey_from_secret())
# get signature threshold from secrets
n_sigs.append(secret.n_sigs)
except Exception as e:
except Exception:
# secret is not a spending condition so we treat is a normal secret
return True
# for all proofs all pubkeys must be the same
@@ -612,10 +612,10 @@ class Ledger:
proof_msgs = set([p.secret for p in proofs])
self.proofs_used |= proof_msgs
# store in db
logger.trace(f"crud: storing proofs")
logger.trace("crud: storing proofs")
for p in proofs:
await self.crud.invalidate_proof(proof=p, db=self.db)
logger.trace(f"crud: stored proofs")
logger.trace("crud: stored proofs")
async def _set_proofs_pending(
self, proofs: List[Proof], conn: Optional[Connection] = None
@@ -641,7 +641,7 @@ class Ledger:
logger.trace(
f"crud: _set_proofs_pending proof {p.secret} set as pending"
)
except:
except Exception:
raise TransactionError("proofs already pending.")
async def _unset_proofs_pending(
@@ -679,9 +679,9 @@ class Ledger:
Raises:
Exception: At least one of the proofs is in the pending table.
"""
logger.trace(f"crud: _validate_proofs_pending validating proofs")
logger.trace("crud: _validate_proofs_pending validating proofs")
proofs_pending = await self.crud.get_proofs_pending(db=self.db, conn=conn)
logger.trace(f"crud: _validate_proofs_pending got proofs pending")
logger.trace("crud: _validate_proofs_pending got proofs pending")
for p in proofs:
for pp in proofs_pending:
if p.secret == pp.secret:
@@ -694,7 +694,8 @@ class Ledger:
Args:
proofs (List[Proof]): List of proofs to check.
outputs (Optional[List[BlindedMessage]], optional): List of outputs to check. Must be provided for /split but not for /melt. Defaults to None.
outputs (Optional[List[BlindedMessage]], optional): List of outputs to check.
Must be provided for /split but not for /melt. Defaults to None.
Raises:
Exception: Scripts did not validate.
@@ -814,7 +815,7 @@ class Ledger:
Returns:
Tuple[str, str]: Bolt11 invoice and a hash (for looking it up later)
"""
logger.trace(f"called request_mint")
logger.trace("called request_mint")
if settings.mint_max_peg_in and amount > settings.mint_max_peg_in:
raise NotAllowedError(
f"Maximum mint amount is {settings.mint_max_peg_in} sat."
@@ -941,8 +942,8 @@ class Ledger:
f"status: {status}, preimage: {preimage}, fee_msat: {fee_msat}"
)
if status == True:
logger.trace(f"invalidating proofs")
if status:
logger.trace("invalidating proofs")
await self._invalidate_proofs(proofs)
logger.trace("invalidated proofs")
# prepare change to compensate wallet for overpaid fees
@@ -1008,7 +1009,7 @@ class Ledger:
)
paid = await self.lightning.get_invoice_status(decoded_invoice.payment_hash)
logger.trace(f"check_fees: paid: {paid}")
internal = paid.paid == False
internal = paid.paid is False
else:
amount = 0
internal = True
@@ -1039,14 +1040,14 @@ class Ledger:
Returns:
Tuple[List[BlindSignature],List[BlindSignature]]: Promises on both sides of the split.
"""
logger.trace(f"split called")
logger.trace("split called")
await self._set_proofs_pending(proofs)
total_amount = sum_proofs(proofs)
try:
logger.trace(f"verifying _verify_split_amount")
logger.trace("verifying _verify_split_amount")
# verify that amount is kosher
self._verify_amount(total_amount)
@@ -1055,11 +1056,11 @@ class Ledger:
logger.trace("verifying proofs: _verify_proofs_and_outputs")
await self._verify_proofs_and_outputs(proofs, outputs)
logger.trace(f"verified proofs and outputs")
logger.trace("verified proofs and outputs")
# Mark proofs as used and prepare new promises
logger.trace(f"invalidating proofs")
logger.trace("invalidating proofs")
await self._invalidate_proofs(proofs)
logger.trace(f"invalidated proofs")
logger.trace("invalidated proofs")
except Exception as e:
logger.trace(f"split failed: {e}")
raise e
@@ -1091,7 +1092,7 @@ class Ledger:
# verify amounts in produced promises
self._verify_equation_balanced(proofs, promises)
logger.trace(f"split successful")
logger.trace("split successful")
return promises
return prom_fst, prom_snd

View File

@@ -1,11 +1,9 @@
from typing import Dict, List, Optional, Union
from typing import List, Optional, Union
from fastapi import APIRouter
from loguru import logger
from secp256k1 import PublicKey
from ..core.base import (
BlindedMessage,
BlindedSignature,
CheckFeesRequest,
CheckFeesResponse,
@@ -39,7 +37,7 @@ router: APIRouter = APIRouter()
response_model_exclude_none=True,
)
async def info() -> GetInfoResponse:
logger.trace(f"> GET /info")
logger.trace("> GET /info")
return GetInfoResponse(
name=settings.mint_info_name,
pubkey=ledger.pubkey.serialize().hex() if ledger.pubkey else None,
@@ -66,7 +64,7 @@ async def info() -> GetInfoResponse:
)
async def keys():
"""This endpoint returns a dictionary of all supported token values of the mint and their associated public key."""
logger.trace(f"> GET /keys")
logger.trace("> GET /keys")
keyset = ledger.get_keyset()
keys = KeysResponse.parse_obj(keyset)
return keys.__root__
@@ -101,7 +99,7 @@ async def keyset_keys(idBase64Urlsafe: str):
)
async def keysets() -> KeysetsResponse:
"""This endpoint returns a list of keysets that the mint currently supports and will accept tokens from."""
logger.trace(f"> GET /keysets")
logger.trace("> GET /keysets")
keysets = KeysetsResponse(keysets=ledger.keysets.get_ids())
return keysets
@@ -187,7 +185,10 @@ async def melt(payload: PostMeltRequest) -> GetMeltResponse:
name="Check proof state",
summary="Check whether a proof is spent already or is pending in a transaction",
response_model=CheckSpendableResponse,
response_description="Two lists of booleans indicating whether the provided proofs are spendable or pending in a transaction respectively.",
response_description=(
"Two lists of booleans indicating whether the provided proofs "
"are spendable or pending in a transaction respectively."
),
)
async def check_spendable(
payload: CheckSpendableRequest,
@@ -258,7 +259,8 @@ async def split(
else:
frst_promises.insert(0, promise) # and insert at the beginning
logger.trace(
f"Split into keep: {len(frst_promises)}: {sum([p.amount for p in frst_promises])} sat and send: {len(scnd_promises)}: {sum([p.amount for p in scnd_promises])} sat"
f"Split into keep: {len(frst_promises)}: {sum([p.amount for p in frst_promises])} "
f"sat and send: {len(scnd_promises)}: {sum([p.amount for p in scnd_promises])} sat"
)
return PostSplitResponse_Deprecated(fst=frst_promises, snd=scnd_promises)
# END backwards compatibility < 0.13
@@ -271,7 +273,10 @@ async def split(
name="Restore",
summary="Restores a blinded signature from a secret",
response_model=PostRestoreResponse,
response_description="Two lists with the first being the list of the provided outputs that have an associated blinded signature which is given in the second list.",
response_description=(
"Two lists with the first being the list of the provided outputs that "
"have an associated blinded signature which is given in the second list."
),
)
async def restore(payload: PostMintRequest) -> PostRestoreResponse:
assert payload.outputs, Exception("no outputs provided.")

View File

@@ -9,8 +9,6 @@ from loguru import logger
from ..core.db import Database
from ..core.migrations import migrate_databases
from ..core.settings import settings
from ..lightning.fake import FakeWallet # type: ignore
from ..lightning.lnbits import LNbitsWallet # type: ignore
from ..mint import migrations
from ..mint.ledger import Ledger

View File

@@ -91,7 +91,7 @@ class TorProxy:
try:
logger.debug(f"Setting permissions of {PATHS[platform.system()]} to 755")
os.chmod(PATHS[platform.system()], 0o755)
except:
except Exception:
logger.debug("Exception: could not set permissions of Tor binary")
return PATHS[platform.system()]
@@ -138,7 +138,7 @@ class TorProxy:
s.connect(location)
s.close()
return True
except Exception as e:
except Exception:
return False
def read_pid(self):
@@ -163,7 +163,7 @@ class TorProxy:
pid = int(pid)
try:
os.kill(pid, signal)
except:
except Exception:
return False
else:
return True

View File

@@ -1,11 +1,11 @@
import sys
sys.tracebacklimit = None # type: ignore
from loguru import logger
from ..core.settings import settings
sys.tracebacklimit = None # type: ignore
# configure logger
logger.remove()
logger.add(sys.stderr, level="DEBUG" if settings.debug else "INFO")

View File

@@ -1,4 +1,3 @@
import asyncio
import os
from datetime import datetime
from itertools import groupby, islice
@@ -119,7 +118,7 @@ async def invoice(
global wallet
wallet = await load_mint(wallet, mint)
if not settings.lightning:
r = await wallet.mint(amount, split=optional_split)
await wallet.mint(amount, split=optional_split)
return InvoiceResponse(
amount=amount,
)
@@ -392,7 +391,7 @@ async def wallets():
}
}
)
except:
except Exception:
pass
return WalletsResponse(wallets=result)
@@ -417,7 +416,7 @@ async def info():
client = NostrClient(private_key=settings.nostr_private_key, connect=False)
nostr_public_key = client.private_key.bech32()
nostr_relays = settings.nostr_relays
except:
except Exception:
nostr_public_key = "Invalid key"
nostr_relays = []
else:

View File

@@ -89,7 +89,11 @@ def coro(f):
@coro
async def cli(ctx: Context, host: str, walletname: str, tests: bool):
if settings.tor and not TorProxy().check_platform():
error_str = "Your settings say TOR=true but the built-in Tor bundle is not supported on your system. You have two options: Either install Tor manually and set TOR=FALSE and SOCKS_HOST=localhost and SOCKS_PORT=9050 in your Cashu config (recommended). Or turn off Tor by setting TOR=false (not recommended). Cashu will not work until you edit your config file accordingly."
error_str = (
"Your settings say TOR=true but the built-in Tor bundle is not supported on your system. You have two options: Either install"
" Tor manually and set TOR=FALSE and SOCKS_HOST=localhost and SOCKS_PORT=9050 in your Cashu config (recommended). Or turn off Tor by "
"setting TOR=false (not recommended). Cashu will not work until you edit your config file accordingly."
)
error_str += "\n\n"
if settings.env_file:
error_str += f"Edit your Cashu config file here: {settings.env_file}"
@@ -156,7 +160,7 @@ async def pay(ctx: Context, invoice: str, yes: bool):
default=True,
)
print(f"Paying Lightning invoice ...")
print("Paying Lightning invoice ...")
assert total_amount > 0, "amount is not positive"
if wallet.available_balance < total_amount:
print("Error: Balance too low.")
@@ -192,7 +196,7 @@ async def invoice(ctx: Context, amount: int, hash: str, split: int):
logger.debug(f"Requesting split with {n_splits} * {split} sat tokens.")
if not settings.lightning:
r = await wallet.mint(amount, split=optional_split)
await wallet.mint(amount, split=optional_split)
# user requests an invoice
elif amount and not hash:
invoice = await wallet.request_mint(amount)
@@ -207,7 +211,7 @@ async def invoice(ctx: Context, amount: int, hash: str, split: int):
check_until = time.time() + 5 * 60 # check for five minutes
print("")
print(
f"Checking invoice ...",
"Checking invoice ...",
end="",
flush=True,
)
@@ -310,7 +314,8 @@ async def balance(ctx: Context, verbose):
if verbose:
print(
f"Balance: {wallet.available_balance} sat (pending: {wallet.balance-wallet.available_balance} sat) in {len([p for p in wallet.proofs if not p.reserved])} tokens"
f"Balance: {wallet.available_balance} sat (pending: {wallet.balance-wallet.available_balance} sat) "
f"in {len([p for p in wallet.proofs if not p.reserved])} tokens"
)
else:
print(f"Balance: {wallet.available_balance} sat")
@@ -498,7 +503,7 @@ async def pending(ctx: Context, legacy, number: int, offset: int):
wallet: Wallet = ctx.obj["WALLET"]
reserved_proofs = await get_reserved_proofs(wallet.db)
if len(reserved_proofs):
print(f"--------------------------\n")
print("--------------------------\n")
sorted_proofs = sorted(reserved_proofs, key=itemgetter("send_id")) # type: ignore
if number:
number += offset
@@ -532,7 +537,7 @@ async def pending(ctx: Context, legacy, number: int, offset: int):
legacy=True,
)
print(f"{token_legacy}\n")
print(f"--------------------------\n")
print("--------------------------\n")
print("To remove all spent tokens use: cashu burn -a")
@@ -566,7 +571,7 @@ async def lock(ctx, p2sh):
f"Anyone can send tokens to this lock:\n\ncashu send <amount> --lock {lock_str}"
)
print("")
print(f"Only you can receive tokens from this lock: cashu receive <token>")
print("Only you can receive tokens from this lock: cashu receive <token>")
@cli.command("locks", help="Show unused receiving locks.")
@@ -586,12 +591,12 @@ async def locks(ctx):
if len(locks):
print("")
print("---- Pay to script hash (P2SH) locks ----\n")
for l in locks:
print(f"Lock: P2SH:{l.address}")
print(f"Script: {l.script}")
print(f"Signature: {l.signature}")
for lock in locks:
print(f"Lock: P2SH:{lock.address}")
print(f"Script: {lock.script}")
print(f"Signature: {lock.signature}")
print("")
print(f"--------------------------\n")
print("--------------------------\n")
return True
@@ -604,7 +609,7 @@ async def invoices(ctx):
invoices = await get_lightning_invoices(db=wallet.db)
if len(invoices):
print("")
print(f"--------------------------\n")
print("--------------------------\n")
for invoice in invoices:
print(f"Paid: {invoice.paid}")
print(f"Incoming: {invoice.amount > 0}")
@@ -626,7 +631,7 @@ async def invoices(ctx):
print("")
print(f"Payment request: {invoice.pr}")
print("")
print(f"--------------------------\n")
print("--------------------------\n")
else:
print("No invoices found.")
@@ -652,9 +657,10 @@ async def wallets(ctx):
if w == ctx.obj["WALLET_NAME"]:
active_wallet = True
print(
f"Wallet: {w}\tBalance: {sum_proofs(wallet.proofs)} sat (available: {sum_proofs([p for p in wallet.proofs if not p.reserved])} sat){' *' if active_wallet else ''}"
f"Wallet: {w}\tBalance: {sum_proofs(wallet.proofs)} sat (available: "
f"{sum_proofs([p for p in wallet.proofs if not p.reserved])} sat){' *' if active_wallet else ''}"
)
except:
except Exception:
pass
@@ -679,8 +685,8 @@ async def info(ctx: Context, mint: bool, mnemonic: bool):
client = NostrClient(private_key=settings.nostr_private_key, connect=False)
print(f"Nostr public key: {client.public_key.bech32()}")
print(f"Nostr relays: {settings.nostr_relays}")
except:
print(f"Nostr: Error. Invalid key.")
except Exception:
print("Nostr: Error. Invalid key.")
if settings.socks_proxy:
print(f"Socks proxy: {settings.socks_proxy}")
if settings.http_proxy:

View File

@@ -1,21 +1,9 @@
import os
import urllib.parse
from typing import List
import click
from click import Context
from loguru import logger
from ...core.base import (
Proof,
TokenV1,
TokenV2,
TokenV2Mint,
TokenV3,
TokenV3Token,
WalletKeyset,
)
from ...core.helpers import sum_proofs
from ...core.settings import settings
from ...wallet.crud import get_keyset
from ...wallet.wallet import Wallet as Wallet
@@ -114,7 +102,7 @@ async def verify_mint(mint_wallet: Wallet, url: str):
print(f"Mint URL: {url}")
print("\n")
click.confirm(
f"Do you trust this mint and want to receive the tokens?",
"Do you trust this mint and want to receive the tokens?",
abort=True,
default=True,
)

View File

@@ -1,8 +1,7 @@
import json
import time
from typing import Any, List, Optional, Tuple
from ..core.base import Invoice, KeyBase, P2SHScript, Proof, WalletKeyset
from ..core.base import Invoice, P2SHScript, Proof, WalletKeyset
from ..core.db import Connection, Database
@@ -59,7 +58,7 @@ async def invalidate_proof(
conn: Optional[Connection] = None,
):
await (conn or db).execute(
f"""
"""
DELETE FROM proofs
WHERE secret = ?
""",
@@ -250,7 +249,7 @@ async def store_lightning_invoice(
conn: Optional[Connection] = None,
):
await (conn or db).execute(
f"""
"""
INSERT INTO invoices
(amount, pr, hash, preimage, paid, time_created, time_paid)
VALUES (?, ?, ?, ?, ?, ?, ?)
@@ -395,7 +394,7 @@ async def set_nostr_last_check_timestamp(
conn: Optional[Connection] = None,
):
await (conn or db).execute(
f"UPDATE nostr SET last = ? WHERE type = ?",
"UPDATE nostr SET last = ? WHERE type = ?",
(timestamp, "dm"),
)
@@ -405,7 +404,7 @@ async def get_nostr_last_check_timestamp(
conn: Optional[Connection] = None,
):
row = await (conn or db).fetchone(
f"""
"""
SELECT last from nostr WHERE type = ?
""",
("dm",),
@@ -418,7 +417,7 @@ async def get_seed_and_mnemonic(
conn: Optional[Connection] = None,
) -> Optional[Tuple[str, str]]:
row = await (conn or db).fetchone(
f"""
"""
SELECT seed, mnemonic from seed
""",
)
@@ -439,7 +438,7 @@ async def store_seed_and_mnemonic(
conn: Optional[Connection] = None,
):
await (conn or db).execute(
f"""
"""
INSERT INTO seed
(seed, mnemonic)
VALUES (?, ?)

View File

@@ -87,7 +87,7 @@ def deserialize_token_from_string(token: str) -> TokenV3:
try:
tokenv2 = TokenV2.parse_obj(json.loads(base64.urlsafe_b64decode(token)))
token = serialize_TokenV2_to_TokenV3(tokenv2)
except:
except Exception:
pass
# V1Tokens (<0.7) (W3siaWQ...)
@@ -95,7 +95,7 @@ def deserialize_token_from_string(token: str) -> TokenV3:
try:
tokenv1 = TokenV1.parse_obj(json.loads(base64.urlsafe_b64decode(token)))
token = serialize_TokenV1_to_TokenV3(tokenv1)
except:
except Exception:
pass
# ----- receive token -----

View File

@@ -151,7 +151,7 @@ async def m007_nostr(db: Database):
Stores timestamps of nostr operations.
"""
await db.execute(
f"""
"""
CREATE TABLE IF NOT EXISTS nostr (
type TEXT NOT NULL,
last TIMESTAMP DEFAULT NULL
@@ -159,7 +159,7 @@ async def m007_nostr(db: Database):
"""
)
await db.execute(
f"""
"""
INSERT INTO nostr
(type, last)
VALUES (?, ?)

View File

@@ -1,4 +1,3 @@
import asyncio
import base64
import hashlib
import json
@@ -10,7 +9,6 @@ from datetime import datetime, timedelta
from itertools import groupby
from typing import Dict, List, Optional, Tuple, Union
import click
import requests
from bip32 import BIP32
from loguru import logger
@@ -35,7 +33,6 @@ from ..core.base import (
PostMintResponse,
PostRestoreResponse,
PostSplitRequest,
PostSplitResponse_Deprecated,
Proof,
Secret,
SecretKind,
@@ -62,7 +59,6 @@ from ..core.script import (
)
from ..core.settings import settings
from ..core.split import amount_split
from ..nostr.nostr.client.client import NostrClient
from ..tor.tor import TorProxy
from ..wallet.crud import (
bump_secret_derivation,
@@ -101,7 +97,7 @@ def async_set_requests(func):
if settings.tor and TorProxy().check_platform():
self.tor = TorProxy(timeout=True)
self.tor.run_daemon(verbose=True)
proxy_url = f"socks5://localhost:9050"
proxy_url = "socks5://localhost:9050"
elif settings.socks_proxy:
proxy_url = f"socks5://{settings.socks_proxy}"
elif settings.http_proxy:
@@ -164,7 +160,7 @@ class LedgerAPI(object):
Returns:
List[Proof]: list of proofs that can be used as ecash
"""
logger.trace(f"Constructing proofs.")
logger.trace("Constructing proofs.")
proofs: List[Proof] = []
for promise, secret, r, path in zip(promises, secrets, rs, derivation_paths):
logger.trace(f"Creating proof with keyset {self.keyset_id} = {promise.id}")
@@ -249,7 +245,8 @@ class LedgerAPI(object):
"""Loads keys from mint and stores them in the database.
Args:
keyset_id (str, optional): keyset id to load. If given, requests keys for this keyset from the mint. If not given, requests current keyset of the mint. Defaults to "".
keyset_id (str, optional): keyset id to load. If given, requests keys for this keyset
from the mint. If not given, requests current keyset of the mint. Defaults to "".
Raises:
AssertionError: if mint URL is not set
@@ -297,7 +294,7 @@ class LedgerAPI(object):
mint_keysets = []
try:
mint_keysets = await self._get_keyset_ids(self.url)
except:
except Exception:
assert self.keys.id, "could not get keysets from mint, and do not have keys"
pass
self.keysets = mint_keysets or [self.keys.id]
@@ -735,7 +732,7 @@ class Wallet(LedgerAPI):
try:
self.bip32 = BIP32.from_seed(self.seed)
self.private_key = PrivateKey(
self.bip32.get_privkey_from_path(f"m/129372'/0'/0'/0'")
self.bip32.get_privkey_from_path("m/129372'/0'/0'/0'")
)
except ValueError:
raise ValueError("Invalid seed")
@@ -948,7 +945,7 @@ class Wallet(LedgerAPI):
try:
for p in proofs:
Secret.deserialize(p.secret)
except:
except Exception:
# if not, we do not add witnesses (treat as regular token secret)
return outputs
@@ -1015,20 +1012,20 @@ class Wallet(LedgerAPI):
try:
for p in proofs:
Secret.deserialize(p.secret)
except:
except Exception:
# if not, we do not add witnesses (treat as regular token secret)
return proofs
logger.debug(f"Spending conditions detected.")
logger.debug("Spending conditions detected.")
# P2SH scripts
if all([Secret.deserialize(p.secret).kind == SecretKind.P2SH for p in proofs]):
logger.debug(f"P2SH redemption detected.")
logger.debug("P2SH redemption detected.")
proofs = await self.add_p2sh_witnesses_to_proofs(proofs)
# P2PK signatures
elif all(
[Secret.deserialize(p.secret).kind == SecretKind.P2PK for p in proofs]
):
logger.debug(f"P2PK redemption detected.")
logger.debug("P2PK redemption detected.")
proofs = await self.add_p2pk_witnesses_to_proofs(proofs)
return proofs
@@ -1155,7 +1152,7 @@ class Wallet(LedgerAPI):
status = await super().pay_lightning(proofs, invoice, outputs)
if status.paid == True:
if status.paid:
# the payment was successful
await self.invalidate(proofs)
invoice_obj = Invoice(

334
poetry.lock generated
View File

@@ -1,10 +1,9 @@
# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand.
# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
[[package]]
name = "anyio"
version = "3.7.1"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -16,7 +15,6 @@ files = [
exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
idna = ">=2.8"
sniffio = ">=1.1"
typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
[package.extras]
doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"]
@@ -27,7 +25,6 @@ trio = ["trio (<0.22)"]
name = "asn1crypto"
version = "1.5.1"
description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP"
category = "main"
optional = false
python-versions = "*"
files = [
@@ -39,7 +36,6 @@ files = [
name = "attrs"
version = "23.1.0"
description = "Classes Without Boilerplate"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -47,9 +43,6 @@ files = [
{file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
]
[package.dependencies]
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
[package.extras]
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
dev = ["attrs[docs,tests]", "pre-commit"]
@@ -61,7 +54,6 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte
name = "base58"
version = "2.1.1"
description = "Base58 and Base58Check implementation."
category = "main"
optional = false
python-versions = ">=3.5"
files = [
@@ -76,7 +68,6 @@ tests = ["PyHamcrest (>=2.0.2)", "mypy", "pytest (>=4.6)", "pytest-benchmark", "
name = "bech32"
version = "1.2.0"
description = "Reference implementation for Bech32 and segwit addresses."
category = "main"
optional = false
python-versions = ">=3.5"
files = [
@@ -88,7 +79,6 @@ files = [
name = "bip32"
version = "3.4"
description = "Minimalistic implementation of the BIP32 key derivation scheme"
category = "main"
optional = false
python-versions = "*"
files = [
@@ -104,7 +94,6 @@ coincurve = ">=15.0,<19"
name = "bitstring"
version = "3.1.9"
description = "Simple construction, analysis and modification of binary data."
category = "main"
optional = false
python-versions = "*"
files = [
@@ -117,7 +106,6 @@ files = [
name = "black"
version = "22.12.0"
description = "The uncompromising code formatter."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -141,7 +129,6 @@ mypy-extensions = ">=0.4.3"
pathspec = ">=0.9.0"
platformdirs = ">=2"
tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""}
typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""}
typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
[package.extras]
@@ -152,21 +139,19 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "certifi"
version = "2023.5.7"
version = "2023.7.22"
description = "Python package for providing Mozilla's CA Bundle."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"},
{file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},
{file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"},
{file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"},
]
[[package]]
name = "cffi"
version = "1.15.1"
description = "Foreign Function Interface for Python calling C code."
category = "main"
optional = false
python-versions = "*"
files = [
@@ -243,7 +228,6 @@ pycparser = "*"
name = "charset-normalizer"
version = "3.2.0"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "main"
optional = false
python-versions = ">=3.7.0"
files = [
@@ -326,25 +310,22 @@ files = [
[[package]]
name = "click"
version = "8.1.5"
version = "8.1.6"
description = "Composable command line interface toolkit"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "click-8.1.5-py3-none-any.whl", hash = "sha256:e576aa487d679441d7d30abb87e1b43d24fc53bffb8758443b1a9e1cee504548"},
{file = "click-8.1.5.tar.gz", hash = "sha256:4be4b1af8d665c6d942909916d31a213a106800c47d0eeba73d34da3cbc11367"},
{file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"},
{file = "click-8.1.6.tar.gz", hash = "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd"},
]
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
[[package]]
name = "coincurve"
version = "18.0.0"
description = "Cross-platform Python CFFI bindings for libsecp256k1"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -400,7 +381,6 @@ cffi = ">=1.3.0"
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
@@ -412,7 +392,6 @@ files = [
name = "coverage"
version = "7.2.7"
description = "Code coverage measurement for Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -488,7 +467,6 @@ toml = ["tomli"]
name = "cryptography"
version = "36.0.2"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -529,7 +507,6 @@ test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0
name = "ecdsa"
version = "0.18.0"
description = "ECDSA cryptographic signature library (pure python)"
category = "main"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
@@ -548,7 +525,6 @@ gmpy2 = ["gmpy2"]
name = "environs"
version = "9.5.0"
description = "simplified environment variable parsing"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -570,7 +546,6 @@ tests = ["dj-database-url", "dj-email-url", "django-cache-url", "pytest"]
name = "exceptiongroup"
version = "1.1.2"
description = "Backport of PEP 654 (exception groups)"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -585,7 +560,6 @@ test = ["pytest (>=6)"]
name = "fastapi"
version = "0.83.0"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
category = "main"
optional = false
python-versions = ">=3.6.1"
files = [
@@ -603,11 +577,26 @@ dev = ["autoflake (>=1.4.0,<2.0.0)", "flake8 (>=3.8.3,<6.0.0)", "passlib[bcrypt]
doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer (>=0.4.1,<0.5.0)"]
test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==22.3.0)", "databases[sqlite] (>=0.3.2,<0.6.0)", "email_validator (>=1.1.1,<2.0.0)", "flake8 (>=3.8.3,<6.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.14.0,<0.19.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "orjson (>=3.2.1,<4.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=6.2.4,<7.0.0)", "pytest-cov (>=2.12.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "requests (>=2.24.0,<3.0.0)", "sqlalchemy (>=1.3.18,<1.5.0)", "types-dataclasses (==0.6.5)", "types-orjson (==3.6.2)", "types-ujson (==4.2.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"]
[[package]]
name = "flake8"
version = "6.0.0"
description = "the modular source code checker: pep8 pyflakes and co"
optional = false
python-versions = ">=3.8.1"
files = [
{file = "flake8-6.0.0-py2.py3-none-any.whl", hash = "sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7"},
{file = "flake8-6.0.0.tar.gz", hash = "sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"},
]
[package.dependencies]
mccabe = ">=0.7.0,<0.8.0"
pycodestyle = ">=2.10.0,<2.11.0"
pyflakes = ">=3.0.0,<3.1.0"
[[package]]
name = "h11"
version = "0.12.0"
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -619,7 +608,6 @@ files = [
name = "httpcore"
version = "0.15.0"
description = "A minimal low-level HTTP client."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -628,20 +616,19 @@ files = [
]
[package.dependencies]
anyio = ">=3.0.0,<4.0.0"
anyio = "==3.*"
certifi = "*"
h11 = ">=0.11,<0.13"
sniffio = ">=1.0.0,<2.0.0"
sniffio = "==1.*"
[package.extras]
http2 = ["h2 (>=3,<5)"]
socks = ["socksio (>=1.0.0,<2.0.0)"]
socks = ["socksio (==1.*)"]
[[package]]
name = "httpx"
version = "0.23.0"
description = "The next generation HTTP client."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -657,15 +644,14 @@ sniffio = "*"
[package.extras]
brotli = ["brotli", "brotlicffi"]
cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<13)"]
cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<13)"]
http2 = ["h2 (>=3,<5)"]
socks = ["socksio (>=1.0.0,<2.0.0)"]
socks = ["socksio (==1.*)"]
[[package]]
name = "idna"
version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "main"
optional = false
python-versions = ">=3.5"
files = [
@@ -677,7 +663,6 @@ files = [
name = "importlib-metadata"
version = "5.2.0"
description = "Read metadata from Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -686,7 +671,6 @@ files = [
]
[package.dependencies]
typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
zipp = ">=0.5"
[package.extras]
@@ -698,7 +682,6 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag
name = "iniconfig"
version = "2.0.0"
description = "brain-dead simple config-ini parsing"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -708,18 +691,17 @@ files = [
[[package]]
name = "isort"
version = "5.11.5"
version = "5.12.0"
description = "A Python utility / library to sort Python imports."
category = "dev"
optional = false
python-versions = ">=3.7.0"
python-versions = ">=3.8.0"
files = [
{file = "isort-5.11.5-py3-none-any.whl", hash = "sha256:ba1d72fb2595a01c7895a5128f9585a5cc4b6d395f1c8d514989b9a7eb2a8746"},
{file = "isort-5.11.5.tar.gz", hash = "sha256:6be1f76a507cb2ecf16c7cf14a37e41609ca082330be4e3436a18ef74add55db"},
{file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"},
{file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
]
[package.extras]
colors = ["colorama (>=0.4.3,<0.5.0)"]
colors = ["colorama (>=0.4.3)"]
pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"]
plugins = ["setuptools"]
requirements-deprecated-finder = ["pip-api", "pipreqs"]
@@ -728,7 +710,6 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"]
name = "loguru"
version = "0.6.0"
description = "Python logging made (stupidly) simple"
category = "main"
optional = false
python-versions = ">=3.5"
files = [
@@ -745,30 +726,39 @@ dev = ["Sphinx (>=4.1.1)", "black (>=19.10b0)", "colorama (>=0.3.4)", "docutils
[[package]]
name = "marshmallow"
version = "3.19.0"
version = "3.20.1"
description = "A lightweight library for converting complex datatypes to and from native Python datatypes."
category = "main"
optional = false
python-versions = ">=3.7"
python-versions = ">=3.8"
files = [
{file = "marshmallow-3.19.0-py3-none-any.whl", hash = "sha256:93f0958568da045b0021ec6aeb7ac37c81bfcccbb9a0e7ed8559885070b3a19b"},
{file = "marshmallow-3.19.0.tar.gz", hash = "sha256:90032c0fd650ce94b6ec6dc8dfeb0e3ff50c144586462c389b81a07205bedb78"},
{file = "marshmallow-3.20.1-py3-none-any.whl", hash = "sha256:684939db93e80ad3561392f47be0230743131560a41c5110684c16e21ade0a5c"},
{file = "marshmallow-3.20.1.tar.gz", hash = "sha256:5d2371bbe42000f2b3fb5eaa065224df7d8f8597bc19a1bbfa5bfe7fba8da889"},
]
[package.dependencies]
packaging = ">=17.0"
[package.extras]
dev = ["flake8 (==5.0.4)", "flake8-bugbear (==22.10.25)", "mypy (==0.990)", "pre-commit (>=2.4,<3.0)", "pytest", "pytz", "simplejson", "tox"]
docs = ["alabaster (==0.7.12)", "autodocsumm (==0.2.9)", "sphinx (==5.3.0)", "sphinx-issues (==3.0.1)", "sphinx-version-warning (==1.1.2)"]
lint = ["flake8 (==5.0.4)", "flake8-bugbear (==22.10.25)", "mypy (==0.990)", "pre-commit (>=2.4,<3.0)"]
dev = ["flake8 (==6.0.0)", "flake8-bugbear (==23.7.10)", "mypy (==1.4.1)", "pre-commit (>=2.4,<4.0)", "pytest", "pytz", "simplejson", "tox"]
docs = ["alabaster (==0.7.13)", "autodocsumm (==0.2.11)", "sphinx (==7.0.1)", "sphinx-issues (==3.0.1)", "sphinx-version-warning (==1.1.2)"]
lint = ["flake8 (==6.0.0)", "flake8-bugbear (==23.7.10)", "mypy (==1.4.1)", "pre-commit (>=2.4,<4.0)"]
tests = ["pytest", "pytz", "simplejson"]
[[package]]
name = "mccabe"
version = "0.7.0"
description = "McCabe checker, plugin for flake8"
optional = false
python-versions = ">=3.6"
files = [
{file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
{file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
]
[[package]]
name = "mnemonic"
version = "0.20"
description = "Implementation of Bitcoin BIP-0039"
category = "main"
optional = false
python-versions = ">=3.5"
files = [
@@ -780,7 +770,6 @@ files = [
name = "mypy"
version = "0.971"
description = "Optional static typing for Python"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -812,7 +801,6 @@ files = [
[package.dependencies]
mypy-extensions = ">=0.4.3"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
typed-ast = {version = ">=1.4.0,<2", markers = "python_version < \"3.8\""}
typing-extensions = ">=3.10"
[package.extras]
@@ -824,7 +812,6 @@ reports = ["lxml"]
name = "mypy-extensions"
version = "1.0.0"
description = "Type system extensions for programs checked with the mypy type checker."
category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@@ -836,7 +823,6 @@ files = [
name = "outcome"
version = "1.2.0"
description = "Capture the outcome of Python function calls."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -851,7 +837,6 @@ attrs = ">=19.2.0"
name = "packaging"
version = "23.1"
description = "Core utilities for Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -863,7 +848,6 @@ files = [
name = "pathspec"
version = "0.11.1"
description = "Utility library for gitignore style pattern matching of file paths."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -875,7 +859,6 @@ files = [
name = "platformdirs"
version = "3.9.1"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -883,9 +866,6 @@ files = [
{file = "platformdirs-3.9.1.tar.gz", hash = "sha256:1b42b450ad933e981d56e59f1b97495428c9bd60698baab9f3eb3d00d5822421"},
]
[package.dependencies]
typing-extensions = {version = ">=4.6.3", markers = "python_version < \"3.8\""}
[package.extras]
docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"]
@@ -894,7 +874,6 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-
name = "pluggy"
version = "1.2.0"
description = "plugin and hook calling mechanisms for python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -902,9 +881,6 @@ files = [
{file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"},
]
[package.dependencies]
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
[package.extras]
dev = ["pre-commit", "tox"]
testing = ["pytest", "pytest-benchmark"]
@@ -913,7 +889,6 @@ testing = ["pytest", "pytest-benchmark"]
name = "psycopg2-binary"
version = "2.9.6"
description = "psycopg2 - Python-PostgreSQL Database Adapter"
category = "main"
optional = true
python-versions = ">=3.6"
files = [
@@ -981,11 +956,21 @@ files = [
{file = "psycopg2_binary-2.9.6-cp39-cp39-win_amd64.whl", hash = "sha256:f6a88f384335bb27812293fdb11ac6aee2ca3f51d3c7820fe03de0a304ab6249"},
]
[[package]]
name = "pycodestyle"
version = "2.10.0"
description = "Python style guide checker"
optional = false
python-versions = ">=3.6"
files = [
{file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"},
{file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"},
]
[[package]]
name = "pycparser"
version = "2.21"
description = "C parser in Python"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -997,7 +982,6 @@ files = [
name = "pycryptodomex"
version = "3.18.0"
description = "Cryptographic library for Python"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
@@ -1037,48 +1021,47 @@ files = [
[[package]]
name = "pydantic"
version = "1.10.11"
version = "1.10.12"
description = "Data validation and settings management using python type hints"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "pydantic-1.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ff44c5e89315b15ff1f7fdaf9853770b810936d6b01a7bcecaa227d2f8fe444f"},
{file = "pydantic-1.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a6c098d4ab5e2d5b3984d3cb2527e2d6099d3de85630c8934efcfdc348a9760e"},
{file = "pydantic-1.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16928fdc9cb273c6af00d9d5045434c39afba5f42325fb990add2c241402d151"},
{file = "pydantic-1.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0588788a9a85f3e5e9ebca14211a496409cb3deca5b6971ff37c556d581854e7"},
{file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9baf78b31da2dc3d3f346ef18e58ec5f12f5aaa17ac517e2ffd026a92a87588"},
{file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:373c0840f5c2b5b1ccadd9286782852b901055998136287828731868027a724f"},
{file = "pydantic-1.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:c3339a46bbe6013ef7bdd2844679bfe500347ac5742cd4019a88312aa58a9847"},
{file = "pydantic-1.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:08a6c32e1c3809fbc49debb96bf833164f3438b3696abf0fbeceb417d123e6eb"},
{file = "pydantic-1.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a451ccab49971af043ec4e0d207cbc8cbe53dbf148ef9f19599024076fe9c25b"},
{file = "pydantic-1.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b02d24f7b2b365fed586ed73582c20f353a4c50e4be9ba2c57ab96f8091ddae"},
{file = "pydantic-1.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f34739a89260dfa420aa3cbd069fbcc794b25bbe5c0a214f8fb29e363484b66"},
{file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e297897eb4bebde985f72a46a7552a7556a3dd11e7f76acda0c1093e3dbcf216"},
{file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d185819a7a059550ecb85d5134e7d40f2565f3dd94cfd870132c5f91a89cf58c"},
{file = "pydantic-1.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:4400015f15c9b464c9db2d5d951b6a780102cfa5870f2c036d37c23b56f7fc1b"},
{file = "pydantic-1.10.11-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2417de68290434461a266271fc57274a138510dca19982336639484c73a07af6"},
{file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:331c031ba1554b974c98679bd0780d89670d6fd6f53f5d70b10bdc9addee1713"},
{file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8268a735a14c308923e8958363e3a3404f6834bb98c11f5ab43251a4e410170c"},
{file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:44e51ba599c3ef227e168424e220cd3e544288c57829520dc90ea9cb190c3248"},
{file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d7781f1d13b19700b7949c5a639c764a077cbbdd4322ed505b449d3ca8edcb36"},
{file = "pydantic-1.10.11-cp37-cp37m-win_amd64.whl", hash = "sha256:7522a7666157aa22b812ce14c827574ddccc94f361237ca6ea8bb0d5c38f1629"},
{file = "pydantic-1.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc64eab9b19cd794a380179ac0e6752335e9555d214cfcb755820333c0784cb3"},
{file = "pydantic-1.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8dc77064471780262b6a68fe67e013298d130414d5aaf9b562c33987dbd2cf4f"},
{file = "pydantic-1.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe429898f2c9dd209bd0632a606bddc06f8bce081bbd03d1c775a45886e2c1cb"},
{file = "pydantic-1.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:192c608ad002a748e4a0bed2ddbcd98f9b56df50a7c24d9a931a8c5dd053bd3d"},
{file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ef55392ec4bb5721f4ded1096241e4b7151ba6d50a50a80a2526c854f42e6a2f"},
{file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:41e0bb6efe86281623abbeeb0be64eab740c865388ee934cd3e6a358784aca6e"},
{file = "pydantic-1.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:265a60da42f9f27e0b1014eab8acd3e53bd0bad5c5b4884e98a55f8f596b2c19"},
{file = "pydantic-1.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:469adf96c8e2c2bbfa655fc7735a2a82f4c543d9fee97bd113a7fb509bf5e622"},
{file = "pydantic-1.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e6cbfbd010b14c8a905a7b10f9fe090068d1744d46f9e0c021db28daeb8b6de1"},
{file = "pydantic-1.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abade85268cc92dff86d6effcd917893130f0ff516f3d637f50dadc22ae93999"},
{file = "pydantic-1.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9738b0f2e6c70f44ee0de53f2089d6002b10c33264abee07bdb5c7f03038303"},
{file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:787cf23e5a0cde753f2eabac1b2e73ae3844eb873fd1f5bdbff3048d8dbb7604"},
{file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:174899023337b9fc685ac8adaa7b047050616136ccd30e9070627c1aaab53a13"},
{file = "pydantic-1.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:1954f8778489a04b245a1e7b8b22a9d3ea8ef49337285693cf6959e4b757535e"},
{file = "pydantic-1.10.11-py3-none-any.whl", hash = "sha256:008c5e266c8aada206d0627a011504e14268a62091450210eda7c07fabe6963e"},
{file = "pydantic-1.10.11.tar.gz", hash = "sha256:f66d479cf7eb331372c470614be6511eae96f1f120344c25f3f9bb59fb1b5528"},
{file = "pydantic-1.10.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718"},
{file = "pydantic-1.10.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe"},
{file = "pydantic-1.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b"},
{file = "pydantic-1.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d"},
{file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09"},
{file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed"},
{file = "pydantic-1.10.12-cp310-cp310-win_amd64.whl", hash = "sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a"},
{file = "pydantic-1.10.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc"},
{file = "pydantic-1.10.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405"},
{file = "pydantic-1.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62"},
{file = "pydantic-1.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494"},
{file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246"},
{file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33"},
{file = "pydantic-1.10.12-cp311-cp311-win_amd64.whl", hash = "sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f"},
{file = "pydantic-1.10.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a"},
{file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565"},
{file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350"},
{file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303"},
{file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5"},
{file = "pydantic-1.10.12-cp37-cp37m-win_amd64.whl", hash = "sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8"},
{file = "pydantic-1.10.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62"},
{file = "pydantic-1.10.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb"},
{file = "pydantic-1.10.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0"},
{file = "pydantic-1.10.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c"},
{file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d"},
{file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33"},
{file = "pydantic-1.10.12-cp38-cp38-win_amd64.whl", hash = "sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47"},
{file = "pydantic-1.10.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6"},
{file = "pydantic-1.10.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523"},
{file = "pydantic-1.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86"},
{file = "pydantic-1.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1"},
{file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe"},
{file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb"},
{file = "pydantic-1.10.12-cp39-cp39-win_amd64.whl", hash = "sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d"},
{file = "pydantic-1.10.12-py3-none-any.whl", hash = "sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942"},
{file = "pydantic-1.10.12.tar.gz", hash = "sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303"},
]
[package.dependencies]
@@ -1088,11 +1071,21 @@ typing-extensions = ">=4.2.0"
dotenv = ["python-dotenv (>=0.10.4)"]
email = ["email-validator (>=1.0.3)"]
[[package]]
name = "pyflakes"
version = "3.0.1"
description = "passive checker of Python programs"
optional = false
python-versions = ">=3.6"
files = [
{file = "pyflakes-3.0.1-py2.py3-none-any.whl", hash = "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf"},
{file = "pyflakes-3.0.1.tar.gz", hash = "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"},
]
[[package]]
name = "pysocks"
version = "1.7.1"
description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -1105,7 +1098,6 @@ files = [
name = "pytest"
version = "7.4.0"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1116,7 +1108,6 @@ files = [
[package.dependencies]
colorama = {version = "*", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
iniconfig = "*"
packaging = "*"
pluggy = ">=0.12,<2.0"
@@ -1129,7 +1120,6 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no
name = "pytest-asyncio"
version = "0.19.0"
description = "Pytest support for asyncio"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1139,7 +1129,6 @@ files = [
[package.dependencies]
pytest = ">=6.1.0"
typing-extensions = {version = ">=3.7.2", markers = "python_version < \"3.8\""}
[package.extras]
testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"]
@@ -1148,7 +1137,6 @@ testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy
name = "pytest-cov"
version = "4.1.0"
description = "Pytest plugin for measuring coverage."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1167,7 +1155,6 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale
name = "python-bitcoinlib"
version = "0.11.2"
description = "The Swiss Army Knife of the Bitcoin protocol."
category = "main"
optional = false
python-versions = "*"
files = [
@@ -1177,14 +1164,13 @@ files = [
[[package]]
name = "python-dotenv"
version = "0.21.1"
version = "1.0.0"
description = "Read key-value pairs from a .env file and set them as environment variables"
category = "main"
optional = false
python-versions = ">=3.7"
python-versions = ">=3.8"
files = [
{file = "python-dotenv-0.21.1.tar.gz", hash = "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49"},
{file = "python_dotenv-0.21.1-py3-none-any.whl", hash = "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"},
{file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"},
{file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"},
]
[package.extras]
@@ -1194,7 +1180,6 @@ cli = ["click (>=5.0)"]
name = "represent"
version = "1.6.0.post0"
description = "Create __repr__ automatically or declaratively."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -1212,7 +1197,6 @@ test = ["ipython", "mock", "pytest (>=3.0.5)"]
name = "requests"
version = "2.31.0"
description = "Python HTTP for Humans."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -1234,7 +1218,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
name = "rfc3986"
version = "1.5.0"
description = "Validating URI References per RFC 3986"
category = "main"
optional = false
python-versions = "*"
files = [
@@ -1252,7 +1235,6 @@ idna2008 = ["idna"]
name = "secp256k1"
version = "0.14.0"
description = "FFI bindings to libsecp256k1"
category = "main"
optional = false
python-versions = "*"
files = [
@@ -1288,7 +1270,6 @@ cffi = ">=1.3.0"
name = "setuptools"
version = "65.7.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -1305,7 +1286,6 @@ testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
@@ -1317,7 +1297,6 @@ files = [
name = "sniffio"
version = "1.3.0"
description = "Sniff out which async library your code is running under"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -1329,7 +1308,6 @@ files = [
name = "sqlalchemy"
version = "1.3.24"
description = "Database Abstraction Library"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -1385,7 +1363,6 @@ pymysql = ["pymysql", "pymysql (<1)"]
name = "sqlalchemy-aio"
version = "0.17.0"
description = "Async support for SQLAlchemy."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1407,7 +1384,6 @@ trio = ["trio (>=0.15)"]
name = "starlette"
version = "0.19.1"
description = "The little ASGI library that shines."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -1426,7 +1402,6 @@ full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1434,62 +1409,10 @@ files = [
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
[[package]]
name = "typed-ast"
version = "1.5.5"
description = "a fork of Python 2 and 3 ast modules with type comment support"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "typed_ast-1.5.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bc1efe0ce3ffb74784e06460f01a223ac1f6ab31c6bc0376a21184bf5aabe3b"},
{file = "typed_ast-1.5.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f7a8c46a8b333f71abd61d7ab9255440d4a588f34a21f126bbfc95f6049e686"},
{file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597fc66b4162f959ee6a96b978c0435bd63791e31e4f410622d19f1686d5e769"},
{file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d41b7a686ce653e06c2609075d397ebd5b969d821b9797d029fccd71fdec8e04"},
{file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5fe83a9a44c4ce67c796a1b466c270c1272e176603d5e06f6afbc101a572859d"},
{file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d5c0c112a74c0e5db2c75882a0adf3133adedcdbfd8cf7c9d6ed77365ab90a1d"},
{file = "typed_ast-1.5.5-cp310-cp310-win_amd64.whl", hash = "sha256:e1a976ed4cc2d71bb073e1b2a250892a6e968ff02aa14c1f40eba4f365ffec02"},
{file = "typed_ast-1.5.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c631da9710271cb67b08bd3f3813b7af7f4c69c319b75475436fcab8c3d21bee"},
{file = "typed_ast-1.5.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b445c2abfecab89a932b20bd8261488d574591173d07827c1eda32c457358b18"},
{file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc95ffaaab2be3b25eb938779e43f513e0e538a84dd14a5d844b8f2932593d88"},
{file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61443214d9b4c660dcf4b5307f15c12cb30bdfe9588ce6158f4a005baeb167b2"},
{file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6eb936d107e4d474940469e8ec5b380c9b329b5f08b78282d46baeebd3692dc9"},
{file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e48bf27022897577d8479eaed64701ecaf0467182448bd95759883300ca818c8"},
{file = "typed_ast-1.5.5-cp311-cp311-win_amd64.whl", hash = "sha256:83509f9324011c9a39faaef0922c6f720f9623afe3fe220b6d0b15638247206b"},
{file = "typed_ast-1.5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:44f214394fc1af23ca6d4e9e744804d890045d1643dd7e8229951e0ef39429b5"},
{file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:118c1ce46ce58fda78503eae14b7664163aa735b620b64b5b725453696f2a35c"},
{file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be4919b808efa61101456e87f2d4c75b228f4e52618621c77f1ddcaae15904fa"},
{file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fc2b8c4e1bc5cd96c1a823a885e6b158f8451cf6f5530e1829390b4d27d0807f"},
{file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:16f7313e0a08c7de57f2998c85e2a69a642e97cb32f87eb65fbfe88381a5e44d"},
{file = "typed_ast-1.5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:2b946ef8c04f77230489f75b4b5a4a6f24c078be4aed241cfabe9cbf4156e7e5"},
{file = "typed_ast-1.5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2188bc33d85951ea4ddad55d2b35598b2709d122c11c75cffd529fbc9965508e"},
{file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0635900d16ae133cab3b26c607586131269f88266954eb04ec31535c9a12ef1e"},
{file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57bfc3cf35a0f2fdf0a88a3044aafaec1d2f24d8ae8cd87c4f58d615fb5b6311"},
{file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:fe58ef6a764de7b4b36edfc8592641f56e69b7163bba9f9c8089838ee596bfb2"},
{file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d09d930c2d1d621f717bb217bf1fe2584616febb5138d9b3e8cdd26506c3f6d4"},
{file = "typed_ast-1.5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:d40c10326893ecab8a80a53039164a224984339b2c32a6baf55ecbd5b1df6431"},
{file = "typed_ast-1.5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fd946abf3c31fb50eee07451a6aedbfff912fcd13cf357363f5b4e834cc5e71a"},
{file = "typed_ast-1.5.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ed4a1a42df8a3dfb6b40c3d2de109e935949f2f66b19703eafade03173f8f437"},
{file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045f9930a1550d9352464e5149710d56a2aed23a2ffe78946478f7b5416f1ede"},
{file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:381eed9c95484ceef5ced626355fdc0765ab51d8553fec08661dce654a935db4"},
{file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bfd39a41c0ef6f31684daff53befddae608f9daf6957140228a08e51f312d7e6"},
{file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8c524eb3024edcc04e288db9541fe1f438f82d281e591c548903d5b77ad1ddd4"},
{file = "typed_ast-1.5.5-cp38-cp38-win_amd64.whl", hash = "sha256:7f58fabdde8dcbe764cef5e1a7fcb440f2463c1bbbec1cf2a86ca7bc1f95184b"},
{file = "typed_ast-1.5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:042eb665ff6bf020dd2243307d11ed626306b82812aba21836096d229fdc6a10"},
{file = "typed_ast-1.5.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:622e4a006472b05cf6ef7f9f2636edc51bda670b7bbffa18d26b255269d3d814"},
{file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1efebbbf4604ad1283e963e8915daa240cb4bf5067053cf2f0baadc4d4fb51b8"},
{file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0aefdd66f1784c58f65b502b6cf8b121544680456d1cebbd300c2c813899274"},
{file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:48074261a842acf825af1968cd912f6f21357316080ebaca5f19abbb11690c8a"},
{file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:429ae404f69dc94b9361bb62291885894b7c6fb4640d561179548c849f8492ba"},
{file = "typed_ast-1.5.5-cp39-cp39-win_amd64.whl", hash = "sha256:335f22ccb244da2b5c296e6f96b06ee9bed46526db0de38d2f0e5a6597b81155"},
{file = "typed_ast-1.5.5.tar.gz", hash = "sha256:94282f7a354f36ef5dbce0ef3467ebf6a258e370ab33d5b40c249fa996e590dd"},
]
[[package]]
name = "typing-extensions"
version = "4.7.1"
description = "Backported and Experimental Type Hints for Python 3.7+"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -1499,14 +1422,13 @@ files = [
[[package]]
name = "urllib3"
version = "2.0.3"
version = "2.0.4"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "urllib3-2.0.3-py3-none-any.whl", hash = "sha256:48e7fafa40319d358848e1bc6809b208340fafe2096f1725d05d67443d0483d1"},
{file = "urllib3-2.0.3.tar.gz", hash = "sha256:bee28b5e56addb8226c96f7f13ac28cb4c301dd5ea8a6ca179c0b9835e032825"},
{file = "urllib3-2.0.4-py3-none-any.whl", hash = "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"},
{file = "urllib3-2.0.4.tar.gz", hash = "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11"},
]
[package.extras]
@@ -1519,7 +1441,6 @@ zstd = ["zstandard (>=0.18.0)"]
name = "uvicorn"
version = "0.18.3"
description = "The lightning-fast ASGI server."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -1530,7 +1451,6 @@ files = [
[package.dependencies]
click = ">=7.0"
h11 = ">=0.8"
typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
[package.extras]
standard = ["colorama (>=0.4)", "httptools (>=0.4.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.0)"]
@@ -1539,7 +1459,6 @@ standard = ["colorama (>=0.4)", "httptools (>=0.4.0)", "python-dotenv (>=0.13)",
name = "websocket-client"
version = "1.6.1"
description = "WebSocket client for Python with low level API options"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -1556,7 +1475,6 @@ test = ["websockets"]
name = "wheel"
version = "0.38.4"
description = "A built-package format for Python"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -1571,7 +1489,6 @@ test = ["pytest (>=3.0.0)"]
name = "win32-setctime"
version = "1.1.0"
description = "A small Python utility to set file creation time on Windows"
category = "main"
optional = false
python-versions = ">=3.5"
files = [
@@ -1584,24 +1501,23 @@ dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
[[package]]
name = "zipp"
version = "3.15.0"
version = "3.16.2"
description = "Backport of pathlib-compatible object wrapper for zip files"
category = "main"
optional = false
python-versions = ">=3.7"
python-versions = ">=3.8"
files = [
{file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
{file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
{file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"},
{file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"},
]
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
[extras]
pgsql = ["psycopg2-binary"]
[metadata]
lock-version = "2.0"
python-versions = "^3.7"
content-hash = "22155a0a398b0cb50e8df08d43c4482aeffcc2e2cfcf2827b2e1daa2c30d8755"
python-versions = "^3.8.1"
content-hash = "f3a00adb87135df6d2c6cce6f65f4d616dbfb5501e50e5774e79095301fdb72b"

View File

@@ -6,7 +6,7 @@ authors = ["calle <callebtc@protonmail.com>"]
license = "MIT"
[tool.poetry.dependencies]
python = "^3.7"
python = "^3.8.1"
requests = "^2.27.1"
SQLAlchemy = "^1.3.24"
click = "^8.0.4"
@@ -44,6 +44,7 @@ isort = "^5.10.1"
pytest-asyncio = "^0.19.0"
pytest-cov = "^4.0.0"
pytest = "^7.4.0"
flake8 = "^6.0.0"
[build-system]
requires = ["poetry-core>=1.0.0"]

View File

@@ -1,6 +1,5 @@
import multiprocessing
import os
import secrets
import shutil
import time
from pathlib import Path
@@ -8,7 +7,6 @@ from pathlib import Path
import pytest
import pytest_asyncio
import uvicorn
from fastapi import FastAPI
from uvicorn import Config, Server
from cashu.core.db import Database
@@ -17,9 +15,6 @@ from cashu.core.settings import settings
from cashu.lightning.fake import FakeWallet
from cashu.mint import migrations as migrations_mint
from cashu.mint.ledger import Ledger
from cashu.wallet import migrations as migrations_wallet
from cashu.wallet.api.router import router
from cashu.wallet.wallet import Wallet
SERVER_ENDPOINT = "http://localhost:3337"

View File

@@ -3,12 +3,9 @@ import asyncio
import pytest
from click.testing import CliRunner
from cashu.core.migrations import migrate_databases
from cashu.core.settings import settings
from cashu.wallet import migrations
from cashu.wallet.cli.cli import cli
from cashu.wallet.wallet import Wallet
from tests.conftest import SERVER_ENDPOINT, mint
@pytest.fixture(autouse=True, scope="session")
@@ -165,7 +162,12 @@ def test_send_without_split_but_wrong_amount(mint, cli_prefix):
@pytest.mark.asyncio
def test_receive_tokenv3(mint, cli_prefix):
runner = CliRunner()
token = "cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIjFjQ05JQVoyWC93MSIsICJhbW91bnQiOiAyLCAic2VjcmV0IjogIld6TEF2VW53SDlRaFYwQU1rMy1oYWciLCAiQyI6ICIwMmZlMzUxYjAyN2FlMGY1ZDkyN2U2ZjFjMTljMjNjNTc3NzRhZTI2M2UyOGExN2E2MTUxNjY1ZjU3NWNhNjMyNWMifSwgeyJpZCI6ICIxY0NOSUFaMlgvdzEiLCAiYW1vdW50IjogOCwgInNlY3JldCI6ICJDamFTeTcyR2dVOGwzMGV6bE5zZnVBIiwgIkMiOiAiMDNjMzM0OTJlM2ZlNjI4NzFhMWEzMDhiNWUyYjVhZjBkNWI1Mjk5YzI0YmVkNDI2ZjQ1YzZmNDg5N2QzZjc4NGQ5In1dLCAibWludCI6ICJodHRwOi8vbG9jYWxob3N0OjMzMzcifV19"
token = (
"cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIjFjQ05JQVoyWC93MSIsICJhbW91bnQiOiAyLCAic2VjcmV0IjogIld6TEF2VW53SDlRaFYwQU1rMy1oYWciLC"
"AiQyI6ICIwMmZlMzUxYjAyN2FlMGY1ZDkyN2U2ZjFjMTljMjNjNTc3NzRhZTI2M2UyOGExN2E2MTUxNjY1ZjU3NWNhNjMyNWMifSwgeyJpZCI6ICIxY0NOSUFaMlgvdzEiLCAiYW"
"1vdW50IjogOCwgInNlY3JldCI6ICJDamFTeTcyR2dVOGwzMGV6bE5zZnVBIiwgIkMiOiAiMDNjMzM0OTJlM2ZlNjI4NzFhMWEzMDhiNWUyYjVhZjBkNWI1Mjk5YzI0YmVkNDI2Zj"
"Q1YzZmNDg5N2QzZjc4NGQ5In1dLCAibWludCI6ICJodHRwOi8vbG9jYWxob3N0OjMzMzcifV19"
)
result = runner.invoke(
cli,
[
@@ -184,7 +186,12 @@ def test_receive_tokenv3_no_mint(mint, cli_prefix):
# this test works only if the previous test succeeds because we simulate the case where the mint URL is not in the token
# therefore, we need to know the mint keyset already and have the mint URL in the db
runner = CliRunner()
token = "cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIjFjQ05JQVoyWC93MSIsICJhbW91bnQiOiAyLCAic2VjcmV0IjogIi1oM0ZXMFFoX1FYLW9ac1V2c0RuNlEiLCAiQyI6ICIwMzY5Mzc4MzdlYjg5ZWI4NjMyNWYwOWUyOTIxMWQxYTI4OTRlMzQ2YmM1YzQwZTZhMThlNTk5ZmVjNjEwOGRmMGIifSwgeyJpZCI6ICIxY0NOSUFaMlgvdzEiLCAiYW1vdW50IjogOCwgInNlY3JldCI6ICI3d0VhNUgzZGhSRGRNZl94c1k3c3JnIiwgIkMiOiAiMDJiZmZkM2NlZDkxNjUyMzcxMDg2NjQxMzJiMjgxYjBhZjY1ZTNlZWVkNTY3MmFkZjM0Y2VhNzE5ODhhZWM1NWI1In1dfV19"
token = (
"cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIjFjQ05JQVoyWC93MSIsICJhbW91bnQiOiAyLCAic2VjcmV0IjogIi1oM0ZXMFFoX1FYLW9ac1V2c0RuNlEiLC"
"AiQyI6ICIwMzY5Mzc4MzdlYjg5ZWI4NjMyNWYwOWUyOTIxMWQxYTI4OTRlMzQ2YmM1YzQwZTZhMThlNTk5ZmVjNjEwOGRmMGIifSwgeyJpZCI6ICIxY0NOSUFaMlgvdzEiLCAiYW"
"1vdW50IjogOCwgInNlY3JldCI6ICI3d0VhNUgzZGhSRGRNZl94c1k3c3JnIiwgIkMiOiAiMDJiZmZkM2NlZDkxNjUyMzcxMDg2NjQxMzJiMjgxYjBhZjY1ZTNlZWVkNTY3MmFkZj"
"M0Y2VhNzE5ODhhZWM1NWI1In1dfV19"
)
result = runner.invoke(
cli,
[
@@ -201,7 +208,12 @@ def test_receive_tokenv3_no_mint(mint, cli_prefix):
@pytest.mark.asyncio
def test_receive_tokenv2(mint, cli_prefix):
runner = CliRunner()
token = "eyJwcm9vZnMiOiBbeyJpZCI6ICIxY0NOSUFaMlgvdzEiLCAiYW1vdW50IjogMiwgInNlY3JldCI6ICJhUmREbzlFdW9yZUVfOW90enRNVVpnIiwgIkMiOiAiMDNhMzY5ZmUyN2IxYmVmOTg4MzA3NDQyN2RjMzc1NmU0NThlMmMwYjQ1NWMwYmVmZGM4ZjVmNTA3YmM5MGQxNmU3In0sIHsiaWQiOiAiMWNDTklBWjJYL3cxIiwgImFtb3VudCI6IDgsICJzZWNyZXQiOiAiTEZQbFp6Ui1MWHFfYXFDMGhUeDQyZyIsICJDIjogIjAzNGNiYzQxYWY0ODIxMGFmNjVmYjVjOWIzOTNkMjhmMmQ5ZDZhOWE5MzI2YmI3MzQ2YzVkZmRmMTU5MDk1MzI2YyJ9XSwgIm1pbnRzIjogW3sidXJsIjogImh0dHA6Ly9sb2NhbGhvc3Q6MzMzNyIsICJpZHMiOiBbIjFjQ05JQVoyWC93MSJdfV19"
token = (
"eyJwcm9vZnMiOiBbeyJpZCI6ICIxY0NOSUFaMlgvdzEiLCAiYW1vdW50IjogMiwgInNlY3JldCI6ICJhUmREbzlFdW9yZUVfOW90enRNVVpnIiwgIkMiOiAiMDNhMzY5ZmUy"
"N2IxYmVmOTg4MzA3NDQyN2RjMzc1NmU0NThlMmMwYjQ1NWMwYmVmZGM4ZjVmNTA3YmM5MGQxNmU3In0sIHsiaWQiOiAiMWNDTklBWjJYL3cxIiwgImFtb3VudCI6IDgsICJzZWNy"
"ZXQiOiAiTEZQbFp6Ui1MWHFfYXFDMGhUeDQyZyIsICJDIjogIjAzNGNiYzQxYWY0ODIxMGFmNjVmYjVjOWIzOTNkMjhmMmQ5ZDZhOWE5MzI2YmI3MzQ2YzVkZmRmMTU5MDk1MzI2"
"YyJ9XSwgIm1pbnRzIjogW3sidXJsIjogImh0dHA6Ly9sb2NhbGhvc3Q6MzMzNyIsICJpZHMiOiBbIjFjQ05JQVoyWC93MSJdfV19"
)
result = runner.invoke(
cli,
[*cli_prefix, "receive", token],
@@ -214,7 +226,11 @@ def test_receive_tokenv2(mint, cli_prefix):
@pytest.mark.asyncio
def test_receive_tokenv1(mint, cli_prefix):
runner = CliRunner()
token = "W3siaWQiOiAiMWNDTklBWjJYL3cxIiwgImFtb3VudCI6IDIsICJzZWNyZXQiOiAiRnVsc2dzMktQV1FMcUlLX200SzgwQSIsICJDIjogIjAzNTc4OThlYzlhMjIxN2VhYWIxZDc3YmM1Mzc2OTUwMjJlMjU2YTljMmMwNjc0ZDJlM2FiM2JiNGI0ZDMzMWZiMSJ9LCB7ImlkIjogIjFjQ05JQVoyWC93MSIsICJhbW91bnQiOiA4LCAic2VjcmV0IjogInJlRDBDazVNS2xBTUQ0dWk2OEtfbEEiLCAiQyI6ICIwMjNkODNkNDE0MDU0NWQ1NTg4NjUyMzU5YjJhMjFhODljODY1ZGIzMzAyZTkzMTZkYTM5NjA0YTA2ZDYwYWQzOGYifV0="
token = (
"W3siaWQiOiAiMWNDTklBWjJYL3cxIiwgImFtb3VudCI6IDIsICJzZWNyZXQiOiAiRnVsc2dzMktQV1FMcUlLX200SzgwQSIsICJDIjogIjAzNTc4OThlYzlhMjIxN2VhYWIx"
"ZDc3YmM1Mzc2OTUwMjJlMjU2YTljMmMwNjc0ZDJlM2FiM2JiNGI0ZDMzMWZiMSJ9LCB7ImlkIjogIjFjQ05JQVoyWC93MSIsICJhbW91bnQiOiA4LCAic2VjcmV0IjogInJlRDBD"
"azVNS2xBTUQ0dWk2OEtfbEEiLCAiQyI6ICIwMjNkODNkNDE0MDU0NWQ1NTg4NjUyMzU5YjJhMjFhODljODY1ZGIzMzAyZTkzMTZkYTM5NjA0YTA2ZDYwYWQzOGYifV0="
)
result = runner.invoke(
cli,
[*cli_prefix, "receive", token],

View File

@@ -10,25 +10,46 @@ def test_get_output_split():
def test_tokenv3_get_amount():
token_str = "cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIkplaFpMVTZuQ3BSZCIsICJhbW91bnQiOiAyLCAic2VjcmV0IjogIjBFN2lDazRkVmxSZjVQRjFnNFpWMnciLCAiQyI6ICIwM2FiNTgwYWQ5NTc3OGVkNTI5NmY4YmVlNjU1ZGJkN2Q2NDJmNWQzMmRlOGUyNDg0NzdlMGI0ZDZhYTg2M2ZjZDUifSwgeyJpZCI6ICJKZWhaTFU2bkNwUmQiLCAiYW1vdW50IjogOCwgInNlY3JldCI6ICJzNklwZXh3SGNxcXVLZDZYbW9qTDJnIiwgIkMiOiAiMDIyZDAwNGY5ZWMxNmE1OGFkOTAxNGMyNTliNmQ2MTRlZDM2ODgyOWYwMmMzODc3M2M0NzIyMWY0OTYxY2UzZjIzIn1dLCAibWludCI6ICJodHRwOi8vbG9jYWxob3N0OjMzMzgifV19"
token_str = (
"cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIkplaFpMVTZuQ3BSZCIsICJhbW91bnQiOiAyLCAic2VjcmV0IjogIjBFN2lDazRkVmxSZjVQRjFnNFpWMnci"
"LCAiQyI6ICIwM2FiNTgwYWQ5NTc3OGVkNTI5NmY4YmVlNjU1ZGJkN2Q2NDJmNWQzMmRlOGUyNDg0NzdlMGI0ZDZhYTg2M2ZjZDUifSwgeyJpZCI6ICJKZWhaTFU2bkNwUmQiLCAiYW"
"1vdW50IjogOCwgInNlY3JldCI6ICJzNklwZXh3SGNxcXVLZDZYbW9qTDJnIiwgIkMiOiAiMDIyZDAwNGY5ZWMxNmE1OGFkOTAxNGMyNTliNmQ2MTRlZDM2ODgyOWYwMmMzODc3M2M0"
"NzIyMWY0OTYxY2UzZjIzIn1dLCAibWludCI6ICJodHRwOi8vbG9jYWxob3N0OjMzMzgifV19"
)
token = TokenV3.deserialize(token_str)
assert token.get_amount() == 10
def test_tokenv3_get_proofs():
token_str = "cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIkplaFpMVTZuQ3BSZCIsICJhbW91bnQiOiAyLCAic2VjcmV0IjogIjBFN2lDazRkVmxSZjVQRjFnNFpWMnciLCAiQyI6ICIwM2FiNTgwYWQ5NTc3OGVkNTI5NmY4YmVlNjU1ZGJkN2Q2NDJmNWQzMmRlOGUyNDg0NzdlMGI0ZDZhYTg2M2ZjZDUifSwgeyJpZCI6ICJKZWhaTFU2bkNwUmQiLCAiYW1vdW50IjogOCwgInNlY3JldCI6ICJzNklwZXh3SGNxcXVLZDZYbW9qTDJnIiwgIkMiOiAiMDIyZDAwNGY5ZWMxNmE1OGFkOTAxNGMyNTliNmQ2MTRlZDM2ODgyOWYwMmMzODc3M2M0NzIyMWY0OTYxY2UzZjIzIn1dLCAibWludCI6ICJodHRwOi8vbG9jYWxob3N0OjMzMzgifV19"
token_str = (
"cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIkplaFpMVTZuQ3BSZCIsICJhbW91bnQiOiAyLCAic2VjcmV0IjogIjBFN2lDazRkVmxSZjVQRjFnNFpWMnci"
"LCAiQyI6ICIwM2FiNTgwYWQ5NTc3OGVkNTI5NmY4YmVlNjU1ZGJkN2Q2NDJmNWQzMmRlOGUyNDg0NzdlMGI0ZDZhYTg2M2ZjZDUifSwgeyJpZCI6ICJKZWhaTFU2bkNwUmQiLCAiYW"
"1vdW50IjogOCwgInNlY3JldCI6ICJzNklwZXh3SGNxcXVLZDZYbW9qTDJnIiwgIkMiOiAiMDIyZDAwNGY5ZWMxNmE1OGFkOTAxNGMyNTliNmQ2MTRlZDM2ODgyOWYwMmMzODc3M2M0"
"NzIyMWY0OTYxY2UzZjIzIn1dLCAibWludCI6ICJodHRwOi8vbG9jYWxob3N0OjMzMzgifV19"
)
token = TokenV3.deserialize(token_str)
assert len(token.get_proofs()) == 2
def test_tokenv3_deserialize_serialize():
token_str = "cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIkplaFpMVTZuQ3BSZCIsICJhbW91bnQiOiAyLCAic2VjcmV0IjogIjBFN2lDazRkVmxSZjVQRjFnNFpWMnciLCAiQyI6ICIwM2FiNTgwYWQ5NTc3OGVkNTI5NmY4YmVlNjU1ZGJkN2Q2NDJmNWQzMmRlOGUyNDg0NzdlMGI0ZDZhYTg2M2ZjZDUifSwgeyJpZCI6ICJKZWhaTFU2bkNwUmQiLCAiYW1vdW50IjogOCwgInNlY3JldCI6ICJzNklwZXh3SGNxcXVLZDZYbW9qTDJnIiwgIkMiOiAiMDIyZDAwNGY5ZWMxNmE1OGFkOTAxNGMyNTliNmQ2MTRlZDM2ODgyOWYwMmMzODc3M2M0NzIyMWY0OTYxY2UzZjIzIn1dLCAibWludCI6ICJodHRwOi8vbG9jYWxob3N0OjMzMzgifV19"
token_str = (
"cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIkplaFpMVTZuQ3BSZCIsICJhbW91bnQiOiAyLCAic2VjcmV0IjogIjBFN2lDazRkVmxSZjVQRjFnNFpWMnci"
"LCAiQyI6ICIwM2FiNTgwYWQ5NTc3OGVkNTI5NmY4YmVlNjU1ZGJkN2Q2NDJmNWQzMmRlOGUyNDg0NzdlMGI0ZDZhYTg2M2ZjZDUifSwgeyJpZCI6ICJKZWhaTFU2bkNwUmQiLCAiYW"
"1vdW50IjogOCwgInNlY3JldCI6ICJzNklwZXh3SGNxcXVLZDZYbW9qTDJnIiwgIkMiOiAiMDIyZDAwNGY5ZWMxNmE1OGFkOTAxNGMyNTliNmQ2MTRlZDM2ODgyOWYwMmMzODc3M2M0"
"NzIyMWY0OTYxY2UzZjIzIn1dLCAibWludCI6ICJodHRwOi8vbG9jYWxob3N0OjMzMzgifV19"
)
token = TokenV3.deserialize(token_str)
assert token.serialize() == token_str
def test_tokenv3_deserialize_with_memo():
token_str = "cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIkplaFpMVTZuQ3BSZCIsICJhbW91bnQiOiAyLCAic2VjcmV0IjogIjBFN2lDazRkVmxSZjVQRjFnNFpWMnciLCAiQyI6ICIwM2FiNTgwYWQ5NTc3OGVkNTI5NmY4YmVlNjU1ZGJkN2Q2NDJmNWQzMmRlOGUyNDg0NzdlMGI0ZDZhYTg2M2ZjZDUifSwgeyJpZCI6ICJKZWhaTFU2bkNwUmQiLCAiYW1vdW50IjogOCwgInNlY3JldCI6ICJzNklwZXh3SGNxcXVLZDZYbW9qTDJnIiwgIkMiOiAiMDIyZDAwNGY5ZWMxNmE1OGFkOTAxNGMyNTliNmQ2MTRlZDM2ODgyOWYwMmMzODc3M2M0NzIyMWY0OTYxY2UzZjIzIn1dLCAibWludCI6ICJodHRwOi8vbG9jYWxob3N0OjMzMzgifV0sICJtZW1vIjogIlRlc3QgbWVtbyJ9"
token_str = (
"cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIkplaFpMVTZuQ3BSZCIsICJhbW91bnQiOiAyLCAic2VjcmV0IjogIjBFN2lDazRkVmxSZjV"
"QRjFnNFpWMnciLCAiQyI6ICIwM2FiNTgwYWQ5NTc3OGVkNTI5NmY4YmVlNjU1ZGJkN2Q2NDJmNWQzMmRlOGUyNDg0NzdlMGI0ZDZhYTg2M2ZjZDUifSwg"
"eyJpZCI6ICJKZWhaTFU2bkNwUmQiLCAiYW1vdW50IjogOCwgInNlY3JldCI6ICJzNklwZXh3SGNxcXVLZDZYbW9qTDJnIiwgIkMiOiAiMDIyZDAwNGY5Z"
"WMxNmE1OGFkOTAxNGMyNTliNmQ2MTRlZDM2ODgyOWYwMmMzODc3M2M0NzIyMWY0OTYxY2UzZjIzIn1dLCAibWludCI6ICJodHRwOi8vbG9jYWxob3N0Oj"
"MzMzgifV0sICJtZW1vIjogIlRlc3QgbWVtbyJ9"
)
token = TokenV3.deserialize(token_str)
assert token.serialize() == token_str
assert token.memo == "Test memo"

View File

@@ -1,5 +1,3 @@
import pytest
from cashu.core.crypto.b_dhke import hash_to_curve, step1_alice, step2_bob, step3_alice
from cashu.core.crypto.secp import PrivateKey, PublicKey

View File

@@ -5,13 +5,10 @@ import pytest
from cashu.core.base import BlindedMessage, Proof
from cashu.core.crypto.b_dhke import step1_alice
from cashu.core.helpers import calculate_number_of_blank_outputs
from cashu.core.migrations import migrate_databases
SERVER_ENDPOINT = "http://localhost:3338"
from cashu.core.settings import settings
from cashu.mint.ledger import Ledger
from tests.conftest import ledger
SERVER_ENDPOINT = "http://localhost:3338"
async def assert_err(f, msg):

View File

@@ -1,15 +1,9 @@
import asyncio
import json
import pytest
import pytest_asyncio
import requests
from cashu.core.base import CheckSpendableRequest, CheckSpendableResponse, Proof
from cashu.core.settings import settings
from tests.conftest import ledger
BASE_URL = f"http://localhost:3337"
BASE_URL = "http://localhost:3337"
@pytest.mark.asyncio

View File

@@ -1,35 +1,19 @@
import asyncio
import shutil
import time
from pathlib import Path
from typing import Dict, List, Union
import pytest
import pytest_asyncio
from mnemonic import Mnemonic
from cashu.core.base import Proof, Secret, SecretKind, Tags
from cashu.core.base import Proof
from cashu.core.crypto.secp import PrivateKey, PublicKey
from cashu.core.errors import (
CashuError,
InvoiceNotPaidError,
KeysetError,
KeysetNotFoundError,
LightningError,
NoSecretInProofsError,
NotAllowedError,
SecretTooLongError,
TokenAlreadySpentError,
TransactionError,
)
from cashu.core.helpers import async_unwrap, sum_proofs
from cashu.core.migrations import migrate_databases
from cashu.core.errors import CashuError, KeysetNotFoundError
from cashu.core.helpers import sum_proofs
from cashu.core.settings import settings
from cashu.wallet import migrations
from cashu.wallet.wallet import Wallet
from cashu.wallet.wallet import Wallet as Wallet1
from cashu.wallet.wallet import Wallet as Wallet2
from tests.conftest import SERVER_ENDPOINT, mint
from tests.conftest import SERVER_ENDPOINT
async def assert_err(f, msg: Union[str, CashuError]):
@@ -240,7 +224,7 @@ async def test_double_spend(wallet1: Wallet):
await wallet1.split(wallet1.proofs, 20)
await assert_err(
wallet1.split(doublespend, 20),
f"Mint Error: Token already spent.",
"Mint Error: Token already spent.",
)
assert wallet1.balance == 64
assert wallet1.available_balance == 64

View File

@@ -1,15 +1,11 @@
import asyncio
import pytest
import pytest_asyncio
from fastapi.testclient import TestClient
from cashu.core.migrations import migrate_databases
from cashu.core.settings import settings
from cashu.wallet import migrations
from cashu.wallet.api.app import app
from cashu.wallet.wallet import Wallet
from tests.conftest import SERVER_ENDPOINT, mint
from tests.conftest import SERVER_ENDPOINT
@pytest_asyncio.fixture(scope="function")

View File

@@ -6,16 +6,14 @@ from typing import List
import pytest
import pytest_asyncio
from cashu.core.base import Proof, Secret, SecretKind, SigFlags, Tags
from cashu.core.base import Proof, SigFlags, Tags
from cashu.core.crypto.secp import PrivateKey, PublicKey
from cashu.core.helpers import async_unwrap, sum_proofs
from cashu.core.migrations import migrate_databases
from cashu.core.settings import settings
from cashu.wallet import migrations
from cashu.wallet.wallet import Wallet
from cashu.wallet.wallet import Wallet as Wallet1
from cashu.wallet.wallet import Wallet as Wallet2
from tests.conftest import SERVER_ENDPOINT, mint
from tests.conftest import SERVER_ENDPOINT
async def assert_err(f, msg):
@@ -144,7 +142,7 @@ async def test_p2pk_locktime_with_refund_pubkey(wallet1: Wallet, wallet2: Wallet
@pytest.mark.asyncio
async def test_p2pk_locktime_with_wrong_refund_pubkey(wallet1: Wallet, wallet2: Wallet):
await wallet1.mint(64)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
await wallet2.create_p2pk_pubkey() # receiver side
# sender side
garbage_pubkey = PrivateKey().pubkey
garbage_pubkey_2 = PrivateKey().pubkey
@@ -275,7 +273,7 @@ async def test_p2pk_multisig_with_wrong_first_private_key(
wallet1: Wallet, wallet2: Wallet
):
await wallet1.mint(64)
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
wrong_pubklic_key = PrivateKey().pubkey
assert wrong_pubklic_key

View File

@@ -1,21 +1,18 @@
import asyncio
import copy
import secrets
from typing import List
import pytest
import pytest_asyncio
from cashu.core.base import Proof, Secret, SecretKind, Tags
from cashu.core.base import Proof
from cashu.core.crypto.secp import PrivateKey, PublicKey
from cashu.core.helpers import async_unwrap, sum_proofs
from cashu.core.helpers import sum_proofs
from cashu.core.migrations import migrate_databases
from cashu.core.settings import settings
from cashu.wallet import migrations
from cashu.wallet.wallet import Wallet
from cashu.wallet.wallet import Wallet as Wallet1
from cashu.wallet.wallet import Wallet as Wallet2
from tests.conftest import SERVER_ENDPOINT, mint
from tests.conftest import SERVER_ENDPOINT
async def assert_err(f, msg):