Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fees #503

Merged
merged 37 commits into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6a3f910
wip
callebtc Feb 29, 2024
eb99379
Merge branch 'main' into add-fees
callebtc Mar 12, 2024
e95b74a
wip
callebtc Mar 12, 2024
9daa444
Merge branch 'main' into add-fees
callebtc Mar 17, 2024
0ee014e
model
callebtc Mar 20, 2024
ac8a307
Merge branch 'main' into add-fees
callebtc Mar 26, 2024
8958ac3
refactor wallet transactions
callebtc Mar 26, 2024
8eea896
refactor wallet
callebtc Mar 26, 2024
0b4b736
sending with fees works and outputs fill up the wallet
callebtc Mar 26, 2024
7301c75
wip work
callebtc Mar 27, 2024
e638102
ok
callebtc Mar 29, 2024
7aa6099
comments
callebtc Apr 9, 2024
72ff760
Merge branch 'main' into add-fees
callebtc Apr 10, 2024
cdc5908
Merge branch 'main' into add-fees
callebtc Apr 15, 2024
80fc53e
receive with amount=0
callebtc Apr 15, 2024
a0614fe
Merge branch 'main' into add-fees-merge-main
callebtc May 23, 2024
c50107c
correctly import postmeltrequest
callebtc May 23, 2024
ee4f4fb
fix melt amount
callebtc May 23, 2024
32fa497
tests working
callebtc May 24, 2024
281985d
remove mint_loaded decorator in deprecated wallet api
callebtc May 24, 2024
4049538
wallet works with units
callebtc May 24, 2024
3a8aa6c
refactor: melt_quote
callebtc May 24, 2024
ef43bd4
fix fees
callebtc May 24, 2024
1c455bd
add file
callebtc May 24, 2024
0fab554
fees for melt inputs
callebtc May 25, 2024
8b61d21
set default input fee for internal quotes to 0
callebtc May 25, 2024
abf3b6c
fix coinselect
callebtc May 25, 2024
da33d9f
coin selection working
callebtc May 25, 2024
6aefdea
yo
callebtc May 25, 2024
561c0cc
fix all tests
callebtc May 25, 2024
4197d6c
clean up
callebtc May 29, 2024
e360502
last commit added fees for inputs for melt transactions - this commit…
callebtc May 29, 2024
333b0da
fix fee return and melt quote max allowed amount check during creatio…
callebtc May 30, 2024
8652012
clean up code
callebtc May 30, 2024
701c09a
add tests for fees
callebtc Jun 1, 2024
866e2ab
add melt tests
callebtc Jun 1, 2024
237b212
update wallet fee information
callebtc Jun 1, 2024
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
321 changes: 32 additions & 289 deletions cashu/core/base.py

Large diffs are not rendered by default.

19 changes: 16 additions & 3 deletions cashu/core/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,18 @@ def __init__(self):
super().__init__(self.detail, code=self.code)


class TransactionNotBalancedError(TransactionError):
code = 11002

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


class SecretTooLongError(TransactionError):
detail = "secret too long"
code = 11003

def __init__(self):
super().__init__(self.detail, code=self.code)
def __init__(self, detail="secret too long"):
super().__init__(detail, code=self.code)


class NoSecretInProofsError(TransactionError):
Expand All @@ -51,6 +57,13 @@ def __init__(self):
super().__init__(self.detail, code=self.code)


class TransactionUnitError(TransactionError):
code = 11005

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


class KeysetError(CashuError):
detail = "keyset error"
code = 12000
Expand Down
13 changes: 12 additions & 1 deletion cashu/core/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,21 @@
from functools import partial, wraps
from typing import List

from ..core.base import BlindedSignature, Proof
from ..core.base import Amount, BlindedSignature, Proof, Unit
from ..core.settings import settings


def amount_summary(proofs: List[Proof], unit: Unit) -> str:
amounts_we_have = [
(amount, len([p for p in proofs if p.amount == amount]))
for amount in set([p.amount for p in proofs])
]
amounts_we_have.sort(key=lambda x: x[0])
return (
f"{', '.join([f'{Amount(unit, a).str()} ({c}x)' for a, c in amounts_we_have])}"
)


def sum_proofs(proofs: List[Proof]):
return sum([p.amount for p in proofs])

Expand Down
265 changes: 265 additions & 0 deletions cashu/core/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
from typing import Any, Dict, List, Optional, Union

from pydantic import BaseModel, Field

from .base import (
BlindedMessage,
BlindedMessage_Deprecated,
BlindedSignature,
Proof,
ProofState,
)
from .settings import settings

# ------- API -------

