diff --git a/.flake8 b/.flake8
deleted file mode 100644
index c64e6e9..0000000
--- a/.flake8
+++ /dev/null
@@ -1,8 +0,0 @@
-[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,
diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml
index 8ba2d5c..e001f35 100644
--- a/.github/workflows/checks.yml
+++ b/.github/workflows/checks.yml
@@ -24,9 +24,7 @@ jobs:
run: poetry install
- name: Check black
run: make black-check
- - name: Check isort
- run: make isort-check
- linting:
+ mypy:
runs-on: ubuntu-latest
strategy:
matrix:
@@ -49,5 +47,8 @@ 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
+ ruff:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: chartboost/ruff-action@v1
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 8bba7a2..22f3090 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,5 +1,4 @@
exclude: '^cashu/nostr/.*'
-
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
@@ -14,16 +13,11 @@ repos:
- id: mixed-line-ending
- id: check-case-conflict
- repo: https://github.com/psf/black
- rev: 22.6.0
+ rev: 23.7.0
hooks:
- id: black
- - repo: https://github.com/pycqa/isort
- rev: 5.12.0
+ - repo: https://github.com/astral-sh/ruff-pre-commit
+ rev: v0.0.283
hooks:
- - id: isort
- args: ['--profile', 'black']
- - repo: https://github.com/pycqa/flake8
- rev: 6.0.0
- hooks:
- - id: flake8
- entry: poetry run flake8
+ - id: ruff
+ args: [ --fix, --exit-non-zero-on-fix ]
diff --git a/Makefile b/Makefile
index 3e17cb2..fb3cbfa 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
-isort:
- poetry run isort --profile black . --skip cashu/nostr
+ruff:
+ poetry run ruff check . --fix
-isort-check:
- poetry run isort --profile black --check-only . --skip cashu/nostr
+ruff-check:
+ poetry run ruff check .
black:
poetry run black . --exclude cashu/nostr
@@ -13,12 +13,9 @@ black-check:
mypy:
poetry run mypy cashu --ignore-missing
-flake8:
- poetry run flake8 cashu
+format: black ruff
-format: isort black
-
-check: isort-check black-check flake8 mypy
+check: black-check ruff-check mypy
clean:
rm -r cashu.egg-info/ || true
diff --git a/cashu/core/base.py b/cashu/core/base.py
index 3860e62..525b4b6 100644
--- a/cashu/core/base.py
+++ b/cashu/core/base.py
@@ -22,8 +22,8 @@ class SecretKind:
class SigFlags:
- SIG_INPUTS = (
- "SIG_INPUTS" # require signatures only on the inputs (default signature flag)
+ SIG_INPUTS = ( # require signatures only on the inputs (default signature flag)
+ "SIG_INPUTS"
)
SIG_ALL = "SIG_ALL" # require signatures on inputs and outputs
@@ -159,20 +159,17 @@ class Proof(BaseModel):
Value token
"""
- id: Union[
- None, str
- ] = "" # NOTE: None for backwards compatibility for old clients that do not include the keyset id < 0.3
+ # NOTE: None for backwards compatibility for old clients that do not include the keyset id < 0.3
+ id: Union[None, str] = ""
amount: int = 0
secret: str = "" # secret or message to be blinded and signed
C: str = "" # signature on secret, unblinded by wallet
p2pksigs: Union[List[str], None] = [] # P2PK signature
p2shscript: Union[P2SHScript, None] = None # P2SH spending condition
- reserved: Union[
- None, bool
- ] = False # whether this proof is reserved for sending, used for coin management in the wallet
- send_id: Union[
- None, str
- ] = "" # unique ID of send attempt, used for grouping pending tokens in the wallet
+ # whether this proof is reserved for sending, used for coin management in the wallet
+ reserved: Union[None, bool] = False
+ # unique ID of send attempt, used for grouping pending tokens in the wallet
+ send_id: Union[None, str] = ""
time_created: Union[None, str] = ""
time_reserved: Union[None, str] = ""
derivation_path: Union[None, str] = "" # derivation path of the proof
@@ -338,9 +335,9 @@ class CheckSpendableRequest(BaseModel):
class CheckSpendableResponse(BaseModel):
spendable: List[bool]
- pending: Optional[
- List[bool]
- ] = None # TODO: Uncomment when all mints are updated to 0.12.3 and support /check
+ pending: Optional[List[bool]] = (
+ None # TODO: Uncomment when all mints are updated to 0.12.3 and support /check
+ )
# with pending tokens (kept for backwards compatibility of new wallets with old mints)
@@ -421,9 +418,11 @@ class WalletKeyset:
return cls(
id=row["id"],
- public_keys=deserialize(str(row["public_keys"]))
- if dict(row).get("public_keys")
- else {},
+ public_keys=(
+ deserialize(str(row["public_keys"]))
+ if dict(row).get("public_keys")
+ else {}
+ ),
mint_url=row["mint_url"],
valid_from=row["valid_from"],
valid_to=row["valid_to"],
@@ -489,7 +488,8 @@ class MintKeyset:
self.id = derive_keyset_id(self.public_keys) # type: ignore
if backwards_compatibility_pre_0_12:
logger.warning(
- f"WARNING: Using weak key derivation for keyset {self.id} (backwards compatibility < 0.12)"
+ f"WARNING: Using weak key derivation for keyset {self.id} (backwards"
+ " compatibility < 0.12)"
)
diff --git a/cashu/core/bolt11.py b/cashu/core/bolt11.py
index 962581d..3c59fbb 100644
--- a/cashu/core/bolt11.py
+++ b/cashu/core/bolt11.py
@@ -184,7 +184,6 @@ def lnencode(addr, privkey):
tags_set = set()
for k, v in addr.tags:
-
# BOLT #11:
#
# A writer MUST NOT include more than one `d`, `h`, `n` or `x` fields,
diff --git a/cashu/core/db.py b/cashu/core/db.py
index 0af326a..6087386 100644
--- a/cashu/core/db.py
+++ b/cashu/core/db.py
@@ -117,9 +117,9 @@ class Database(Compat):
psycopg2.extensions.new_type( # type: ignore
(1082, 1083, 1266),
"DATE2INT",
- lambda value, curs: time.mktime(value.timetuple())
- if value is not None
- else None,
+ lambda value, curs: (
+ time.mktime(value.timetuple()) if value is not None else None
+ ),
)
)
diff --git a/cashu/core/migrations.py b/cashu/core/migrations.py
index 37a697c..ce3e2bf 100644
--- a/cashu/core/migrations.py
+++ b/cashu/core/migrations.py
@@ -37,11 +37,13 @@ async def migrate_databases(db: Database, migrations_module):
exists = None
if conn.type == SQLITE:
exists = await conn.fetchone(
- f"SELECT * FROM sqlite_master WHERE type='table' AND name='{table_with_schema(db, 'dbversions')}'"
+ "SELECT * FROM sqlite_master WHERE type='table' AND"
+ f" name='{table_with_schema(db, 'dbversions')}'"
)
elif conn.type in {POSTGRES, COCKROACH}:
exists = await conn.fetchone(
- f"SELECT * FROM information_schema.tables WHERE table_name = '{table_with_schema(db, 'dbversions')}'"
+ "SELECT * FROM information_schema.tables WHERE table_name ="
+ f" '{table_with_schema(db, 'dbversions')}'"
)
if not exists:
diff --git a/cashu/core/script.py b/cashu/core/script.py
index ff471d1..0fc2a8e 100644
--- a/cashu/core/script.py
+++ b/cashu/core/script.py
@@ -134,7 +134,8 @@ if __name__ == "__main__":
txin_redeemScript_b64 = base64.urlsafe_b64encode(txin_redeemScript).decode()
txin_signature_b64 = base64.urlsafe_b64encode(txin_signature).decode()
print(
- f"Carol to Bob:\nscript: {txin_redeemScript.__repr__()}\nscript: {txin_redeemScript_b64}\nsignature: {txin_signature_b64}\n"
+ f"Carol to Bob:\nscript: {txin_redeemScript.__repr__()}\nscript:"
+ f" {txin_redeemScript_b64}\nsignature: {txin_signature_b64}\n"
)
print("")
# ---------
@@ -155,7 +156,8 @@ if __name__ == "__main__":
tx, _ = step1_bob_carol_create_tx(txin_p2sh_address)
print(
- f"Bob verifies:\nscript: {txin_redeemScript_b64}\nsignature: {txin_signature_b64}\n"
+ f"Bob verifies:\nscript: {txin_redeemScript_b64}\nsignature:"
+ f" {txin_signature_b64}\n"
)
script_valid = step3_bob_verify_script(txin_signature, txin_redeemScript, tx)
# MINT redeems tokens and stores P2SH:txin_p2sh_address
diff --git a/cashu/mint/app.py b/cashu/mint/app.py
index 3b4ef32..412cd90 100644
--- a/cashu/mint/app.py
+++ b/cashu/mint/app.py
@@ -36,11 +36,16 @@ def create_app(config_object="core.settings") -> FastAPI:
class Formatter:
def __init__(self):
self.padding = 0
- self.minimal_fmt: str = "{time:YYYY-MM-DD HH:mm:ss.SS} | {level} | {message}\n"
+ self.minimal_fmt: str = (
+ "{time:YYYY-MM-DD HH:mm:ss.SS} |"
+ " {level} | {message}\n"
+ )
if settings.debug:
self.fmt: str = (
- "{time:YYYY-MM-DD HH:mm:ss.SS} | {level: <4} | {name}:"
- "{function}:{line} | {message}\n"
+ "{time:YYYY-MM-DD HH:mm:ss.SS} | {level:"
+ " <4} |"
+ " {name}:{function}:{line}"
+ " | {message}\n"
)
else:
self.fmt: str = self.minimal_fmt
diff --git a/cashu/mint/crud.py b/cashu/mint/crud.py
index c7eaffc..d15ab22 100644
--- a/cashu/mint/crud.py
+++ b/cashu/mint/crud.py
@@ -90,11 +90,9 @@ async def get_proofs_used(
db: Database,
conn: Optional[Connection] = None,
):
- rows = await (conn or db).fetchall(
- f"""
+ rows = await (conn or db).fetchall(f"""
SELECT secret from {table_with_schema(db, 'proofs_used')}
- """
- )
+ """)
return [row[0] for row in rows]
@@ -123,11 +121,9 @@ async def get_proofs_pending(
db: Database,
conn: Optional[Connection] = None,
):
- rows = await (conn or db).fetchall(
- f"""
+ rows = await (conn or db).fetchall(f"""
SELECT * from {table_with_schema(db, 'proofs_pending')}
- """
- )
+ """)
return [Proof(**r) for r in rows]
diff --git a/cashu/mint/ledger.py b/cashu/mint/ledger.py
index 1544c11..8f972d5 100644
--- a/cashu/mint/ledger.py
+++ b/cashu/mint/ledger.py
@@ -276,9 +276,10 @@ class Ledger:
if not valid:
raise TransactionError("script invalid.")
# check if secret commits to script address
- assert secret.data == str(
- txin_p2sh_address
- ), f"secret does not contain correct P2SH address: {secret.data} is not {txin_p2sh_address}."
+ assert secret.data == str(txin_p2sh_address), (
+ f"secret does not contain correct P2SH address: {secret.data} is not"
+ f" {txin_p2sh_address}."
+ )
return True
# P2PK
@@ -310,9 +311,10 @@ class Ledger:
assert n_sigs_required > 0, "n_sigs must be positive."
# check if enough signatures are present
- assert (
- len(proof.p2pksigs) >= n_sigs_required
- ), f"not enough signatures provided: {len(proof.p2pksigs)} < {n_sigs_required}."
+ assert len(proof.p2pksigs) >= n_sigs_required, (
+ f"not enough signatures provided: {len(proof.p2pksigs)} <"
+ f" {n_sigs_required}."
+ )
n_valid_sigs_per_output = 0
# loop over all signatures in output
@@ -327,20 +329,24 @@ class Ledger:
):
n_valid_sigs_per_output += 1
logger.trace(
- f"p2pk signature on input is valid: {input_sig} on {pubkey}."
+ f"p2pk signature on input is valid: {input_sig} on"
+ f" {pubkey}."
)
continue
else:
logger.trace(
- f"p2pk signature on input is invalid: {input_sig} on {pubkey}."
+ f"p2pk signature on input is invalid: {input_sig} on"
+ f" {pubkey}."
)
# check if we have enough valid signatures
assert n_valid_sigs_per_output, "no valid signature provided for input."
- assert (
- n_valid_sigs_per_output >= n_sigs_required
- ), f"signature threshold not met. {n_valid_sigs_per_output} < {n_sigs_required}."
+ assert n_valid_sigs_per_output >= n_sigs_required, (
+ f"signature threshold not met. {n_valid_sigs_per_output} <"
+ f" {n_sigs_required}."
+ )
logger.trace(
- f"{n_valid_sigs_per_output} of {n_sigs_required} valid signatures found."
+ f"{n_valid_sigs_per_output} of {n_sigs_required} valid signatures"
+ " found."
)
logger.trace(proof.p2pksigs)
@@ -424,11 +430,13 @@ class Ledger:
):
n_valid_sigs_per_output += 1
assert n_valid_sigs_per_output, "no valid signature provided for output."
- assert (
- n_valid_sigs_per_output >= n_sigs_required
- ), f"signature threshold not met. {n_valid_sigs_per_output} < {n_sigs_required}."
+ assert n_valid_sigs_per_output >= n_sigs_required, (
+ f"signature threshold not met. {n_valid_sigs_per_output} <"
+ f" {n_sigs_required}."
+ )
logger.trace(
- f"{n_valid_sigs_per_output} of {n_sigs_required} valid signatures found."
+ f"{n_valid_sigs_per_output} of {n_sigs_required} valid signatures"
+ " found."
)
logger.trace(output.p2pksigs)
logger.trace("p2pk signatures on output is valid.")
@@ -492,7 +500,8 @@ class Ledger:
Tuple[str, str]: Bolt11 invoice and payment hash (for lookup)
"""
logger.trace(
- f"_request_lightning_invoice: Requesting Lightning invoice for {amount} satoshis."
+ "_request_lightning_invoice: Requesting Lightning invoice for"
+ f" {amount} satoshis."
)
error, balance = await self.lightning.status()
logger.trace(f"_request_lightning_invoice: Lightning wallet balance: {balance}")
@@ -549,14 +558,16 @@ class Ledger:
try:
if amount > invoice.amount:
raise LightningError(
- f"requested amount too high: {amount}. Invoice amount: {invoice.amount}"
+ f"requested amount too high: {amount}. Invoice amount:"
+ f" {invoice.amount}"
)
logger.trace(
f"_check_lightning_invoice: checking invoice {invoice.payment_hash}"
)
status = await self.lightning.get_invoice_status(invoice.payment_hash)
logger.trace(
- f"_check_lightning_invoice: invoice {invoice.payment_hash} status: {status}"
+ f"_check_lightning_invoice: invoice {invoice.payment_hash} status:"
+ f" {status}"
)
if status.paid:
return status.paid
@@ -658,7 +669,8 @@ class Ledger:
try:
for p in proofs:
logger.trace(
- f"crud: _unset_proofs_pending unsetting proof {p.secret} as pending"
+ f"crud: _unset_proofs_pending unsetting proof {p.secret} as"
+ " pending"
)
await self.crud.unset_proof_pending(proof=p, db=self.db, conn=conn)
logger.trace(
@@ -1005,7 +1017,8 @@ class Ledger:
decoded_invoice = bolt11.decode(pr)
amount = math.ceil(decoded_invoice.amount_msat / 1000)
logger.trace(
- f"check_fees: checking lightning invoice: {decoded_invoice.payment_hash}"
+ "check_fees: checking lightning invoice:"
+ f" {decoded_invoice.payment_hash}"
)
paid = await self.lightning.get_invoice_status(decoded_invoice.payment_hash)
logger.trace(f"check_fees: paid: {paid}")
@@ -1071,7 +1084,8 @@ class Ledger:
# BEGIN backwards compatibility < 0.13.0
if amount is not None:
logger.debug(
- "Split: Client provided `amount` - backwards compatibility response pre 0.13.0"
+ "Split: Client provided `amount` - backwards compatibility response pre"
+ " 0.13.0"
)
# split outputs according to amount
total = sum_proofs(proofs)
diff --git a/cashu/mint/migrations.py b/cashu/mint/migrations.py
index 0ad57cd..44779e6 100644
--- a/cashu/mint/migrations.py
+++ b/cashu/mint/migrations.py
@@ -2,19 +2,16 @@ from ..core.db import Database, table_with_schema
async def m000_create_migrations_table(db: Database):
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'dbversions')} (
db TEXT PRIMARY KEY,
version INT NOT NULL
)
- """
- )
+ """)
async def m001_initial(db: Database):
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'promises')} (
amount {db.big_int} NOT NULL,
B_b TEXT NOT NULL,
@@ -23,11 +20,9 @@ async def m001_initial(db: Database):
UNIQUE (B_b)
);
- """
- )
+ """)
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'proofs_used')} (
amount {db.big_int} NOT NULL,
C TEXT NOT NULL,
@@ -36,11 +31,9 @@ async def m001_initial(db: Database):
UNIQUE (secret)
);
- """
- )
+ """)
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'invoices')} (
amount {db.big_int} NOT NULL,
pr TEXT NOT NULL,
@@ -50,49 +43,41 @@ async def m001_initial(db: Database):
UNIQUE (hash)
);
- """
- )
+ """)
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE VIEW {table_with_schema(db, 'balance_issued')} AS
SELECT COALESCE(SUM(s), 0) AS balance FROM (
SELECT SUM(amount)
FROM {table_with_schema(db, 'promises')}
WHERE amount > 0
) AS s;
- """
- )
+ """)
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE VIEW {table_with_schema(db, 'balance_redeemed')} AS
SELECT COALESCE(SUM(s), 0) AS balance FROM (
SELECT SUM(amount)
FROM {table_with_schema(db, 'proofs_used')}
WHERE amount > 0
) AS s;
- """
- )
+ """)
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE VIEW {table_with_schema(db, 'balance')} AS
SELECT s_issued - s_used FROM (
SELECT bi.balance AS s_issued, bu.balance AS s_used
FROM {table_with_schema(db, 'balance_issued')} bi
CROSS JOIN {table_with_schema(db, 'balance_redeemed')} bu
) AS balance;
- """
- )
+ """)
async def m003_mint_keysets(db: Database):
"""
Stores mint keysets from different mints and epochs.
"""
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'keysets')} (
id TEXT NOT NULL,
derivation_path TEXT,
@@ -104,10 +89,8 @@ async def m003_mint_keysets(db: Database):
UNIQUE (derivation_path)
);
- """
- )
- await db.execute(
- f"""
+ """)
+ await db.execute(f"""
CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'mint_pubkeys')} (
id TEXT NOT NULL,
amount INTEGER NOT NULL,
@@ -116,8 +99,7 @@ async def m003_mint_keysets(db: Database):
UNIQUE (id, pubkey)
);
- """
- )
+ """)
async def m004_keysets_add_version(db: Database):
@@ -133,8 +115,7 @@ async def m005_pending_proofs_table(db: Database) -> None:
"""
Store pending proofs.
"""
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'proofs_pending')} (
amount INTEGER NOT NULL,
C TEXT NOT NULL,
@@ -143,8 +124,7 @@ async def m005_pending_proofs_table(db: Database) -> None:
UNIQUE (secret)
);
- """
- )
+ """)
async def m006_invoices_add_payment_hash(db: Database):
diff --git a/cashu/mint/router.py b/cashu/mint/router.py
index 2fbb833..3ede2c6 100644
--- a/cashu/mint/router.py
+++ b/cashu/mint/router.py
@@ -59,7 +59,10 @@ async def info() -> GetInfoResponse:
"/keys",
name="Mint public keys",
summary="Get the public keys of the newest mint keyset",
- response_description="A dictionary of all supported token values of the mint and their associated public key of the current keyset.",
+ response_description=(
+ "A dictionary of all supported token values of the mint and their associated"
+ " public key of the current keyset."
+ ),
response_model=KeysResponse,
)
async def keys():
@@ -74,7 +77,10 @@ async def keys():
"/keys/{idBase64Urlsafe}",
name="Keyset public keys",
summary="Public keys of a specific keyset",
- response_description="A dictionary of all supported token values of the mint and their associated public key for a specific keyset.",
+ response_description=(
+ "A dictionary of all supported token values of the mint and their associated"
+ " public key for a specific keyset."
+ ),
response_model=KeysResponse,
)
async def keyset_keys(idBase64Urlsafe: str):
@@ -109,7 +115,10 @@ async def keysets() -> KeysetsResponse:
name="Request mint",
summary="Request minting of new tokens",
response_model=GetMintResponse,
- response_description="A Lightning invoice to be paid and a hash to request minting of new tokens after payment.",
+ response_description=(
+ "A Lightning invoice to be paid and a hash to request minting of new tokens"
+ " after payment."
+ ),
)
async def request_mint(amount: int = 0) -> GetMintResponse:
"""
@@ -135,7 +144,9 @@ async def request_mint(amount: int = 0) -> GetMintResponse:
name="Mint tokens",
summary="Mint tokens in exchange for a Bitcoin paymemt that the user has made",
response_model=PostMintResponse,
- response_description="A list of blinded signatures that can be used to create proofs.",
+ response_description=(
+ "A list of blinded signatures that can be used to create proofs."
+ ),
)
async def mint(
payload: PostMintRequest,
@@ -163,9 +174,15 @@ async def mint(
@router.post(
"/melt",
name="Melt tokens",
- summary="Melt tokens for a Bitcoin payment that the mint will make for the user in exchange",
+ summary=(
+ "Melt tokens for a Bitcoin payment that the mint will make for the user in"
+ " exchange"
+ ),
response_model=GetMeltResponse,
- response_description="The state of the payment, a preimage as proof of payment, and a list of promises for change.",
+ response_description=(
+ "The state of the payment, a preimage as proof of payment, and a list of"
+ " promises for change."
+ ),
)
async def melt(payload: PostMeltRequest) -> GetMeltResponse:
"""
@@ -225,7 +242,9 @@ async def check_fees(payload: CheckFeesRequest) -> CheckFeesResponse:
name="Split",
summary="Split proofs at a specified amount",
response_model=Union[PostSplitResponse, PostSplitResponse_Deprecated],
- response_description="A list of blinded signatures that can be used to create proofs.",
+ response_description=(
+ "A list of blinded signatures that can be used to create proofs."
+ ),
)
async def split(
payload: PostSplitRequest,
@@ -259,8 +278,9 @@ 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])} "
- f"sat and send: {len(scnd_promises)}: {sum([p.amount for p in scnd_promises])} sat"
+ f"Split into keep: {len(frst_promises)}:"
+ f" {sum([p.amount for p in frst_promises])} sat and send:"
+ f" {len(scnd_promises)}: {sum([p.amount for p in scnd_promises])} sat"
)
return PostSplitResponse_Deprecated(fst=frst_promises, snd=scnd_promises)
# END backwards compatibility < 0.13
diff --git a/cashu/mint/startup.py b/cashu/mint/startup.py
index f4c8de7..735f59e 100644
--- a/cashu/mint/startup.py
+++ b/cashu/mint/startup.py
@@ -53,7 +53,8 @@ async def start_mint_init():
error_message, balance = await ledger.lightning.status()
if error_message:
logger.warning(
- f"The backend for {ledger.lightning.__class__.__name__} isn't working properly: '{error_message}'",
+ f"The backend for {ledger.lightning.__class__.__name__} isn't working"
+ f" properly: '{error_message}'",
RuntimeWarning,
)
logger.info(f"Lightning balance: {balance} msat")
diff --git a/cashu/wallet/api/router.py b/cashu/wallet/api/router.py
index 7ad7e9d..3a671b6 100644
--- a/cashu/wallet/api/router.py
+++ b/cashu/wallet/api/router.py
@@ -276,8 +276,9 @@ async def burn(
wallet = await mint_wallet(mint)
if not (all or token or force or delete) or (token and all):
raise Exception(
- "enter a token or use --all to burn all pending tokens, --force to check all tokens"
- "or --delete with send ID to force-delete pending token from list if mint is unavailable.",
+ "enter a token or use --all to burn all pending tokens, --force to check"
+ " all tokensor --delete with send ID to force-delete pending token from"
+ " list if mint is unavailable.",
)
if all:
# check only those who are flagged as reserved
diff --git a/cashu/wallet/cli/cli.py b/cashu/wallet/cli/cli.py
index c3e6b37..9acf2b2 100644
--- a/cashu/wallet/cli/cli.py
+++ b/cashu/wallet/cli/cli.py
@@ -90,18 +90,27 @@ def coro(f):
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."
+ "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}"
env_path = settings.env_file
else:
- error_str += f"Ceate a new Cashu config file here: {os.path.join(settings.cashu_dir, '.env')}"
+ error_str += (
+ "Ceate a new Cashu config file here:"
+ f" {os.path.join(settings.cashu_dir, '.env')}"
+ )
env_path = os.path.join(settings.cashu_dir, ".env")
- error_str += f'\n\nYou can turn off Tor with this command: echo "TOR=FALSE" >> {env_path}'
+ error_str += (
+ '\n\nYou can turn off Tor with this command: echo "TOR=FALSE" >>'
+ f" {env_path}"
+ )
raise Exception(error_str)
ctx.ensure_object(dict)
@@ -155,7 +164,8 @@ async def pay(ctx: Context, invoice: str, yes: bool):
total_amount, fee_reserve_sat = await wallet.get_pay_amount_with_fees(invoice)
if not yes:
click.confirm(
- f"Pay {total_amount - fee_reserve_sat} sat ({total_amount} sat with potential fees)?",
+ f"Pay {total_amount - fee_reserve_sat} sat ({total_amount} sat with"
+ " potential fees)?",
abort=True,
default=True,
)
@@ -206,7 +216,8 @@ async def invoice(ctx: Context, amount: int, hash: str, split: int):
print(f"Invoice: {invoice.pr}")
print("")
print(
- f"If you abort this you can use this command to recheck the invoice:\ncashu invoice {amount} --hash {invoice.hash}"
+ "If you abort this you can use this command to recheck the"
+ f" invoice:\ncashu invoice {amount} --hash {invoice.hash}"
)
check_until = time.time() + 5 * 60 # check for five minutes
print("")
@@ -232,7 +243,8 @@ async def invoice(ctx: Context, amount: int, hash: str, split: int):
if not paid:
print("\n")
print(
- "Invoice is not paid yet, stopping check. Use the command above to recheck after the invoice has been paid."
+ "Invoice is not paid yet, stopping check. Use the command above to"
+ " recheck after the invoice has been paid."
)
# user paid invoice and want to check it
@@ -306,7 +318,8 @@ async def balance(ctx: Context, verbose):
print("")
for k, v in keyset_balances.items():
print(
- f"Keyset: {k} - Balance: {v['available']} sat (pending: {v['balance']-v['available']} sat)"
+ f"Keyset: {k} - Balance: {v['available']} sat (pending:"
+ f" {v['balance']-v['available']} sat)"
)
print("")
@@ -314,8 +327,9 @@ async def balance(ctx: Context, verbose):
if verbose:
print(
- 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"
+ f"Balance: {wallet.available_balance} sat (pending:"
+ f" {wallet.balance-wallet.available_balance} sat) in"
+ f" {len([p for p in wallet.proofs if not p.reserved])} tokens"
)
else:
print(f"Balance: {wallet.available_balance} sat")
@@ -386,7 +400,7 @@ async def send_command(
"-n",
default=False,
is_flag=True,
- help="Receive tokens via nostr." "receive",
+ help="Receive tokens via nostr.receive",
)
@click.option(
"--all", "-a", default=False, is_flag=True, help="Receive all pending tokens."
@@ -454,8 +468,9 @@ async def burn(ctx: Context, token: str, all: bool, force: bool, delete: str):
await wallet.load_mint()
if not (all or token or force or delete) or (token and all):
print(
- "Error: enter a token or use --all to burn all pending tokens, --force to check all tokens "
- "or --delete with send ID to force-delete pending token from list if mint is unavailable."
+ "Error: enter a token or use --all to burn all pending tokens, --force to"
+ " check all tokens or --delete with send ID to force-delete pending token"
+ " from list if mint is unavailable."
)
return
if all:
@@ -527,7 +542,8 @@ async def pending(ctx: Context, legacy, number: int, offset: int):
int(grouped_proofs[0].time_reserved)
).strftime("%Y-%m-%d %H:%M:%S")
print(
- f"#{i} Amount: {sum_proofs(grouped_proofs)} sat Time: {reserved_date} ID: {key} Mint: {mint}\n"
+ f"#{i} Amount: {sum_proofs(grouped_proofs)} sat Time:"
+ f" {reserved_date} ID: {key} Mint: {mint}\n"
)
print(f"{token}\n")
@@ -657,7 +673,8 @@ async def wallets(ctx):
if w == ctx.obj["WALLET_NAME"]:
active_wallet = True
print(
- f"Wallet: {w}\tBalance: {sum_proofs(wallet.proofs)} sat (available: "
+ 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 Exception:
@@ -741,12 +758,14 @@ async def restore(ctx: Context, to: int, batch: int):
ret = await get_seed_and_mnemonic(wallet.db)
if ret:
print(
- "Wallet already has a mnemonic. You can't restore an already initialized wallet."
+ "Wallet already has a mnemonic. You can't restore an already initialized"
+ " wallet."
)
print("To restore a wallet, please delete the wallet directory and try again.")
print("")
print(
- f"The wallet directory is: {os.path.join(settings.cashu_dir, ctx.obj['WALLET_NAME'])}"
+ "The wallet directory is:"
+ f" {os.path.join(settings.cashu_dir, ctx.obj['WALLET_NAME'])}"
)
return
# ask the user for a mnemonic but allow also no input
diff --git a/cashu/wallet/cli/cli_helpers.py b/cashu/wallet/cli/cli_helpers.py
index 068d244..e7d12b2 100644
--- a/cashu/wallet/cli/cli_helpers.py
+++ b/cashu/wallet/cli/cli_helpers.py
@@ -78,7 +78,8 @@ async def print_mint_balances(wallet, show_mints=False):
print("")
for i, (k, v) in enumerate(mint_balances.items()):
print(
- f"Mint {i+1}: Balance: {v['available']} sat (pending: {v['balance']-v['available']} sat) URL: {k}"
+ f"Mint {i+1}: Balance: {v['available']} sat (pending:"
+ f" {v['balance']-v['available']} sat) URL: {k}"
)
print("")
diff --git a/cashu/wallet/crud.py b/cashu/wallet/crud.py
index 887db75..e229ccf 100644
--- a/cashu/wallet/crud.py
+++ b/cashu/wallet/crud.py
@@ -31,11 +31,9 @@ async def get_proofs(
db: Database,
conn: Optional[Connection] = None,
):
- rows = await (conn or db).fetchall(
- """
+ rows = await (conn or db).fetchall("""
SELECT * from proofs
- """
- )
+ """)
return [Proof(**dict(r)) for r in rows]
@@ -43,12 +41,10 @@ async def get_reserved_proofs(
db: Database,
conn: Optional[Connection] = None,
):
- rows = await (conn or db).fetchall(
- """
+ rows = await (conn or db).fetchall("""
SELECT * from proofs
WHERE reserved
- """
- )
+ """)
return [Proof(**r) for r in rows]
diff --git a/cashu/wallet/helpers.py b/cashu/wallet/helpers.py
index ac71118..302298d 100644
--- a/cashu/wallet/helpers.py
+++ b/cashu/wallet/helpers.py
@@ -195,7 +195,8 @@ async def send(
send_proofs = [p]
break
assert send_proofs, Exception(
- f"No proof with this amount found. Available amounts: {set([p.amount for p in wallet.proofs])}"
+ "No proof with this amount found. Available amounts:"
+ f" {set([p.amount for p in wallet.proofs])}"
)
await wallet.set_reserved(send_proofs, reserved=True)
diff --git a/cashu/wallet/migrations.py b/cashu/wallet/migrations.py
index 810def7..061b31c 100644
--- a/cashu/wallet/migrations.py
+++ b/cashu/wallet/migrations.py
@@ -2,19 +2,16 @@ from ..core.db import Database
async def m000_create_migrations_table(db: Database):
- await db.execute(
- """
+ await db.execute("""
CREATE TABLE IF NOT EXISTS dbversions (
db TEXT PRIMARY KEY,
version INT NOT NULL
)
- """
- )
+ """)
async def m001_initial(db: Database):
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE TABLE IF NOT EXISTS proofs (
amount {db.big_int} NOT NULL,
C TEXT NOT NULL,
@@ -23,11 +20,9 @@ async def m001_initial(db: Database):
UNIQUE (secret)
);
- """
- )
+ """)
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE TABLE IF NOT EXISTS proofs_used (
amount {db.big_int} NOT NULL,
C TEXT NOT NULL,
@@ -36,30 +31,25 @@ async def m001_initial(db: Database):
UNIQUE (secret)
);
- """
- )
+ """)
- await db.execute(
- """
+ await db.execute("""
CREATE VIEW IF NOT EXISTS balance AS
SELECT COALESCE(SUM(s), 0) AS balance FROM (
SELECT SUM(amount) AS s
FROM proofs
WHERE amount > 0
);
- """
- )
+ """)
- await db.execute(
- """
+ await db.execute("""
CREATE VIEW IF NOT EXISTS balance_used AS
SELECT COALESCE(SUM(s), 0) AS used FROM (
SELECT SUM(amount) AS s
FROM proofs_used
WHERE amount > 0
);
- """
- )
+ """)
async def m002_add_proofs_reserved(db: Database):
@@ -85,8 +75,7 @@ async def m004_p2sh_locks(db: Database):
"""
Stores P2SH addresses and unlock scripts.
"""
- await db.execute(
- """
+ await db.execute("""
CREATE TABLE IF NOT EXISTS p2sh (
address TEXT NOT NULL,
script TEXT NOT NULL,
@@ -96,16 +85,14 @@ async def m004_p2sh_locks(db: Database):
UNIQUE (address, script, signature)
);
- """
- )
+ """)
async def m005_wallet_keysets(db: Database):
"""
Stores mint keysets from different mints and epochs.
"""
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE TABLE IF NOT EXISTS keysets (
id TEXT,
mint_url TEXT,
@@ -117,8 +104,7 @@ async def m005_wallet_keysets(db: Database):
UNIQUE (id, mint_url)
);
- """
- )
+ """)
await db.execute("ALTER TABLE proofs ADD COLUMN id TEXT")
await db.execute("ALTER TABLE proofs_used ADD COLUMN id TEXT")
@@ -128,8 +114,7 @@ async def m006_invoices(db: Database):
"""
Stores Lightning invoices.
"""
- await db.execute(
- f"""
+ await db.execute(f"""
CREATE TABLE IF NOT EXISTS invoices (
amount INTEGER NOT NULL,
pr TEXT NOT NULL,
@@ -142,22 +127,19 @@ async def m006_invoices(db: Database):
UNIQUE (hash)
);
- """
- )
+ """)
async def m007_nostr(db: Database):
"""
Stores timestamps of nostr operations.
"""
- await db.execute(
- """
+ await db.execute("""
CREATE TABLE IF NOT EXISTS nostr (
type TEXT NOT NULL,
last TIMESTAMP DEFAULT NULL
)
- """
- )
+ """)
await db.execute(
"""
INSERT INTO nostr
@@ -182,14 +164,12 @@ async def m009_privatekey_and_determinstic_key_derivation(db: Database):
await db.execute("ALTER TABLE keysets ADD COLUMN counter INTEGER DEFAULT 0")
await db.execute("ALTER TABLE proofs ADD COLUMN derivation_path TEXT")
await db.execute("ALTER TABLE proofs_used ADD COLUMN derivation_path TEXT")
- await db.execute(
- """
+ await db.execute("""
CREATE TABLE IF NOT EXISTS seed (
seed TEXT NOT NULL,
mnemonic TEXT NOT NULL,
UNIQUE (seed, mnemonic)
);
- """
- )
+ """)
# await db.execute("INSERT INTO secret_derivation (counter) VALUES (0)")
diff --git a/cashu/wallet/nostr.py b/cashu/wallet/nostr.py
index 1ea1918..3f508b7 100644
--- a/cashu/wallet/nostr.py
+++ b/cashu/wallet/nostr.py
@@ -99,8 +99,9 @@ async def receive_nostr(
):
if settings.nostr_private_key is None:
print(
- "Warning: No nostr private key set! You don't have NOSTR_PRIVATE_KEY set in your .env file. "
- "I will create a random private key for this session but I will not remember it."
+ "Warning: No nostr private key set! You don't have NOSTR_PRIVATE_KEY set in"
+ " your .env file. I will create a random private key for this session but I"
+ " will not remember it."
)
print("")
client = NostrClient(
diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py
index 61cd606..8926ffa 100644
--- a/cashu/wallet/wallet.py
+++ b/cashu/wallet/wallet.py
@@ -702,7 +702,8 @@ class Wallet(LedgerAPI):
else ""
)
print(
- f'Generated a new mnemonic{wallet_name}. To view it, run "cashu{wallet_command_prefix_str} info --mnemonic".'
+ f"Generated a new mnemonic{wallet_name}. To view it, run"
+ f' "cashu{wallet_command_prefix_str} info --mnemonic".'
)
elif from_mnemonic:
# or use the one provided
@@ -1425,7 +1426,8 @@ class Wallet(LedgerAPI):
if invalidated_proofs:
logger.debug(
- f"Invalidating {len(invalidated_proofs)} proofs worth {sum_proofs(invalidated_proofs)} sat."
+ f"Invalidating {len(invalidated_proofs)} proofs worth"
+ f" {sum_proofs(invalidated_proofs)} sat."
)
async with self.db.connect() as conn:
@@ -1559,7 +1561,8 @@ class Wallet(LedgerAPI):
private_key = self.private_key
assert private_key.pubkey
logger.trace(
- f"Signing with private key: {private_key.serialize()} public key: {private_key.pubkey.serialize().hex()}"
+ f"Signing with private key: {private_key.serialize()} public key:"
+ f" {private_key.pubkey.serialize().hex()}"
)
for proof in proofs:
logger.trace(f"Signing proof: {proof}")
diff --git a/poetry.lock b/poetry.lock
index ccdf37d..4a3bc9e 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -104,31 +104,42 @@ files = [
[[package]]
name = "black"
-version = "22.12.0"
+version = "23.7.0"
description = "The uncompromising code formatter."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"},
- {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"},
- {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"},
- {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"},
- {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"},
- {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"},
- {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"},
- {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"},
- {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"},
- {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"},
- {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"},
- {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"},
+ {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"},
+ {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"},
+ {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"},
+ {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"},
+ {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"},
+ {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"},
+ {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"},
+ {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"},
+ {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"},
+ {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"},
+ {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"},
+ {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"},
+ {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"},
+ {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"},
+ {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"},
+ {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"},
+ {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"},
+ {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"},
+ {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"},
+ {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"},
+ {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"},
+ {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"},
]
[package.dependencies]
click = ">=8.0.0"
mypy-extensions = ">=0.4.3"
+packaging = ">=22.0"
pathspec = ">=0.9.0"
platformdirs = ">=2"
-tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""}
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
[package.extras]
@@ -614,22 +625,6 @@ files = [
docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"]
-[[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"
@@ -740,23 +735,6 @@ files = [
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
-[[package]]
-name = "isort"
-version = "5.12.0"
-description = "A Python utility / library to sort Python imports."
-optional = false
-python-versions = ">=3.8.0"
-files = [
- {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)"]
-pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"]
-plugins = ["setuptools"]
-requirements-deprecated-finder = ["pip-api", "pipreqs"]
-
[[package]]
name = "loguru"
version = "0.6.0"
@@ -795,17 +773,6 @@ docs = ["alabaster (==0.7.13)", "autodocsumm (==0.2.11)", "sphinx (==7.0.1)", "s
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"
@@ -1039,17 +1006,6 @@ 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"
@@ -1154,17 +1110,6 @@ 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"
@@ -1363,6 +1308,32 @@ idna = {version = "*", optional = true, markers = "extra == \"idna2008\""}
[package.extras]
idna2008 = ["idna"]
+[[package]]
+name = "ruff"
+version = "0.0.284"
+description = "An extremely fast Python linter, written in Rust."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ruff-0.0.284-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:8b949084941232e2c27f8d12c78c5a6a010927d712ecff17231ee1a8371c205b"},
+ {file = "ruff-0.0.284-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:a3930d66b35e4dc96197422381dff2a4e965e9278b5533e71ae8474ef202fab0"},
+ {file = "ruff-0.0.284-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d1f7096038961d8bc3b956ee69d73826843eb5b39a5fa4ee717ed473ed69c95"},
+ {file = "ruff-0.0.284-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bcaf85907fc905d838f46490ee15f04031927bbea44c478394b0bfdeadc27362"},
+ {file = "ruff-0.0.284-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3660b85a9d84162a055f1add334623ae2d8022a84dcd605d61c30a57b436c32"},
+ {file = "ruff-0.0.284-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0a3218458b140ea794da72b20ea09cbe13c4c1cdb7ac35e797370354628f4c05"},
+ {file = "ruff-0.0.284-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2fe880cff13fffd735387efbcad54ba0ff1272bceea07f86852a33ca71276f4"},
+ {file = "ruff-0.0.284-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1d098ea74d0ce31478765d1f8b4fbdbba2efc532397b5c5e8e5ea0c13d7e5ae"},
+ {file = "ruff-0.0.284-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4c79ae3308e308b94635cd57a369d1e6f146d85019da2fbc63f55da183ee29b"},
+ {file = "ruff-0.0.284-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f86b2b1e7033c00de45cc176cf26778650fb8804073a0495aca2f674797becbb"},
+ {file = "ruff-0.0.284-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e37e086f4d623c05cd45a6fe5006e77a2b37d57773aad96b7802a6b8ecf9c910"},
+ {file = "ruff-0.0.284-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d29dfbe314e1131aa53df213fdfea7ee874dd96ea0dd1471093d93b59498384d"},
+ {file = "ruff-0.0.284-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:88295fd649d0aa1f1271441df75bf06266a199497afd239fd392abcfd75acd7e"},
+ {file = "ruff-0.0.284-py3-none-win32.whl", hash = "sha256:735cd62fccc577032a367c31f6a9de7c1eb4c01fa9a2e60775067f44f3fc3091"},
+ {file = "ruff-0.0.284-py3-none-win_amd64.whl", hash = "sha256:f67ed868d79fbcc61ad0fa034fe6eed2e8d438d32abce9c04b7c4c1464b2cf8e"},
+ {file = "ruff-0.0.284-py3-none-win_arm64.whl", hash = "sha256:1292cfc764eeec3cde35b3a31eae3f661d86418b5e220f5d5dba1c27a6eccbb6"},
+ {file = "ruff-0.0.284.tar.gz", hash = "sha256:ebd3cc55cd499d326aac17a331deaea29bea206e01c08862f9b5c6e93d77a491"},
+]
+
[[package]]
name = "secp256k1"
version = "0.14.0"
@@ -1672,4 +1643,4 @@ pgsql = ["psycopg2-binary"]
[metadata]
lock-version = "2.0"
python-versions = "^3.8.1"
-content-hash = "7bc36d84b841a4799da7a9f631d90195a569d3bf38dd5b4a7ed47a5901940d88"
+content-hash = "83e8f09ebad4bca75c90591fbe0c50d0acf9d19edf6e30437e91fded95cd88c4"
diff --git a/pyproject.toml b/pyproject.toml
index ee79539..e3a5847 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -39,13 +39,12 @@ pgsql = ["psycopg2-binary"]
[tool.poetry.group.dev.dependencies]
mypy = "^0.971"
-black = {version = "^22.8.0", allow-prereleases = true}
-isort = "^5.10.1"
pytest-asyncio = "^0.19.0"
pytest-cov = "^4.0.0"
pytest = "^7.4.0"
-flake8 = "^6.0.0"
pre-commit = "^3.3.3"
+ruff = "^0.0.284"
+black = "^23.7.0"
[build-system]
requires = ["poetry-core>=1.0.0"]
@@ -55,3 +54,62 @@ build-backend = "poetry.core.masonry.api"
mint = "cashu.mint.main:main"
cashu = "cashu.wallet.cli.cli:cli"
wallet-test = "tests.test_wallet:test"
+
+
+[tool.black]
+line-length = 88
+
+# previously experimental-string-processing = true
+# this should autoformat string properly but does not work
+preview = true
+
+
+[tool.ruff]
+# Same as Black. but black has a 10% overflow rule
+line-length = 150
+
+# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
+# (`I`) means isorting
+select = ["E", "F", "I"]
+ignore = []
+
+# Allow autofix for all enabled rules (when `--fix`) is provided.
+fixable = ["ALL"]
+unfixable = []
+
+# Exclude a variety of commonly ignored directories.
+exclude = [
+ "cashu/nostr",
+ "cashu/core/bolt11.py",
+ ".bzr",
+ ".direnv",
+ ".eggs",
+ ".git",
+ ".git-rewrite",
+ ".hg",
+ ".mypy_cache",
+ ".nox",
+ ".pants.d",
+ ".pytype",
+ ".ruff_cache",
+ ".svn",
+ ".tox",
+ ".venv",
+ "__pypackages__",
+ "_build",
+ "buck-out",
+ "build",
+ "dist",
+ "node_modules",
+ "venv",
+]
+
+# Allow unused variables when underscore-prefixed.
+dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
+
+# Assume Python 3.8
+# target-version = "py38"
+
+[tool.ruff.mccabe]
+# Unlike Flake8, default to a complexity level of 10.
+max-complexity = 10
diff --git a/tests/test_wallet.py b/tests/test_wallet.py
index dc2d850..c33eee1 100644
--- a/tests/test_wallet.py
+++ b/tests/test_wallet.py
@@ -94,7 +94,7 @@ async def test_get_keys(wallet1: Wallet):
assert len(wallet1.keys.public_keys) == settings.max_order
keyset = await wallet1._get_keys(wallet1.url)
assert keyset.id is not None
- assert type(keyset.id) == str
+ assert isinstance(keyset.id, str)
assert len(keyset.id) > 0
@@ -244,9 +244,7 @@ async def test_duplicate_proofs_double_spent(wallet1: Wallet):
@pytest.mark.asyncio
async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet):
await wallet1.mint(64)
- _, spendable_proofs = await wallet1.split_to_send( # type: ignore
- wallet1.proofs, 32, set_reserved=True
- )
+ _, spendable_proofs = await wallet1.split_to_send(wallet1.proofs, 32, set_reserved=True) # type: ignore
await wallet2.redeem(spendable_proofs)
assert wallet2.balance == 32
@@ -325,7 +323,8 @@ async def test_token_state(wallet1: Wallet):
@pytest.mark.asyncio
async def test_bump_secret_derivation(wallet3: Wallet):
await wallet3._init_private_key(
- "half depart obvious quality work element tank gorilla view sugar picture humble"
+ "half depart obvious quality work element tank gorilla view sugar picture"
+ " humble"
)
secrets1, rs1, derivaion_paths1 = await wallet3.generate_n_secrets(5)
secrets2, rs2, derivaion_paths2 = await wallet3.generate_secrets_from_to(0, 4)
@@ -351,7 +350,8 @@ async def test_bump_secret_derivation(wallet3: Wallet):
@pytest.mark.asyncio
async def test_bump_secret_derivation_two_steps(wallet3: Wallet):
await wallet3._init_private_key(
- "half depart obvious quality work element tank gorilla view sugar picture humble"
+ "half depart obvious quality work element tank gorilla view sugar picture"
+ " humble"
)
secrets1_1, rs1_1, derivaion_paths1 = await wallet3.generate_n_secrets(2)
secrets1_2, rs1_2, derivaion_paths2 = await wallet3.generate_n_secrets(3)
@@ -365,7 +365,8 @@ async def test_bump_secret_derivation_two_steps(wallet3: Wallet):
@pytest.mark.asyncio
async def test_generate_secrets_from_to(wallet3: Wallet):
await wallet3._init_private_key(
- "half depart obvious quality work element tank gorilla view sugar picture humble"
+ "half depart obvious quality work element tank gorilla view sugar picture"
+ " humble"
)
secrets1, rs1, derivaion_paths1 = await wallet3.generate_secrets_from_to(0, 4)
assert len(secrets1) == 5
@@ -392,7 +393,8 @@ async def test_restore_wallet_after_mint(wallet3: Wallet):
async def test_restore_wallet_with_invalid_mnemonic(wallet3: Wallet):
await assert_err(
wallet3._init_private_key(
- "half depart obvious quality work element tank gorilla view sugar picture picture"
+ "half depart obvious quality work element tank gorilla view sugar picture"
+ " picture"
),
"Invalid mnemonic",
)
@@ -401,16 +403,15 @@ async def test_restore_wallet_with_invalid_mnemonic(wallet3: Wallet):
@pytest.mark.asyncio
async def test_restore_wallet_after_split_to_send(wallet3: Wallet):
await wallet3._init_private_key(
- "half depart obvious quality work element tank gorilla view sugar picture humble"
+ "half depart obvious quality work element tank gorilla view sugar picture"
+ " humble"
)
await reset_wallet_db(wallet3)
await wallet3.mint(64)
assert wallet3.balance == 64
- _, spendable_proofs = await wallet3.split_to_send( # type: ignore
- wallet3.proofs, 32, set_reserved=True
- )
+ _, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 32, set_reserved=True) # type: ignore
await reset_wallet_db(wallet3)
await wallet3.load_proofs()
@@ -432,9 +433,7 @@ async def test_restore_wallet_after_send_and_receive(wallet3: Wallet, wallet2: W
await wallet3.mint(64)
assert wallet3.balance == 64
- _, spendable_proofs = await wallet3.split_to_send( # type: ignore
- wallet3.proofs, 32, set_reserved=True
- )
+ _, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 32, set_reserved=True) # type: ignore
await wallet2.redeem(spendable_proofs)
@@ -465,16 +464,15 @@ class ProofBox:
@pytest.mark.asyncio
async def test_restore_wallet_after_send_and_self_receive(wallet3: Wallet):
await wallet3._init_private_key(
- "lucky broken tell exhibit shuffle tomato ethics virus rabbit spread measure text"
+ "lucky broken tell exhibit shuffle tomato ethics virus rabbit spread measure"
+ " text"
)
await reset_wallet_db(wallet3)
await wallet3.mint(64)
assert wallet3.balance == 64
- _, spendable_proofs = await wallet3.split_to_send( # type: ignore
- wallet3.proofs, 32, set_reserved=True
- )
+ _, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 32, set_reserved=True) # type: ignore
await wallet3.redeem(spendable_proofs)
@@ -500,9 +498,7 @@ async def test_restore_wallet_after_send_twice(
box.add(wallet3.proofs)
assert wallet3.balance == 2
- keep_proofs, spendable_proofs = await wallet3.split_to_send( # type: ignore
- wallet3.proofs, 1, set_reserved=True
- )
+ keep_proofs, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 1, set_reserved=True) # type: ignore
box.add(wallet3.proofs)
assert wallet3.available_balance == 1
await wallet3.redeem(spendable_proofs)
@@ -522,9 +518,7 @@ async def test_restore_wallet_after_send_twice(
# again
- _, spendable_proofs = await wallet3.split_to_send( # type: ignore
- wallet3.proofs, 1, set_reserved=True
- )
+ _, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 1, set_reserved=True) # type: ignore
box.add(wallet3.proofs)
assert wallet3.available_balance == 1
@@ -557,9 +551,7 @@ async def test_restore_wallet_after_send_and_self_receive_nonquadratic_value(
box.add(wallet3.proofs)
assert wallet3.balance == 64
- keep_proofs, spendable_proofs = await wallet3.split_to_send( # type: ignore
- wallet3.proofs, 10, set_reserved=True
- )
+ keep_proofs, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 10, set_reserved=True) # type: ignore
box.add(wallet3.proofs)
assert wallet3.available_balance == 64 - 10
@@ -579,9 +571,7 @@ async def test_restore_wallet_after_send_and_self_receive_nonquadratic_value(
# again
- _, spendable_proofs = await wallet3.split_to_send( # type: ignore
- wallet3.proofs, 12, set_reserved=True
- )
+ _, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 12, set_reserved=True) # type: ignore
assert wallet3.available_balance == 64 - 12
await wallet3.redeem(spendable_proofs)