Skip to content

Commit

Permalink
add strike wallet and choose backend dynamically
Browse files Browse the repository at this point in the history
  • Loading branch information
callebtc committed Nov 21, 2023
1 parent 5b62af4 commit 47f83c1
Show file tree
Hide file tree
Showing 17 changed files with 661 additions and 251 deletions.
21 changes: 15 additions & 6 deletions cashu/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ class MeltQuote(BaseModel):
checking_id: str
unit: str
amount: int
fee_reserve: Optional[int] = None
fee_reserve: int
paid: bool


Expand Down Expand Up @@ -427,6 +427,7 @@ class Unit(Enum):
sat = 0
msat = 1
usd = 2
cheese = 3

def str(self, amount: int) -> str:
if self == Unit.sat:
Expand All @@ -435,10 +436,16 @@ def str(self, amount: int) -> str:
return f"{amount} msat"
elif self == Unit.usd:
return f"${amount/100:.2f} USD"
elif self == Unit.cheese:
return f"E{amount/100:.2f} Chuck E Cheese Tokens"
else:
raise Exception("Invalid unit")


class Method(Enum):
bolt11 = 0


class WalletKeyset:
"""
Contains the keyset from the wallets's perspective.
Expand Down Expand Up @@ -486,9 +493,9 @@ def __init__(
self.unit = Unit[unit]

def serialize(self):
return json.dumps({
amount: key.serialize().hex() for amount, key in self.public_keys.items()
})
return json.dumps(
{amount: key.serialize().hex() for amount, key in self.public_keys.items()}
)

@classmethod
def from_row(cls, row: Row):
Expand Down Expand Up @@ -567,8 +574,8 @@ def __init__(
# infer unit from derivation path
if not unit:
logger.warning(
f"Unit for keyset {self.id} not set – attempting to parse from"
" derivation path"
f"Unit for keyset {self.derivation_path} not set – attempting to parse"
" from derivation path"
)
try:
self.unit = Unit(
Expand All @@ -587,6 +594,8 @@ def __init__(
if self.seed and self.derivation_path:
self.generate_keys()

logger.debug(f"Keyset id: {self.id} ({self.unit.name})")

@property
def public_keys_hex(self) -> Dict[int, str]:
assert self.public_keys, "public keys not set"
Expand Down
2 changes: 2 additions & 0 deletions cashu/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class MintSettings(CashuSettings):
mint_lnbits_endpoint: str = Field(default=None)
mint_lnbits_key: str = Field(default=None)

mint_strike_key: str = Field(default=None)


class FakeWalletSettings(MintSettings):
fakewallet_brr: bool = Field(default=True)
Expand Down
1 change: 1 addition & 0 deletions cashu/lightning/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .fake import FakeWallet # noqa: F401
from .lnbits import LNbitsWallet # noqa: F401
from .lndrest import LndRestWallet # noqa: F401
from .strike import StrikeUSDWallet # noqa: F401

if settings.mint_lightning_backend is None:
raise Exception("MINT_LIGHTNING_BACKEND not configured")
36 changes: 33 additions & 3 deletions cashu/lightning/base.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
from abc import ABC, abstractmethod
from typing import Coroutine, Optional
from typing import Coroutine, Optional, Union

from pydantic import BaseModel

from ..core.base import Method, Unit


class StatusResponse(BaseModel):
error_message: Optional[str]
balance_msat: int
balance: Union[int, float]


class InvoiceQuoteResponse(BaseModel):
checking_id: str
amount: int


class PaymentQuoteResponse(BaseModel):
checking_id: str
amount: int
fee: int


class InvoiceResponse(BaseModel):
Expand Down Expand Up @@ -48,7 +61,10 @@ def __str__(self) -> str:
return "unknown (should never happen)"


class Wallet(ABC):
class LightningWallet(ABC):
unit: Unit
method: Method

@abstractmethod
def status(self) -> Coroutine[None, None, StatusResponse]:
pass
Expand Down Expand Up @@ -80,6 +96,20 @@ def get_payment_status(
) -> Coroutine[None, None, PaymentStatus]:
pass

@abstractmethod
async def get_payment_quote(
self,
bolt11: str,
) -> PaymentQuoteResponse:
pass

# @abstractmethod
# async def get_invoice_quote(
# self,
# bolt11: str,
# ) -> InvoiceQuoteResponse:
# pass

# @abstractmethod
# def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
# pass
Expand Down
4 changes: 2 additions & 2 deletions cashu/lightning/corelightningrest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@
from ..core.settings import settings
from .base import (
InvoiceResponse,
LightningWallet,
PaymentResponse,
PaymentStatus,
StatusResponse,
Unsupported,
Wallet,
)
from .macaroon import load_macaroon


class CoreLightningRestWallet(Wallet):
class CoreLightningRestWallet(LightningWallet):
def __init__(self):
macaroon = settings.mint_corelightning_rest_macaroon
assert macaroon, "missing cln-rest macaroon"
Expand Down
29 changes: 26 additions & 3 deletions cashu/lightning/fake.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import hashlib
import math
import random
from datetime import datetime
from os import urandom
Expand All @@ -14,19 +15,26 @@
encode,
)

from ..core.base import Method, Unit
from ..core.helpers import fee_reserve
from ..core.settings import settings
from .base import (
InvoiceQuoteResponse,
InvoiceResponse,
LightningWallet,
PaymentQuoteResponse,
PaymentResponse,
PaymentStatus,
StatusResponse,
Wallet,
)


class FakeWallet(Wallet):
class FakeWallet(LightningWallet):
"""https://github.com/lnbits/lnbits"""