# ------- API: INFO -------


class MintMeltMethodSetting(BaseModel):
method: str
unit: str
min_amount: Optional[int] = None
max_amount: Optional[int] = None


class GetInfoResponse(BaseModel):
name: Optional[str] = None
pubkey: Optional[str] = None
version: Optional[str] = None
description: Optional[str] = None
description_long: Optional[str] = None
contact: Optional[List[List[str]]] = None
motd: Optional[str] = None
nuts: Optional[Dict[int, Any]] = None


class Nut15MppSupport(BaseModel):
method: str
unit: str
mpp: bool


class GetInfoResponse_deprecated(BaseModel):
name: Optional[str] = None
pubkey: Optional[str] = None
version: Optional[str] = None
description: Optional[str] = None
description_long: Optional[str] = None
contact: Optional[List[List[str]]] = None
nuts: Optional[List[str]] = None
motd: Optional[str] = None
parameter: Optional[dict] = None


# ------- API: KEYS -------


class KeysResponseKeyset(BaseModel):
id: str
unit: str
keys: Dict[int, str]


class KeysResponse(BaseModel):
keysets: List[KeysResponseKeyset]


class KeysetsResponseKeyset(BaseModel):
id: str
unit: str
active: bool
input_fee_ppk: Optional[int] = None


class KeysetsResponse(BaseModel):
keysets: list[KeysetsResponseKeyset]


class KeysResponse_deprecated(BaseModel):
__root__: Dict[str, str]


class KeysetsResponse_deprecated(BaseModel):
keysets: list[str]


# ------- API: MINT QUOTE -------


class PostMintQuoteRequest(BaseModel):
unit: str = Field(..., max_length=settings.mint_max_request_length) # output unit
amount: int = Field(..., gt=0) # output amount


class PostMintQuoteResponse(BaseModel):
quote: str # quote id
request: str # input payment request
paid: bool # whether the request has been paid
expiry: Optional[int] # expiry of the quote


# ------- API: MINT -------


class PostMintRequest(BaseModel):
quote: str = Field(..., max_length=settings.mint_max_request_length) # quote id
outputs: List[BlindedMessage] = Field(
..., max_items=settings.mint_max_request_length
)


class PostMintResponse(BaseModel):
signatures: List[BlindedSignature] = []


class GetMintResponse_deprecated(BaseModel):
pr: str
hash: str


class PostMintRequest_deprecated(BaseModel):
outputs: List[BlindedMessage_Deprecated] = Field(
..., max_items=settings.mint_max_request_length
)


class PostMintResponse_deprecated(BaseModel):
promises: List[BlindedSignature] = []


# ------- API: MELT QUOTE -------


class PostMeltQuoteRequest(BaseModel):
unit: str = Field(..., max_length=settings.mint_max_request_length) # input unit
request: str = Field(
..., max_length=settings.mint_max_request_length
) # output payment request
amount: Optional[int] = Field(default=None, gt=0) # input amount


class PostMeltQuoteResponse(BaseModel):
quote: str # quote id
amount: int # input amount
fee_reserve: int # input fee reserve
paid: bool # whether the request has been paid
expiry: Optional[int] # expiry of the quote


# ------- API: MELT -------


class PostMeltRequest(BaseModel):
quote: str = Field(..., max_length=settings.mint_max_request_length) # quote id
inputs: List[Proof] = Field(..., max_items=settings.mint_max_request_length)
outputs: Union[List[BlindedMessage], None] = Field(
None, max_items=settings.mint_max_request_length
)


class PostMeltResponse(BaseModel):
paid: Union[bool, None]
payment_preimage: Union[str, None]
change: Union[List[BlindedSignature], None] = None


class PostMeltRequest_deprecated(BaseModel):
proofs: List[Proof] = Field(..., max_items=settings.mint_max_request_length)
pr: str = Field(..., max_length=settings.mint_max_request_length)
outputs: Union[List[BlindedMessage_Deprecated], None] = Field(
None, max_items=settings.mint_max_request_length
)


class PostMeltResponse_deprecated(BaseModel):
paid: Union[bool, None]
preimage: Union[str, None]
change: Union[List[BlindedSignature], None] = None


# ------- API: SPLIT -------


class PostSplitRequest(BaseModel):
inputs: List[Proof] = Field(..., max_items=settings.mint_max_request_length)
outputs: List[BlindedMessage] = Field(
..., max_items=settings.mint_max_request_length
)


class PostSplitResponse(BaseModel):
signatures: List[BlindedSignature]


