Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 68 additions & 19 deletions cashu/core/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,14 @@ def __init__(self, detail):


class SecretTooLongError(TransactionError):
code = 11003
code = 11000

def __init__(self, detail="secret too long"):
super().__init__(detail, code=self.code)
Comment thread
KvngMikey marked this conversation as resolved.


class WitnessTooLongError(TransactionError):
code = 11004
code = 11000

def __init__(self, detail="witness too long"):
super().__init__(detail, code=self.code)
Expand All @@ -96,13 +96,6 @@ def __init__(self):
super().__init__(self.detail, code=self.code)


class TransactionUnitError(TransactionError):
code = 11009

def __init__(self, detail):
super().__init__(detail, code=self.code)


class TransactionAmountExceedsLimitError(TransactionError):
code = 11006

Expand Down Expand Up @@ -142,6 +135,30 @@ def __init__(self, detail: Optional[str] = None):
super().__init__(detail, code=self.code)


class AmountlessInvoiceNotSupportedError(TransactionError):
detail = "Amountless invoice is not supported"
code = 11011

def __init__(self, detail: Optional[str] = None):
super().__init__(detail or self.detail, code=self.code)


class AmountMismatchError(TransactionError):
detail = "Amount in request does not equal invoice"
code = 11012

def __init__(self, detail: Optional[str] = None):
super().__init__(detail or self.detail, code=self.code)


class UnitNotSupportedError(TransactionError):
detail = "Unit in request is not supported"
code = 11013

def __init__(self, detail: Optional[str] = None):
super().__init__(detail or self.detail, code=self.code)


class BatchDuplicateQuotesError(TransactionError):
detail = "Duplicate quote IDs provided"
code = 11016
Expand Down Expand Up @@ -196,16 +213,24 @@ class QuoteNotPaidError(CashuError):
detail = "quote not paid"
code = 20001

def __init__(self):
super().__init__(self.detail, code=self.code)
def __init__(self, detail: Optional[str] = None):
super().__init__(detail or self.detail, code=self.code)


class QuoteAlreadyIssuedError(CashuError):
detail = "quote already issued"
code = 20002

def __init__(self):
super().__init__(self.detail, code=self.code)
def __init__(self, detail: Optional[str] = None):
super().__init__(detail or self.detail, code=self.code)


class MintingDisabledError(CashuError):
detail = "Minting is disabled"
code = 20003

def __init__(self, detail: Optional[str] = None):
super().__init__(detail or self.detail, code=self.code)


class LightningPaymentFailedError(CashuError):
Expand All @@ -216,6 +241,30 @@ def __init__(self, detail: Optional[str] = None):
super().__init__(detail or self.detail, code=self.code)


class QuotePendingError(CashuError):
detail = "quote is pending"
code = 20005

def __init__(self, detail: Optional[str] = None):
super().__init__(detail or self.detail, code=self.code)


class InvoiceAlreadyPaidError(CashuError):
detail = "invoice already paid"
code = 20006

def __init__(self, detail: Optional[str] = None):
super().__init__(detail or self.detail, code=self.code)


class QuoteExpiredError(CashuError):
detail = "quote is expired"
code = 20007

def __init__(self, detail: Optional[str] = None):
super().__init__(detail or self.detail, code=self.code)


class QuoteSignatureInvalidError(CashuError):
detail = "Signature for mint request invalid"
code = 20008
Expand All @@ -234,47 +283,47 @@ def __init__(self):

class ClearAuthRequiredError(CashuError):
detail = "Endpoint requires clear auth"
code = 80001
code = 30001

def __init__(self):
super().__init__(self.detail, code=self.code)


class ClearAuthFailedError(CashuError):
detail = "Clear authentication failed"
code = 80002
code = 30002

def __init__(self):
super().__init__(self.detail, code=self.code)


class BlindAuthRequiredError(CashuError):
detail = "Endpoint requires blind auth"
code = 81001
code = 31001

def __init__(self):
super().__init__(self.detail, code=self.code)


class BlindAuthFailedError(CashuError):
detail = "Blind authentication failed"
code = 81002
code = 31002

def __init__(self):
super().__init__(self.detail, code=self.code)


class BlindAuthAmountExceededError(CashuError):
detail = "Maximum blind auth amount exceeded"
code = 81003
code = 31003

def __init__(self, detail: Optional[str] = None):
super().__init__(detail or self.detail, code=self.code)


class BlindAuthRateLimitExceededError(CashuError):
detail = "Blind auth token mint rate limit exceeded"
code = 81004
code = 31004

