mirror of
https://github.com/aljazceru/nutshell.git
synced 2026-02-03 15:54:20 +01:00
[DEV] add ruff and remove isort and flake (#300)
* [DEV] add ruff and remove isort and flake - precommit - workflow - Makefile updated black * configure black to use default line-length * reformat to 88 chars line-length * fix ugly comments
This commit is contained in:
8
.flake8
8
.flake8
@@ -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,
|
||||
11
.github/workflows/checks.yml
vendored
11
.github/workflows/checks.yml
vendored
@@ -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
|
||||
|
||||
@@ -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 ]
|
||||
|
||||
15
Makefile
15
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
|
||||
|
||||
@@ -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)"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -36,11 +36,16 @@ def create_app(config_object="core.settings") -> FastAPI:
|
||||
class Formatter:
|
||||
def __init__(self):
|
||||
self.padding = 0
|
||||
self.minimal_fmt: str = "<green>{time:YYYY-MM-DD HH:mm:ss.SS}</green> | <level>{level}</level> | <level>{message}</level>\n"
|
||||
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"
|
||||
"<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
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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("")
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)")
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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}")
|
||||
|
||||
135
poetry.lock
generated
135
poetry.lock
generated
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user