method = Method.bolt11
unit = Unit.sat

queue: asyncio.Queue[Bolt11] = asyncio.Queue(0)
payment_secrets: Dict[str, str] = dict()
paid_invoices: Set[str] = set()
Expand All @@ -40,7 +48,7 @@ class FakeWallet(Wallet):
).hex()

async def status(self) -> StatusResponse:
return StatusResponse(error_message=None, balance_msat=1337)
return StatusResponse(error_message=None, balance=1337)

async def create_invoice(
self,
Expand Down Expand Up @@ -125,3 +133,18 @@ async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
while True:
value: Bolt11 = await self.queue.get()
yield value.payment_hash

async def get_invoice_quote(self, bolt11: str) -> InvoiceQuoteResponse:
invoice_obj = decode(bolt11)
assert invoice_obj.amount_msat, "invoice has no amount."
amount = invoice_obj.amount_msat
return InvoiceQuoteResponse(checking_id="", amount=amount)

async def get_payment_quote(self, bolt11: str) -> PaymentQuoteResponse:
invoice_obj = decode(bolt11)
assert invoice_obj.amount_msat, "invoice has no amount."
amount_msat = int(invoice_obj.amount_msat)
fees_msat = fee_reserve(amount_msat)
fee_sat = math.ceil(fees_msat / 1000)
amount_sat = math.ceil(amount_msat / 1000)
return PaymentQuoteResponse(checking_id="", fee=fee_sat, amount=amount_sat)
4 changes: 2 additions & 2 deletions cashu/lightning/lnbits.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
from ..core.settings import settings
from .base import (
InvoiceResponse,
LightningWallet,
PaymentResponse,
PaymentStatus,
StatusResponse,
Wallet,
)


class LNbitsWallet(Wallet):
class LNbitsWallet(LightningWallet):
"""https://github.com/lnbits/lnbits"""

def __init__(self):
Expand Down
4 changes: 2 additions & 2 deletions cashu/lightning/lndrest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
from ..core.settings import settings
from .base import (
InvoiceResponse,
LightningWallet,
PaymentResponse,
PaymentStatus,
StatusResponse,
Wallet,
)
from .macaroon import load_macaroon


class LndRestWallet(Wallet):
class LndRestWallet(LightningWallet):
"""https://api.lightning.community/rest/index.html#lnd-rest-api-reference"""

def __init__(self):
Expand Down
Loading

0 comments on commit 47f83c1

Please sign in to comment.