# deprecated since 0.13.0
class PostSplitRequest_Deprecated(BaseModel):
proofs: List[Proof] = Field(..., max_items=settings.mint_max_request_length)
amount: Optional[int] = None
outputs: List[BlindedMessage_Deprecated] = Field(
..., max_items=settings.mint_max_request_length
)


class PostSplitResponse_Deprecated(BaseModel):
promises: List[BlindedSignature] = []


class PostSplitResponse_Very_Deprecated(BaseModel):
fst: List[BlindedSignature] = []
snd: List[BlindedSignature] = []
deprecated: str = "The amount field is deprecated since 0.13.0"


# ------- API: CHECK -------


class PostCheckStateRequest(BaseModel):
Ys: List[str] = Field(..., max_items=settings.mint_max_request_length)


class PostCheckStateResponse(BaseModel):
states: List[ProofState] = []


class CheckSpendableRequest_deprecated(BaseModel):
proofs: List[Proof] = Field(..., max_items=settings.mint_max_request_length)


class CheckSpendableResponse_deprecated(BaseModel):
spendable: List[bool]
pending: List[bool]


class CheckFeesRequest_deprecated(BaseModel):
pr: str = Field(..., max_length=settings.mint_max_request_length)


class CheckFeesResponse_deprecated(BaseModel):
fee: Union[int, None]


# ------- API: RESTORE -------


class PostRestoreRequest(BaseModel):
outputs: List[BlindedMessage] = Field(
..., max_items=settings.mint_max_request_length
)


class PostRestoreRequest_Deprecated(BaseModel):
outputs: List[BlindedMessage_Deprecated] = Field(
..., max_items=settings.mint_max_request_length
)


class PostRestoreResponse(BaseModel):
outputs: List[BlindedMessage] = []
signatures: List[BlindedSignature] = []
promises: Optional[List[BlindedSignature]] = [] # deprecated since 0.15.1

# duplicate value of "signatures" for backwards compatibility with old clients < 0.15.1
def __init__(self, **data):
super().__init__(**data)
self.promises = self.signatures
5 changes: 5 additions & 0 deletions cashu/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class MintSettings(CashuSettings):

mint_database: str = Field(default="data/mint")
mint_test_database: str = Field(default="test_data/test_mint")
mint_max_secret_length: int = Field(default=512)

mint_input_fee_ppk: int = Field(default=0)


class MintBackends(MintSettings):
Expand Down Expand Up @@ -170,6 +173,8 @@ class WalletSettings(CashuSettings):
locktime_delta_seconds: int = Field(default=86400) # 1 day
proofs_batch_size: int = Field(default=1000)

wallet_target_amount_count: int = Field(default=3)


class LndRestFundingSource(MintSettings):
mint_lnd_rest_endpoint: Optional[str] = Field(default=None)
Expand Down
2 changes: 1 addition & 1 deletion cashu/lightning/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
from ..core.base import (
Amount,
MeltQuote,
PostMeltQuoteRequest,
Unit,
)
from ..core.models import PostMeltQuoteRequest


class StatusResponse(BaseModel):
Expand Down
3 changes: 2 additions & 1 deletion cashu/lightning/blink.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
)
from loguru import logger

from ..core.base import Amount, MeltQuote, PostMeltQuoteRequest, Unit
from ..core.base import Amount, MeltQuote, Unit
from ..core.models import PostMeltQuoteRequest
from ..core.settings import settings
from .base import (
InvoiceResponse,
Expand Down
3 changes: 2 additions & 1 deletion cashu/lightning/corelightningrest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
)
from loguru import logger

from ..core.base import Amount, MeltQuote, PostMeltQuoteRequest, Unit
from ..core.base import Amount, MeltQuote, Unit
from ..core.helpers import fee_reserve
from ..core.models import PostMeltQuoteRequest
from ..core.settings import settings
from .base import (
InvoiceResponse,
Expand Down
3 changes: 2 additions & 1 deletion cashu/lightning/fake.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
encode,
)

from ..core.base import Amount, MeltQuote, PostMeltQuoteRequest, Unit
from ..core.base import Amount, MeltQuote, Unit
from ..core.helpers import fee_reserve
from ..core.models import PostMeltQuoteRequest
from ..core.settings import settings
from .base import (
InvoiceResponse,
Expand Down
3 changes: 2 additions & 1 deletion cashu/lightning/lnbits.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
decode,
)

from ..core.base import Amount, MeltQuote, PostMeltQuoteRequest, Unit
from ..core.base import Amount, MeltQuote, Unit
from ..core.helpers import fee_reserve
from ..core.models import PostMeltQuoteRequest
from ..core.settings import settings
from .base import (
InvoiceResponse,
Expand Down
Loading
Loading