mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-23 11:44:19 +01:00
@@ -24,8 +24,8 @@ MINT_PRIVATE_KEY=supersecretprivatekey
|
|||||||
# Supported: LNbitsWallet, FakeWallet
|
# Supported: LNbitsWallet, FakeWallet
|
||||||
MINT_LIGHTNING_BACKEND=LNbitsWallet
|
MINT_LIGHTNING_BACKEND=LNbitsWallet
|
||||||
|
|
||||||
MINT_SERVER_HOST=127.0.0.1
|
MINT_LISTEN_HOST=127.0.0.1
|
||||||
MINT_SERVER_PORT=3338
|
MINT_LISTEN_PORT=3338
|
||||||
|
|
||||||
LIGHTNING=TRUE
|
LIGHTNING=TRUE
|
||||||
# fee to reserve in percent of the amount
|
# fee to reserve in percent of the amount
|
||||||
|
|||||||
4
.github/workflows/tests.yml
vendored
4
.github/workflows/tests.yml
vendored
@@ -31,8 +31,8 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
LIGHTNING: False
|
LIGHTNING: False
|
||||||
MINT_PRIVATE_KEY: "testingkey"
|
MINT_PRIVATE_KEY: "testingkey"
|
||||||
MINT_SERVER_HOST: 0.0.0.0
|
MINT_LISTEN_HOST: 0.0.0.0
|
||||||
MINT_SERVER_PORT: 3337
|
MINT_LISTEN_PORT: 3337
|
||||||
run: |
|
run: |
|
||||||
nohup poetry run mint &
|
nohup poetry run mint &
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import hashlib
|
|||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
|
||||||
from cashu.core.secp import PrivateKey, PublicKey
|
from cashu.core.secp import PrivateKey, PublicKey
|
||||||
from cashu.core.settings import MAX_ORDER
|
from cashu.core.settings import settings
|
||||||
|
|
||||||
# entropy = bytes([random.getrandbits(8) for i in range(16)])
|
# entropy = bytes([random.getrandbits(8) for i in range(16)])
|
||||||
# mnemonic = bip39.mnemonic_from_bytes(entropy)
|
# mnemonic = bip39.mnemonic_from_bytes(entropy)
|
||||||
@@ -27,12 +27,14 @@ def derive_keys(master_key: str, derivation_path: str = ""):
|
|||||||
.encode("utf-8")[:32],
|
.encode("utf-8")[:32],
|
||||||
raw=True,
|
raw=True,
|
||||||
)
|
)
|
||||||
for i in range(MAX_ORDER)
|
for i in range(settings.max_order)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def derive_pubkeys(keys: Dict[int, PrivateKey]):
|
def derive_pubkeys(keys: Dict[int, PrivateKey]):
|
||||||
return {amt: keys[amt].pubkey for amt in [2**i for i in range(MAX_ORDER)]}
|
return {
|
||||||
|
amt: keys[amt].pubkey for amt in [2**i for i in range(settings.max_order)]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def derive_keyset_id(keys: Dict[int, PublicKey]):
|
def derive_keyset_id(keys: Dict[int, PublicKey]):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from functools import partial, wraps
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from cashu.core.base import Proof
|
from cashu.core.base import Proof
|
||||||
from cashu.core.settings import LIGHTNING_FEE_PERCENT, LIGHTNING_RESERVE_FEE_MIN
|
from cashu.core.settings import settings
|
||||||
|
|
||||||
|
|
||||||
def sum_proofs(proofs: List[Proof]):
|
def sum_proofs(proofs: List[Proof]):
|
||||||
@@ -39,5 +39,6 @@ def fee_reserve(amount_msat: int, internal=False) -> int:
|
|||||||
if internal:
|
if internal:
|
||||||
return 0
|
return 0
|
||||||
return max(
|
return max(
|
||||||
int(LIGHTNING_RESERVE_FEE_MIN), int(amount_msat * LIGHTNING_FEE_PERCENT / 100.0)
|
int(settings.lightning_reserve_fee_min),
|
||||||
|
int(amount_msat * settings.lightning_fee_percent / 100.0),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,72 +1,112 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Union
|
from typing import List, Union
|
||||||
|
|
||||||
from environs import Env # type: ignore
|
from environs import Env # type: ignore
|
||||||
|
from pydantic import BaseSettings, Extra, Field, validator
|
||||||
|
|
||||||
env = Env()
|
env = Env()
|
||||||
|
|
||||||
# env file: default to current dir, else home dir
|
VERSION = "0.9.4"
|
||||||
ENV_FILE = os.path.join(os.getcwd(), ".env")
|
|
||||||
if not os.path.isfile(ENV_FILE):
|
|
||||||
|
def find_env_file():
|
||||||
|
# env file: default to current dir, else home dir
|
||||||
|
ENV_FILE = os.path.join(os.getcwd(), ".env")
|
||||||
|
if not os.path.isfile(ENV_FILE):
|
||||||
ENV_FILE = os.path.join(str(Path.home()), ".cashu", ".env")
|
ENV_FILE = os.path.join(str(Path.home()), ".cashu", ".env")
|
||||||
if os.path.isfile(ENV_FILE):
|
if os.path.isfile(ENV_FILE):
|
||||||
env.read_env(ENV_FILE)
|
env.read_env(ENV_FILE)
|
||||||
else:
|
|
||||||
ENV_FILE = ""
|
|
||||||
env.read_env(recurse=False)
|
|
||||||
|
|
||||||
DEBUG = env.bool("DEBUG", default=False)
|
|
||||||
if not DEBUG:
|
|
||||||
sys.tracebacklimit = 0
|
|
||||||
|
|
||||||
CASHU_DIR = env.str("CASHU_DIR", default=os.path.join(str(Path.home()), ".cashu"))
|
|
||||||
CASHU_DIR = CASHU_DIR.replace("~", str(Path.home()))
|
|
||||||
assert len(CASHU_DIR), "CASHU_DIR not defined"
|
|
||||||
|
|
||||||
TOR = env.bool("TOR", default=True)
|
|
||||||
|
|
||||||
SOCKS_HOST = env.str("SOCKS_HOST", default=None)
|
|
||||||
SOCKS_PORT = env.int("SOCKS_PORT", default=9050)
|
|
||||||
|
|
||||||
LIGHTNING = env.bool("LIGHTNING", default=True)
|
|
||||||
LIGHTNING_FEE_PERCENT = env.float("LIGHTNING_FEE_PERCENT", default=1.0)
|
|
||||||
assert LIGHTNING_FEE_PERCENT >= 0, "LIGHTNING_FEE_PERCENT must be at least 0"
|
|
||||||
LIGHTNING_RESERVE_FEE_MIN = env.float("LIGHTNING_RESERVE_FEE_MIN", default=2000)
|
|
||||||
|
|
||||||
MINT_PRIVATE_KEY = env.str("MINT_PRIVATE_KEY", default=None)
|
|
||||||
|
|
||||||
MINT_SERVER_HOST = env.str("MINT_SERVER_HOST", default="127.0.0.1")
|
|
||||||
MINT_SERVER_PORT = env.int("MINT_SERVER_PORT", default=3338)
|
|
||||||
|
|
||||||
MINT_URL = env.str("MINT_URL", default=None)
|
|
||||||
MINT_HOST = env.str("MINT_HOST", default="8333.space")
|
|
||||||
MINT_PORT = env.int("MINT_PORT", default=3338)
|
|
||||||
|
|
||||||
MINT_LIGHTNING_BACKEND = env.str("MINT_LIGHTNING_BACKEND", default="FakeWallet")
|
|
||||||
MINT_DATABASE = env.str("MINT_DATABASE", default="data/mint")
|
|
||||||
|
|
||||||
if not MINT_URL:
|
|
||||||
if MINT_HOST in ["localhost", "127.0.0.1"]:
|
|
||||||
MINT_URL = f"http://{MINT_HOST}:{MINT_PORT}"
|
|
||||||
else:
|
else:
|
||||||
MINT_URL = f"https://{MINT_HOST}:{MINT_PORT}"
|
ENV_FILE = ""
|
||||||
|
return ENV_FILE
|
||||||
|
|
||||||
LNBITS_ENDPOINT = env.str("LNBITS_ENDPOINT", default=None)
|
|
||||||
LNBITS_KEY = env.str("LNBITS_KEY", default=None)
|
|
||||||
|
|
||||||
NOSTR_PRIVATE_KEY = env.str("NOSTR_PRIVATE_KEY", default=None)
|
class CashuSettings(BaseSettings):
|
||||||
NOSTR_RELAYS = env.list(
|
env_file: str = Field(default=None)
|
||||||
"NOSTR_RELAYS",
|
lightning: bool = Field(default=True)
|
||||||
|
lightning_fee_percent: float = Field(default=1.0)
|
||||||
|
lightning_reserve_fee_min: int = Field(default=2000)
|
||||||
|
max_order: int = Field(default=64)
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
env_file = find_env_file()
|
||||||
|
env_file_encoding = "utf-8"
|
||||||
|
case_sensitive = False
|
||||||
|
extra = Extra.ignore
|
||||||
|
|
||||||
|
# def __init__(self, env_file=None):
|
||||||
|
# self.env_file = env_file or self.env_file
|
||||||
|
|
||||||
|
|
||||||
|
class EnvSettings(CashuSettings):
|
||||||
|
debug: bool = Field(default=False)
|
||||||
|
host: str = Field(default="127.0.0.1")
|
||||||
|
port: int = Field(default=5000)
|
||||||
|
cashu_dir: str = Field(default=os.path.join(str(Path.home()), ".cashu"))
|
||||||
|
|
||||||
|
|
||||||
|
class MintSettings(CashuSettings):
|
||||||
|
mint_private_key: str = Field(default=None)
|
||||||
|
mint_listen_host: str = Field(default="127.0.0.1")
|
||||||
|
mint_listen_port: int = Field(default=3338)
|
||||||
|
mint_lightning_backend: str = Field(default="LNbitsWallet")
|
||||||
|
mint_database: str = Field(default="data/mint")
|
||||||
|
|
||||||
|
mint_lnbits_endpoint: str = Field(default=None)
|
||||||
|
mint_lnbits_key: str = Field(default=None)
|
||||||
|
|
||||||
|
|
||||||
|
class WalletSettings(CashuSettings):
|
||||||
|
lightning: bool = Field(default=True)
|
||||||
|
tor: bool = Field(default=True)
|
||||||
|
socks_host: str = Field(default=None)
|
||||||
|
socks_port: int = Field(default=9050)
|
||||||
|
mint_url: str = Field(default=None)
|
||||||
|
mint_host: str = Field(default="8333.space")
|
||||||
|
mint_port: int = Field(default=3338)
|
||||||
|
|
||||||
|
nostr_private_key: str = Field(default=None)
|
||||||
|
nostr_relays: List[str] = Field(
|
||||||
default=[
|
default=[
|
||||||
"wss://nostr-pub.wellorder.net",
|
"wss://nostr-pub.wellorder.net",
|
||||||
"wss://relay.damus.io",
|
"wss://relay.damus.io",
|
||||||
"wss://nostr.zebedee.cloud",
|
"wss://nostr.zebedee.cloud",
|
||||||
"wss://relay.snort.social",
|
"wss://relay.snort.social",
|
||||||
"wss://nostr.fmt.wiz.biz",
|
"wss://nostr.fmt.wiz.biz",
|
||||||
],
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
MAX_ORDER = 64
|
|
||||||
VERSION = "0.9.4"
|
class Settings(EnvSettings, MintSettings, WalletSettings, CashuSettings):
|
||||||
|
version: str = Field(default=VERSION)
|
||||||
|
|
||||||
|
# def __init__(self, env_file=None):
|
||||||
|
# super().Config(env_file=env_file)
|
||||||
|
|
||||||
|
|
||||||
|
settings = Settings()
|
||||||
|
|
||||||
|
|
||||||
|
def startup_settings_tasks():
|
||||||
|
# set env_file (this does not affect the settings module, it's just for reading)
|
||||||
|
settings.env_file = find_env_file()
|
||||||
|
|
||||||
|
if not settings.debug:
|
||||||
|
# set traceback limit
|
||||||
|
sys.tracebacklimit = 0
|
||||||
|
|
||||||
|
# replace ~ with home directory in cashu_dir
|
||||||
|
settings.cashu_dir = settings.cashu_dir.replace("~", str(Path.home()))
|
||||||
|
|
||||||
|
# set mint_url if only mint_host is set
|
||||||
|
if not settings.mint_url:
|
||||||
|
if settings.mint_host in ["localhost", "127.0.0.1"] and settings.mint_port:
|
||||||
|
# localhost without https
|
||||||
|
settings.mint_url = f"http://{settings.mint_host}:{settings.mint_port}"
|
||||||
|
else:
|
||||||
|
settings.mint_url = f"https://{settings.mint_host}:{settings.mint_port}"
|
||||||
|
|
||||||
|
|
||||||
|
startup_settings_tasks()
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from typing import Dict, Optional
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from cashu.core.settings import DEBUG, LNBITS_ENDPOINT, LNBITS_KEY
|
from cashu.core.settings import settings
|
||||||
|
|
||||||
from .base import (
|
from .base import (
|
||||||
InvoiceResponse,
|
InvoiceResponse,
|
||||||
@@ -18,14 +18,14 @@ class LNbitsWallet(Wallet):
|
|||||||
"""https://github.com/lnbits/lnbits"""
|
"""https://github.com/lnbits/lnbits"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.endpoint = LNBITS_ENDPOINT
|
self.endpoint = settings.mint_lnbits_endpoint
|
||||||
|
|
||||||
key = LNBITS_KEY
|
key = settings.mint_lnbits_key
|
||||||
self.key = {"X-Api-Key": key}
|
self.key = {"X-Api-Key": key}
|
||||||
self.s = requests.Session()
|
self.s = requests.Session()
|
||||||
self.s.auth = ("user", "pass")
|
self.s.auth = ("user", "pass")
|
||||||
self.s.headers.update({"X-Api-Key": key})
|
self.s.headers.update({"X-Api-Key": key})
|
||||||
self.s.verify = not DEBUG
|
self.s.verify = not settings.debug
|
||||||
|
|
||||||
async def status(self) -> StatusResponse:
|
async def status(self) -> StatusResponse:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from starlette.middleware import Middleware
|
|||||||
from starlette.middleware.base import BaseHTTPMiddleware
|
from starlette.middleware.base import BaseHTTPMiddleware
|
||||||
from starlette.middleware.cors import CORSMiddleware
|
from starlette.middleware.cors import CORSMiddleware
|
||||||
|
|
||||||
from cashu.core.settings import DEBUG, VERSION
|
from cashu.core.settings import settings
|
||||||
|
|
||||||
from .router import router
|
from .router import router
|
||||||
from .startup import start_mint_init
|
from .startup import start_mint_init
|
||||||
@@ -33,7 +33,7 @@ def create_app(config_object="core.settings") -> FastAPI:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.padding = 0
|
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 DEBUG:
|
if settings.debug:
|
||||||
self.fmt: str = "<green>{time:YYYY-MM-DD HH:mm:ss.SS}</green> | <level>{level: <4}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> | <level>{message}</level>\n"
|
self.fmt: str = "<green>{time:YYYY-MM-DD HH:mm:ss.SS}</green> | <level>{level: <4}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> | <level>{message}</level>\n"
|
||||||
else:
|
else:
|
||||||
self.fmt: str = self.minimal_fmt
|
self.fmt: str = self.minimal_fmt
|
||||||
@@ -53,7 +53,7 @@ def create_app(config_object="core.settings") -> FastAPI:
|
|||||||
logger.log(level, record.getMessage())
|
logger.log(level, record.getMessage())
|
||||||
|
|
||||||
logger.remove()
|
logger.remove()
|
||||||
log_level: str = "DEBUG" if DEBUG else "INFO"
|
log_level: str = "DEBUG" if settings.debug else "INFO"
|
||||||
formatter = Formatter()
|
formatter = Formatter()
|
||||||
logger.add(sys.stderr, level=log_level, format=formatter.format)
|
logger.add(sys.stderr, level=log_level, format=formatter.format)
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ def create_app(config_object="core.settings") -> FastAPI:
|
|||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
title="Cashu Python Mint",
|
title="Cashu Python Mint",
|
||||||
description="Ecash wallet and mint for Bitcoin",
|
description="Ecash wallet and mint for Bitcoin",
|
||||||
version=VERSION,
|
version=settings.version,
|
||||||
license_info={
|
license_info={
|
||||||
"name": "MIT License",
|
"name": "MIT License",
|
||||||
"url": "https://raw.githubusercontent.com/cashubtc/cashu/main/LICENSE",
|
"url": "https://raw.githubusercontent.com/cashubtc/cashu/main/LICENSE",
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from cashu.core.db import Database
|
|||||||
from cashu.core.helpers import fee_reserve, sum_proofs
|
from cashu.core.helpers import fee_reserve, sum_proofs
|
||||||
from cashu.core.script import verify_script
|
from cashu.core.script import verify_script
|
||||||
from cashu.core.secp import PublicKey
|
from cashu.core.secp import PublicKey
|
||||||
from cashu.core.settings import LIGHTNING, MAX_ORDER, VERSION
|
from cashu.core.settings import settings
|
||||||
from cashu.core.split import amount_split
|
from cashu.core.split import amount_split
|
||||||
from cashu.lightning.base import Wallet
|
from cashu.lightning.base import Wallet
|
||||||
from cashu.mint.crud import LedgerCrud
|
from cashu.mint.crud import LedgerCrud
|
||||||
@@ -51,7 +51,9 @@ class Ledger:
|
|||||||
async def load_keyset(self, derivation_path, autosave=True):
|
async def load_keyset(self, derivation_path, autosave=True):
|
||||||
"""Load current keyset keyset or generate new one."""
|
"""Load current keyset keyset or generate new one."""
|
||||||
keyset = MintKeyset(
|
keyset = MintKeyset(
|
||||||
seed=self.master_key, derivation_path=derivation_path, version=VERSION
|
seed=self.master_key,
|
||||||
|
derivation_path=derivation_path,
|
||||||
|
version=settings.version,
|
||||||
)
|
)
|
||||||
# check if current keyset is stored in db and store if not
|
# check if current keyset is stored in db and store if not
|
||||||
logger.trace(f"Loading keyset {keyset.id} from db.")
|
logger.trace(f"Loading keyset {keyset.id} from db.")
|
||||||
@@ -192,7 +194,9 @@ class Ledger:
|
|||||||
|
|
||||||
def _verify_amount(self, amount: int):
|
def _verify_amount(self, amount: int):
|
||||||
"""Any amount used should be a positive integer not larger than 2^MAX_ORDER."""
|
"""Any amount used should be a positive integer not larger than 2^MAX_ORDER."""
|
||||||
valid = isinstance(amount, int) and amount > 0 and amount < 2**MAX_ORDER
|
valid = (
|
||||||
|
isinstance(amount, int) and amount > 0 and amount < 2**settings.max_order
|
||||||
|
)
|
||||||
if not valid:
|
if not valid:
|
||||||
raise Exception("invalid amount: " + str(amount))
|
raise Exception("invalid amount: " + str(amount))
|
||||||
return amount
|
return amount
|
||||||
@@ -359,7 +363,7 @@ class Ledger:
|
|||||||
amounts = [b.amount for b in B_s]
|
amounts = [b.amount for b in B_s]
|
||||||
amount = sum(amounts)
|
amount = sum(amounts)
|
||||||
# check if lightning invoice was paid
|
# check if lightning invoice was paid
|
||||||
if LIGHTNING:
|
if settings.lightning:
|
||||||
if not payment_hash:
|
if not payment_hash:
|
||||||
raise Exception("no payment_hash provided.")
|
raise Exception("no payment_hash provided.")
|
||||||
try:
|
try:
|
||||||
@@ -368,8 +372,10 @@ class Ledger:
|
|||||||
raise e
|
raise e
|
||||||
|
|
||||||
for amount in amounts:
|
for amount in amounts:
|
||||||
if amount not in [2**i for i in range(MAX_ORDER)]:
|
if amount not in [2**i for i in range(settings.max_order)]:
|
||||||
raise Exception(f"Can only mint amounts with 2^n up to {2**MAX_ORDER}.")
|
raise Exception(
|
||||||
|
f"Can only mint amounts with 2^n up to {2**settings.max_order}."
|
||||||
|
)
|
||||||
|
|
||||||
promises = await self._generate_promises(B_s, keyset)
|
promises = await self._generate_promises(B_s, keyset)
|
||||||
return promises
|
return promises
|
||||||
@@ -391,7 +397,7 @@ class Ledger:
|
|||||||
"provided proofs not enough for Lightning payment."
|
"provided proofs not enough for Lightning payment."
|
||||||
)
|
)
|
||||||
|
|
||||||
if LIGHTNING:
|
if settings.lightning:
|
||||||
status, preimage = await self._pay_lightning_invoice(invoice, fees_msat)
|
status, preimage = await self._pay_lightning_invoice(invoice, fees_msat)
|
||||||
else:
|
else:
|
||||||
status, preimage = True, "preimage"
|
status, preimage = True, "preimage"
|
||||||
@@ -413,7 +419,7 @@ class Ledger:
|
|||||||
"""Returns the fees (in msat) required to pay this pr."""
|
"""Returns the fees (in msat) required to pay this pr."""
|
||||||
# hack: check if it's internal, if it exists, it will return paid = False,
|
# hack: check if it's internal, if it exists, it will return paid = False,
|
||||||
# if id does not exist (not internal), it returns paid = None
|
# if id does not exist (not internal), it returns paid = None
|
||||||
if LIGHTNING:
|
if settings.lightning:
|
||||||
decoded_invoice = bolt11.decode(pr)
|
decoded_invoice = bolt11.decode(pr)
|
||||||
amount = math.ceil(decoded_invoice.amount_msat / 1000)
|
amount = math.ceil(decoded_invoice.amount_msat / 1000)
|
||||||
paid = await self.lightning.get_invoice_status(decoded_invoice.payment_hash)
|
paid = await self.lightning.get_invoice_status(decoded_invoice.payment_hash)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import click
|
|||||||
import uvicorn
|
import uvicorn
|
||||||
from click import Context
|
from click import Context
|
||||||
|
|
||||||
from cashu.core.settings import MINT_SERVER_HOST, MINT_SERVER_PORT
|
from cashu.core.settings import settings
|
||||||
|
|
||||||
|
|
||||||
@click.command(
|
@click.command(
|
||||||
@@ -13,15 +13,15 @@ from cashu.core.settings import MINT_SERVER_HOST, MINT_SERVER_PORT
|
|||||||
allow_extra_args=True,
|
allow_extra_args=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@click.option("--port", default=MINT_SERVER_PORT, help="Port to listen on")
|
@click.option("--port", default=settings.mint_listen_port, help="Port to listen on")
|
||||||
@click.option("--host", default=MINT_SERVER_HOST, help="Host to run mint on")
|
@click.option("--host", default=settings.mint_listen_host, help="Host to run mint on")
|
||||||
@click.option("--ssl-keyfile", default=None, help="Path to SSL keyfile")
|
@click.option("--ssl-keyfile", default=None, help="Path to SSL keyfile")
|
||||||
@click.option("--ssl-certfile", default=None, help="Path to SSL certificate")
|
@click.option("--ssl-certfile", default=None, help="Path to SSL certificate")
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def main(
|
def main(
|
||||||
ctx: Context,
|
ctx: Context,
|
||||||
port: int = MINT_SERVER_PORT,
|
port: int = settings.mint_listen_port,
|
||||||
host: str = MINT_SERVER_HOST,
|
host: str = settings.mint_listen_host,
|
||||||
ssl_keyfile: Optional[str] = None,
|
ssl_keyfile: Optional[str] = None,
|
||||||
ssl_certfile: Optional[str] = None,
|
ssl_certfile: Optional[str] = None,
|
||||||
):
|
):
|
||||||
|
|||||||
@@ -7,26 +7,24 @@ from loguru import logger
|
|||||||
|
|
||||||
from cashu.core.db import Database
|
from cashu.core.db import Database
|
||||||
from cashu.core.migrations import migrate_databases
|
from cashu.core.migrations import migrate_databases
|
||||||
from cashu.core.settings import (
|
from cashu.core.settings import settings
|
||||||
CASHU_DIR,
|
|
||||||
LIGHTNING,
|
|
||||||
MINT_DATABASE,
|
|
||||||
MINT_LIGHTNING_BACKEND,
|
|
||||||
MINT_PRIVATE_KEY,
|
|
||||||
)
|
|
||||||
from cashu.lightning.fake import FakeWallet # type: ignore
|
from cashu.lightning.fake import FakeWallet # type: ignore
|
||||||
from cashu.lightning.lnbits import LNbitsWallet # type: ignore
|
from cashu.lightning.lnbits import LNbitsWallet # type: ignore
|
||||||
from cashu.mint import migrations
|
from cashu.mint import migrations
|
||||||
from cashu.mint.ledger import Ledger
|
from cashu.mint.ledger import Ledger
|
||||||
|
|
||||||
|
logger.debug("Enviroment Settings:")
|
||||||
|
for key, value in settings.dict().items():
|
||||||
|
logger.debug(f"{key}: {value}")
|
||||||
|
|
||||||
wallets_module = importlib.import_module("cashu.lightning")
|
wallets_module = importlib.import_module("cashu.lightning")
|
||||||
LIGHTNING_BACKEND = getattr(wallets_module, MINT_LIGHTNING_BACKEND)()
|
lightning_backend = getattr(wallets_module, settings.mint_lightning_backend)()
|
||||||
|
|
||||||
ledger = Ledger(
|
ledger = Ledger(
|
||||||
db=Database("mint", MINT_DATABASE),
|
db=Database("mint", settings.mint_database),
|
||||||
seed=MINT_PRIVATE_KEY,
|
seed=settings.mint_private_key,
|
||||||
derivation_path="0/0/0/0",
|
derivation_path="0/0/0/0",
|
||||||
lightning=LIGHTNING_BACKEND,
|
lightning=lightning_backend,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -36,8 +34,8 @@ async def start_mint_init():
|
|||||||
await ledger.load_used_proofs()
|
await ledger.load_used_proofs()
|
||||||
await ledger.init_keysets()
|
await ledger.init_keysets()
|
||||||
|
|
||||||
if LIGHTNING:
|
if settings.lightning:
|
||||||
logger.info(f"Using backend: {MINT_LIGHTNING_BACKEND}")
|
logger.info(f"Using backend: {settings.mint_lightning_backend}")
|
||||||
error_message, balance = await ledger.lightning.status()
|
error_message, balance = await ledger.lightning.status()
|
||||||
if error_message:
|
if error_message:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
@@ -46,5 +44,5 @@ async def start_mint_init():
|
|||||||
)
|
)
|
||||||
logger.info(f"Lightning balance: {balance} msat")
|
logger.info(f"Lightning balance: {balance} msat")
|
||||||
|
|
||||||
logger.info(f"Data dir: {CASHU_DIR}")
|
logger.info(f"Data dir: {settings.cashu_dir}")
|
||||||
logger.info("Mint started.")
|
logger.info("Mint started.")
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ sys.tracebacklimit = None # type: ignore
|
|||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from cashu.core.settings import DEBUG
|
from cashu.core.settings import settings
|
||||||
|
|
||||||
# configure logger
|
# configure logger
|
||||||
logger.remove()
|
logger.remove()
|
||||||
logger.add(sys.stderr, level="DEBUG" if DEBUG else "INFO")
|
logger.add(sys.stderr, level="DEBUG" if settings.debug else "INFO")
|
||||||
|
|||||||
@@ -21,19 +21,7 @@ from loguru import logger
|
|||||||
from cashu.core.base import Proof, TokenV2
|
from cashu.core.base import Proof, TokenV2
|
||||||
from cashu.core.helpers import sum_proofs
|
from cashu.core.helpers import sum_proofs
|
||||||
from cashu.core.migrations import migrate_databases
|
from cashu.core.migrations import migrate_databases
|
||||||
from cashu.core.settings import (
|
from cashu.core.settings import settings
|
||||||
CASHU_DIR,
|
|
||||||
DEBUG,
|
|
||||||
ENV_FILE,
|
|
||||||
LIGHTNING,
|
|
||||||
MINT_URL,
|
|
||||||
NOSTR_PRIVATE_KEY,
|
|
||||||
NOSTR_RELAYS,
|
|
||||||
SOCKS_HOST,
|
|
||||||
SOCKS_PORT,
|
|
||||||
TOR,
|
|
||||||
VERSION,
|
|
||||||
)
|
|
||||||
from cashu.nostr.nostr.client.client import NostrClient
|
from cashu.nostr.nostr.client.client import NostrClient
|
||||||
from cashu.tor.tor import TorProxy
|
from cashu.tor.tor import TorProxy
|
||||||
from cashu.wallet import migrations
|
from cashu.wallet import migrations
|
||||||
@@ -69,7 +57,12 @@ class NaturalOrderGroup(click.Group):
|
|||||||
|
|
||||||
|
|
||||||
@click.group(cls=NaturalOrderGroup)
|
@click.group(cls=NaturalOrderGroup)
|
||||||
@click.option("--host", "-h", default=MINT_URL, help=f"Mint URL (default: {MINT_URL}).")
|
@click.option(
|
||||||
|
"--host",
|
||||||
|
"-h",
|
||||||
|
default=settings.mint_url,
|
||||||
|
help=f"Mint URL (default: {settings.mint_url}).",
|
||||||
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"--wallet",
|
"--wallet",
|
||||||
"-w",
|
"-w",
|
||||||
@@ -79,24 +72,22 @@ class NaturalOrderGroup(click.Group):
|
|||||||
)
|
)
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def cli(ctx: Context, host: str, walletname: str):
|
def cli(ctx: Context, host: str, walletname: str):
|
||||||
if TOR and not TorProxy().check_platform():
|
if settings.tor and not TorProxy().check_platform():
|
||||||
error_str = "Your settings say TOR=true but the built-in Tor bundle is not supported on your system. You have two options: Either install Tor manually and set TOR=FALSE and SOCKS_HOST=localhost and SOCKS_PORT=9050 in your Cashu config (recommended). Or turn off Tor by setting TOR=false (not recommended). Cashu will not work until you edit your config file accordingly."
|
error_str = "Your settings say TOR=true but the built-in Tor bundle is not supported on your system. You have two options: Either install Tor manually and set TOR=FALSE and SOCKS_HOST=localhost and SOCKS_PORT=9050 in your Cashu config (recommended). Or turn off Tor by setting TOR=false (not recommended). Cashu will not work until you edit your config file accordingly."
|
||||||
error_str += "\n\n"
|
error_str += "\n\n"
|
||||||
if ENV_FILE:
|
if settings.env_file:
|
||||||
error_str += f"Edit your Cashu config file here: {ENV_FILE}"
|
error_str += f"Edit your Cashu config file here: {settings.env_file}"
|
||||||
env_path = ENV_FILE
|
env_path = settings.env_file
|
||||||
else:
|
else:
|
||||||
error_str += (
|
error_str += f"Ceate a new Cashu config file here: {os.path.join(settings.cashu_dir, '.env')}"
|
||||||
f"Ceate a new Cashu config file here: {os.path.join(CASHU_DIR, '.env')}"
|
env_path = os.path.join(settings.cashu_dir, ".env")
|
||||||
)
|
|
||||||
env_path = os.path.join(CASHU_DIR, ".env")
|
|
||||||
error_str += f'\n\nYou can turn off Tor with this command: echo "TOR=FALSE" >> {env_path}'
|
error_str += f'\n\nYou can turn off Tor with this command: echo "TOR=FALSE" >> {env_path}'
|
||||||
raise Exception(error_str)
|
raise Exception(error_str)
|
||||||
|
|
||||||
ctx.ensure_object(dict)
|
ctx.ensure_object(dict)
|
||||||
ctx.obj["HOST"] = host
|
ctx.obj["HOST"] = host
|
||||||
ctx.obj["WALLET_NAME"] = walletname
|
ctx.obj["WALLET_NAME"] = walletname
|
||||||
wallet = Wallet(ctx.obj["HOST"], os.path.join(CASHU_DIR, walletname))
|
wallet = Wallet(ctx.obj["HOST"], os.path.join(settings.cashu_dir, walletname))
|
||||||
ctx.obj["WALLET"] = wallet
|
ctx.obj["WALLET"] = wallet
|
||||||
asyncio.run(init_wallet(wallet))
|
asyncio.run(init_wallet(wallet))
|
||||||
pass
|
pass
|
||||||
@@ -149,7 +140,7 @@ async def invoice(ctx: Context, amount: int, hash: str):
|
|||||||
wallet: Wallet = ctx.obj["WALLET"]
|
wallet: Wallet = ctx.obj["WALLET"]
|
||||||
await wallet.load_mint()
|
await wallet.load_mint()
|
||||||
wallet.status()
|
wallet.status()
|
||||||
if not LIGHTNING:
|
if not settings.lightning:
|
||||||
r = await wallet.mint(amount)
|
r = await wallet.mint(amount)
|
||||||
elif amount and not hash:
|
elif amount and not hash:
|
||||||
invoice = await wallet.request_mint(amount)
|
invoice = await wallet.request_mint(amount)
|
||||||
@@ -601,13 +592,15 @@ async def invoices(ctx):
|
|||||||
@coro
|
@coro
|
||||||
async def wallets(ctx):
|
async def wallets(ctx):
|
||||||
# list all directories
|
# list all directories
|
||||||
wallets = [d for d in listdir(CASHU_DIR) if isdir(join(CASHU_DIR, d))]
|
wallets = [
|
||||||
|
d for d in listdir(settings.cashu_dir) if isdir(join(settings.cashu_dir, d))
|
||||||
|
]
|
||||||
try:
|
try:
|
||||||
wallets.remove("mint")
|
wallets.remove("mint")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
for w in wallets:
|
for w in wallets:
|
||||||
wallet = Wallet(ctx.obj["HOST"], os.path.join(CASHU_DIR, w))
|
wallet = Wallet(ctx.obj["HOST"], os.path.join(settings.cashu_dir, w))
|
||||||
try:
|
try:
|
||||||
await init_wallet(wallet)
|
await init_wallet(wallet)
|
||||||
if wallet.proofs and len(wallet.proofs):
|
if wallet.proofs and len(wallet.proofs):
|
||||||
@@ -625,20 +618,20 @@ async def wallets(ctx):
|
|||||||
@click.pass_context
|
@click.pass_context
|
||||||
@coro
|
@coro
|
||||||
async def info(ctx: Context):
|
async def info(ctx: Context):
|
||||||
print(f"Version: {VERSION}")
|
print(f"Version: {settings.version}")
|
||||||
print(f"Wallet: {ctx.obj['WALLET_NAME']}")
|
print(f"Wallet: {ctx.obj['WALLET_NAME']}")
|
||||||
if DEBUG:
|
if settings.debug:
|
||||||
print(f"Debug: {DEBUG}")
|
print(f"Debug: {settings.debug}")
|
||||||
print(f"Cashu dir: {CASHU_DIR}")
|
print(f"Cashu dir: {settings.cashu_dir}")
|
||||||
if ENV_FILE:
|
if settings.env_file:
|
||||||
print(f"Settings: {ENV_FILE}")
|
print(f"Settings: {settings.env_file}")
|
||||||
if TOR:
|
if settings.tor:
|
||||||
print(f"Tor enabled: {TOR}")
|
print(f"Tor enabled: {settings.tor}")
|
||||||
if NOSTR_PRIVATE_KEY:
|
if settings.nostr_private_key:
|
||||||
client = NostrClient(private_key=NOSTR_PRIVATE_KEY, connect=False)
|
client = NostrClient(private_key=settings.nostr_private_key, connect=False)
|
||||||
print(f"Nostr public key: {client.public_key.bech32()}")
|
print(f"Nostr public key: {client.public_key.bech32()}")
|
||||||
print(f"Nostr relays: {NOSTR_RELAYS}")
|
print(f"Nostr relays: {settings.nostr_relays}")
|
||||||
if SOCKS_HOST:
|
if settings.socks_host:
|
||||||
print(f"Socks proxy: {SOCKS_HOST}:{SOCKS_PORT}")
|
print(f"Socks proxy: {settings.socks_host}:{settings.socks_port}")
|
||||||
print(f"Mint URL: {ctx.obj['HOST']}")
|
print(f"Mint URL: {ctx.obj['HOST']}")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from loguru import logger
|
|||||||
|
|
||||||
from cashu.core.base import Proof, TokenV2, TokenV2Mint, WalletKeyset
|
from cashu.core.base import Proof, TokenV2, TokenV2Mint, WalletKeyset
|
||||||
from cashu.core.helpers import sum_proofs
|
from cashu.core.helpers import sum_proofs
|
||||||
from cashu.core.settings import CASHU_DIR, MINT_URL, NOSTR_PRIVATE_KEY, NOSTR_RELAYS
|
from cashu.core.settings import settings
|
||||||
from cashu.wallet.crud import get_keyset
|
from cashu.wallet.crud import get_keyset
|
||||||
from cashu.wallet.wallet import Wallet as Wallet
|
from cashu.wallet.wallet import Wallet as Wallet
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ async def verify_mints(ctx: Context, token: TokenV2):
|
|||||||
for keyset in set([id for id in mint.ids if id in proofs_keysets]):
|
for keyset in set([id for id in mint.ids if id in proofs_keysets]):
|
||||||
# init a temporary wallet object
|
# init a temporary wallet object
|
||||||
keyset_wallet = Wallet(
|
keyset_wallet = Wallet(
|
||||||
mint.url, os.path.join(CASHU_DIR, ctx.obj["WALLET_NAME"])
|
mint.url, os.path.join(settings.cashu_dir, ctx.obj["WALLET_NAME"])
|
||||||
)
|
)
|
||||||
# make sure that this mint supports this keyset
|
# make sure that this mint supports this keyset
|
||||||
mint_keysets = await keyset_wallet._get_keyset_ids(mint.url)
|
mint_keysets = await keyset_wallet._get_keyset_ids(mint.url)
|
||||||
@@ -81,7 +81,7 @@ async def redeem_multimint(ctx: Context, token: TokenV2, script, signature):
|
|||||||
logger.debug(f"Redeeming tokens from keyset {keyset}")
|
logger.debug(f"Redeeming tokens from keyset {keyset}")
|
||||||
# init a temporary wallet object
|
# init a temporary wallet object
|
||||||
keyset_wallet = Wallet(
|
keyset_wallet = Wallet(
|
||||||
mint.url, os.path.join(CASHU_DIR, ctx.obj["WALLET_NAME"])
|
mint.url, os.path.join(settings.cashu_dir, ctx.obj["WALLET_NAME"])
|
||||||
)
|
)
|
||||||
|
|
||||||
# load the keys
|
# load the keys
|
||||||
@@ -147,7 +147,9 @@ async def get_mint_wallet(ctx: Context):
|
|||||||
mint_url = list(mint_balances.keys())[mint_nr - 1]
|
mint_url = list(mint_balances.keys())[mint_nr - 1]
|
||||||
|
|
||||||
# load this mint_url into a wallet
|
# load this mint_url into a wallet
|
||||||
mint_wallet = Wallet(mint_url, os.path.join(CASHU_DIR, ctx.obj["WALLET_NAME"]))
|
mint_wallet = Wallet(
|
||||||
|
mint_url, os.path.join(settings.cashu_dir, ctx.obj["WALLET_NAME"])
|
||||||
|
)
|
||||||
mint_keysets: WalletKeyset = await get_keyset(mint_url=mint_url, db=mint_wallet.db) # type: ignore
|
mint_keysets: WalletKeyset = await get_keyset(mint_url=mint_url, db=mint_wallet.db) # type: ignore
|
||||||
|
|
||||||
# load the keys
|
# load the keys
|
||||||
@@ -196,7 +198,8 @@ async def proofs_to_serialized_tokenv2(wallet, proofs: List[Proof], url: str):
|
|||||||
url = ks.mint_url if ks and ks.mint_url else ""
|
url = ks.mint_url if ks and ks.mint_url else ""
|
||||||
|
|
||||||
url = url or (
|
url = url or (
|
||||||
input(f"Enter mint URL (press enter for default {MINT_URL}): ") or MINT_URL
|
input(f"Enter mint URL (press enter for default {settings.mint_url}): ")
|
||||||
|
or settings.mint_url
|
||||||
)
|
)
|
||||||
|
|
||||||
token.mints.append(TokenV2Mint(url=url, ids=keysets))
|
token.mints.append(TokenV2Mint(url=url, ids=keysets))
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import click
|
|||||||
from click import Context
|
from click import Context
|
||||||
from requests.exceptions import ConnectionError
|
from requests.exceptions import ConnectionError
|
||||||
|
|
||||||
from cashu.core.settings import NOSTR_PRIVATE_KEY, NOSTR_RELAYS
|
from cashu.core.settings import settings
|
||||||
from cashu.nostr.nostr.client.client import NostrClient
|
from cashu.nostr.nostr.client.client import NostrClient
|
||||||
from cashu.nostr.nostr.event import Event
|
from cashu.nostr.nostr.event import Event
|
||||||
from cashu.nostr.nostr.key import PublicKey
|
from cashu.nostr.nostr.key import PublicKey
|
||||||
@@ -79,8 +79,10 @@ async def send_nostr(ctx: Context, amount: int, pubkey: str, verbose: bool, yes:
|
|||||||
default=True,
|
default=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
client = NostrClient(private_key=NOSTR_PRIVATE_KEY or "", relays=NOSTR_RELAYS)
|
client = NostrClient(
|
||||||
if verbose and not NOSTR_PRIVATE_KEY:
|
private_key=settings.nostr_private_key or "", relays=settings.nostr_relays
|
||||||
|
)
|
||||||
|
if verbose and not settings.nostr_private_key:
|
||||||
# we generated a random key if none was present
|
# we generated a random key if none was present
|
||||||
print(f"Your nostr private key: {client.private_key.bech32()}")
|
print(f"Your nostr private key: {client.private_key.bech32()}")
|
||||||
|
|
||||||
@@ -91,12 +93,14 @@ async def send_nostr(ctx: Context, amount: int, pubkey: str, verbose: bool, yes:
|
|||||||
|
|
||||||
|
|
||||||
async def receive_nostr(ctx: Context, verbose: bool):
|
async def receive_nostr(ctx: Context, verbose: bool):
|
||||||
if NOSTR_PRIVATE_KEY is None:
|
if settings.nostr_private_key is None:
|
||||||
print(
|
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("")
|
print("")
|
||||||
client = NostrClient(private_key=NOSTR_PRIVATE_KEY, relays=NOSTR_RELAYS)
|
client = NostrClient(
|
||||||
|
private_key=settings.nostr_private_key, relays=settings.nostr_relays
|
||||||
|
)
|
||||||
print(f"Your nostr public key: {client.public_key.bech32()}")
|
print(f"Your nostr public key: {client.public_key.bech32()}")
|
||||||
if verbose:
|
if verbose:
|
||||||
print(f"Your nostr private key (do not share!): {client.private_key.bech32()}")
|
print(f"Your nostr private key (do not share!): {client.private_key.bech32()}")
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ from cashu.core.script import (
|
|||||||
step2_carol_sign_tx,
|
step2_carol_sign_tx,
|
||||||
)
|
)
|
||||||
from cashu.core.secp import PublicKey
|
from cashu.core.secp import PublicKey
|
||||||
from cashu.core.settings import DEBUG, MAX_ORDER, SOCKS_HOST, SOCKS_PORT, TOR, VERSION
|
from cashu.core.settings import settings
|
||||||
from cashu.core.split import amount_split
|
from cashu.core.split import amount_split
|
||||||
from cashu.tor.tor import TorProxy
|
from cashu.tor.tor import TorProxy
|
||||||
from cashu.wallet.crud import (
|
from cashu.wallet.crud import (
|
||||||
@@ -67,16 +67,16 @@ def async_set_requests(func):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
async def wrapper(self, *args, **kwargs):
|
async def wrapper(self, *args, **kwargs):
|
||||||
self.s.headers.update({"Client-version": VERSION})
|
self.s.headers.update({"Client-version": settings.version})
|
||||||
if DEBUG:
|
if settings.debug:
|
||||||
self.s.verify = False
|
self.s.verify = False
|
||||||
socks_host, socks_port = None, None
|
socks_host, socks_port = None, None
|
||||||
if TOR and TorProxy().check_platform():
|
if settings.tor and TorProxy().check_platform():
|
||||||
self.tor = TorProxy(timeout=True)
|
self.tor = TorProxy(timeout=True)
|
||||||
self.tor.run_daemon(verbose=True)
|
self.tor.run_daemon(verbose=True)
|
||||||
socks_host, socks_port = "localhost", 9050
|
socks_host, socks_port = "localhost", 9050
|
||||||
else:
|
else:
|
||||||
socks_host, socks_port = SOCKS_HOST, SOCKS_PORT
|
socks_host, socks_port = settings.socks_host, settings.socks_port
|
||||||
|
|
||||||
if socks_host and socks_port:
|
if socks_host and socks_port:
|
||||||
proxies = {
|
proxies = {
|
||||||
@@ -515,8 +515,10 @@ class Wallet(LedgerAPI):
|
|||||||
List[Proof]: Newly minted proofs.
|
List[Proof]: Newly minted proofs.
|
||||||
"""
|
"""
|
||||||
for amount in amounts:
|
for amount in amounts:
|
||||||
if amount not in [2**i for i in range(MAX_ORDER)]:
|
if amount not in [2**i for i in range(settings.max_order)]:
|
||||||
raise Exception(f"Can only mint amounts with 2^n up to {2**MAX_ORDER}.")
|
raise Exception(
|
||||||
|
f"Can only mint amounts with 2^n up to {2**settings.max_order}."
|
||||||
|
)
|
||||||
proofs = await super().mint(amounts, payment_hash)
|
proofs = await super().mint(amounts, payment_hash)
|
||||||
if proofs == []:
|
if proofs == []:
|
||||||
raise Exception("received no proofs.")
|
raise Exception("received no proofs.")
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import pytest
|
|||||||
from click.testing import CliRunner
|
from click.testing import CliRunner
|
||||||
|
|
||||||
from cashu.core.migrations import migrate_databases
|
from cashu.core.migrations import migrate_databases
|
||||||
from cashu.core.settings import VERSION
|
from cashu.core.settings import settings
|
||||||
from cashu.wallet import migrations
|
from cashu.wallet import migrations
|
||||||
from cashu.wallet.cli.cli import cli
|
from cashu.wallet.cli.cli import cli
|
||||||
from cashu.wallet.wallet import Wallet
|
from cashu.wallet.wallet import Wallet
|
||||||
@@ -29,7 +29,7 @@ def test_info():
|
|||||||
)
|
)
|
||||||
print("INFO")
|
print("INFO")
|
||||||
print(result.output)
|
print(result.output)
|
||||||
result.output.startswith(f"Version: {VERSION}")
|
result.output.startswith(f"Version: {settings.version}")
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ SERVER_ENDPOINT = "http://localhost:3338"
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from cashu.core.db import Database
|
from cashu.core.db import Database
|
||||||
from cashu.core.settings import MAX_ORDER
|
from cashu.core.settings import settings
|
||||||
from cashu.mint import migrations
|
from cashu.mint import migrations
|
||||||
from cashu.mint.ledger import Ledger
|
from cashu.mint.ledger import Ledger
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ async def test_keysets(ledger: Ledger):
|
|||||||
async def test_get_keyset(ledger: Ledger):
|
async def test_get_keyset(ledger: Ledger):
|
||||||
keyset = ledger.get_keyset()
|
keyset = ledger.get_keyset()
|
||||||
assert type(keyset) == dict
|
assert type(keyset) == dict
|
||||||
assert len(keyset) == MAX_ORDER
|
assert len(keyset) == settings.max_order
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import pytest_asyncio
|
|||||||
from cashu.core.base import Proof
|
from cashu.core.base import Proof
|
||||||
from cashu.core.helpers import async_unwrap, sum_proofs
|
from cashu.core.helpers import async_unwrap, sum_proofs
|
||||||
from cashu.core.migrations import migrate_databases
|
from cashu.core.migrations import migrate_databases
|
||||||
from cashu.core.settings import MAX_ORDER
|
from cashu.core.settings import settings
|
||||||
from cashu.wallet import migrations
|
from cashu.wallet import migrations
|
||||||
from cashu.wallet.wallet import Wallet
|
from cashu.wallet.wallet import Wallet
|
||||||
from cashu.wallet.wallet import Wallet as Wallet1
|
from cashu.wallet.wallet import Wallet as Wallet1
|
||||||
@@ -51,7 +51,7 @@ async def wallet2(mint):
|
|||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_get_keys(wallet1: Wallet):
|
async def test_get_keys(wallet1: Wallet):
|
||||||
assert wallet1.keys.public_keys
|
assert wallet1.keys.public_keys
|
||||||
assert len(wallet1.keys.public_keys) == MAX_ORDER
|
assert len(wallet1.keys.public_keys) == settings.max_order
|
||||||
keyset = await wallet1._get_keys(wallet1.url)
|
keyset = await wallet1._get_keys(wallet1.url)
|
||||||
assert keyset.id is not None
|
assert keyset.id is not None
|
||||||
assert type(keyset.id) == str
|
assert type(keyset.id) == str
|
||||||
@@ -61,7 +61,7 @@ async def test_get_keys(wallet1: Wallet):
|
|||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_get_keyset(wallet1: Wallet):
|
async def test_get_keyset(wallet1: Wallet):
|
||||||
assert wallet1.keys.public_keys
|
assert wallet1.keys.public_keys
|
||||||
assert len(wallet1.keys.public_keys) == MAX_ORDER
|
assert len(wallet1.keys.public_keys) == settings.max_order
|
||||||
# let's get the keys first so we can get a keyset ID that we use later
|
# let's get the keys first so we can get a keyset ID that we use later
|
||||||
keys1 = await wallet1._get_keys(wallet1.url)
|
keys1 = await wallet1._get_keys(wallet1.url)
|
||||||
# gets the keys of a specific keyset
|
# gets the keys of a specific keyset
|
||||||
@@ -107,7 +107,7 @@ async def test_mint_amounts_wrong_order(wallet1: Wallet):
|
|||||||
"""Mint amount that is not part in 2^n"""
|
"""Mint amount that is not part in 2^n"""
|
||||||
await assert_err(
|
await assert_err(
|
||||||
wallet1.mint_amounts([1, 2, 3]),
|
wallet1.mint_amounts([1, 2, 3]),
|
||||||
f"Can only mint amounts with 2^n up to {2**MAX_ORDER}.",
|
f"Can only mint amounts with 2^n up to {2**settings.max_order}.",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user