def __init__(self):
super().__init__(self.detail, code=self.code)
38 changes: 19 additions & 19 deletions cashu/mint/db/write.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
)
from ...core.db import Connection, Database
from ...core.errors import (
InvoiceAlreadyPaidError,
ProofsArePendingError,
QuoteAlreadyIssuedError,
QuoteNotPaidError,
QuotePendingError,
TransactionError,
)
from ..crud import LedgerCrud
Expand Down Expand Up @@ -171,9 +175,9 @@ async def _set_mint_quote_pending(self, quote_id: str) -> MintQuote:
if not quote:
raise TransactionError("Mint quote not found.")
if quote.pending:
raise TransactionError("Mint quote already pending.")
raise QuotePendingError("Mint quote already pending.")
if not quote.paid:
raise TransactionError("Mint quote is not paid yet.")
raise QuoteNotPaidError("Mint quote is not paid yet.")
Comment thread
KvngMikey marked this conversation as resolved.
# set the quote as pending
self._set_mint_quote_state(quote, MintQuoteState.pending)
logger.trace(f"crud: setting quote {quote_id} as PENDING")
Expand Down Expand Up @@ -213,11 +217,13 @@ async def _set_mint_quotes_pending(self, quote_ids: List[str]) -> List[MintQuote
if not quote:
raise TransactionError(f"Mint quote {quote_id} not found.")
if quote.pending:
raise TransactionError(f"Mint quote {quote_id} already pending.")
raise QuotePendingError(f"Mint quote {quote_id} already pending.")
if quote.issued:
raise TransactionError(f"Mint quote {quote_id} is already issued.")
raise QuoteAlreadyIssuedError(
f"Mint quote {quote_id} is already issued."
)
if not quote.paid:
raise TransactionError(f"Mint quote {quote_id} is not paid yet.")
raise QuoteNotPaidError(f"Mint quote {quote_id} is not paid yet.")

# set the quote as pending
self._set_mint_quote_state(quote, MintQuoteState.pending)
Expand Down Expand Up @@ -330,13 +336,10 @@ async def _set_melt_quote_pending(
)
if len(quotes_db) == 0:
raise TransactionError("Melt quote not found.")
if any(
[
quote.state in [MeltQuoteState.pending, MeltQuoteState.paid]
for quote in quotes_db
]
):
raise TransactionError("Melt quote already paid or pending.")
if any([quote.state == MeltQuoteState.paid for quote in quotes_db]):
raise InvoiceAlreadyPaidError("Melt quote already paid or pending.")
if any([quote.state == MeltQuoteState.pending for quote in quotes_db]):
raise QuotePendingError("Melt quote already paid or pending.")
Comment thread
KvngMikey marked this conversation as resolved.
Outdated
# set the quote as pending
quote_copy.state = MeltQuoteState.pending
await self.crud.update_melt_quote(quote=quote_copy, db=self.db, conn=conn)
Expand Down Expand Up @@ -441,13 +444,10 @@ async def _store_melt_quote(self, quote: MeltQuote):
quotes_db = await self.crud.get_melt_quotes_by_checking_id(
checking_id=quote.checking_id, db=self.db, conn=conn
)
if any(
[
quote.state in [MeltQuoteState.pending, MeltQuoteState.paid]
for quote in quotes_db
]
):
raise TransactionError("Melt quote already paid or pending.")
if any([quote.state == MeltQuoteState.paid for quote in quotes_db]):
raise InvoiceAlreadyPaidError("Melt quote already paid or pending.")
if any([quote.state == MeltQuoteState.pending for quote in quotes_db]):
raise QuotePendingError("Melt quote already paid or pending.")

# store the melt quote
await self.crud.store_melt_quote(quote=quote, db=self.db, conn=conn)
Expand Down
30 changes: 18 additions & 12 deletions cashu/mint/ledger.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,20 @@
from ..core.crypto.secp import PrivateKey, PublicKey
from ..core.db import Connection, Database
from ..core.errors import (
AmountlessInvoiceNotSupportedError,
AmountMismatchError,
BatchDuplicateQuotesError,
CashuError,
InvoiceAlreadyPaidError,
KeysetInactiveError,
LightningError,
LightningPaymentFailedError,
MintingDisabledError,
NotAllowedError,
QuoteAlreadyIssuedError,
QuoteExpiredError,
QuoteNotPaidError,
QuotePendingError,
QuoteSignatureInvalidError,
TransactionAmountExceedsLimitError,
TransactionError,
Expand Down Expand Up @@ -329,7 +335,7 @@ async def mint_quote(self, quote_request: PostMintQuoteRequest) -> MintQuote:
f"Maximum mint amount is {settings.mint_max_mint_bolt11_sat} sat."
)
if settings.mint_bolt11_disable_mint:
raise NotAllowedError("Minting with bolt11 is disabled.")
raise MintingDisabledError("Minting with bolt11 is disabled.")

unit, method = self._verify_and_get_unit_method(
quote_request.unit, Method.bolt11.name
Expand Down Expand Up @@ -510,7 +516,7 @@ async def mint(

quote = await self.get_mint_quote(quote_id)
if quote.pending:
raise TransactionError("Mint quote already pending.")
raise QuotePendingError("Mint quote already pending.")
if quote.issued:
raise QuoteAlreadyIssuedError()
if quote.state != MintQuoteState.paid:
Expand All @@ -524,7 +530,7 @@ async def mint(
if not quote.amount == sum_amount_outputs:
raise TransactionError("amount to mint does not match quote amount")
if quote.expiry and quote.expiry < int(time.time()):
raise TransactionError("quote expired")
raise QuoteExpiredError("quote expired")
if not self._verify_mint_quote_witness(quote, outputs, signature):
raise QuoteSignatureInvalidError()
await self._store_blinded_messages(outputs, mint_id=quote_id)
Expand Down Expand Up @@ -595,7 +601,7 @@ async def mint_batch(

for quote in quotes:
if quote.pending:
raise TransactionError("mint quote already pending")
raise QuotePendingError("mint quote already pending")
if quote.issued:
raise QuoteAlreadyIssuedError()
if quote.state != MintQuoteState.paid:
Expand Down Expand Up @@ -646,7 +652,7 @@ async def mint_batch(
try:
for quote in quotes:
if quote.expiry and quote.expiry < int(time.time()):
raise TransactionError("quote expired")
raise QuoteExpiredError("quote expired")

# Store all blinded messages
await self._store_blinded_messages(
Expand Down Expand Up @@ -685,7 +691,7 @@ def create_internal_melt_quote(
if not mint_quote.method == method.name:
raise TransactionError("methods do not match")
if mint_quote.paid:
raise TransactionError("mint quote already paid")
raise InvoiceAlreadyPaidError("mint quote already paid")
Comment thread
KvngMikey marked this conversation as resolved.
if mint_quote.issued:
raise TransactionError("mint quote already issued")
if not mint_quote.unpaid:
Expand Down Expand Up @@ -728,7 +734,7 @@ def validate_payment_quote(
logger.error(
f"expected {payment_quote.amount.to(Unit.msat).amount} msat but got {melt_quote.mpp_amount}"
)
raise TransactionError("quote amount not as requested")
raise AmountMismatchError("quote amount not as requested")
# make sure the backend returned the amount with a correct unit
if not payment_quote.amount.unit == unit:
raise TransactionError("payment quote amount units do not match")
Expand Down Expand Up @@ -798,7 +804,7 @@ async def melt_quote(
# support only the bol11 method for now.
invoice_obj = bolt11.decode(melt_quote.request)
if not invoice_obj.amount_msat:
raise TransactionError("invoice has no amount.")
raise AmountlessInvoiceNotSupportedError("invoice has no amount.")
# we set the expiry of this quote to the expiry of the bolt11 invoice
now = int(time.time())
expiry = None
Expand Down Expand Up @@ -979,23 +985,23 @@ async def melt_mint_settle_internally(

# we settle the transaction internally
if melt_quote.state == MeltQuoteState.paid:
raise TransactionError("melt quote already paid")
raise InvoiceAlreadyPaidError("melt quote already paid")

# verify amounts from bolt11 invoice
bolt11_request = melt_quote.request
invoice_obj = bolt11.decode(bolt11_request)

if not invoice_obj.amount_msat:
raise TransactionError("invoice has no amount.")
raise AmountlessInvoiceNotSupportedError("invoice has no amount.")
if not mint_quote.amount == melt_quote.amount:
raise TransactionError("amounts do not match")
raise AmountMismatchError("amounts do not match")
if not bolt11_request == mint_quote.request:
raise TransactionError("bolt11 requests do not match")
if not mint_quote.method == melt_quote.method:
raise TransactionError("methods do not match")

if mint_quote.paid:
raise TransactionError("mint quote already paid")
raise InvoiceAlreadyPaidError("mint quote already paid")
if mint_quote.issued:
raise TransactionError("mint quote already issued")

Expand Down
Loading
Loading