mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-22 11:24:19 +01:00
Mint Management gRPC Server (#723)
* settings * fix name settings * management rpc * hook up the RPC server * working * format * update build script fix import error * remove accidental commit of vscode extension data * working ✔ * \n * add get mint quote get melt quote * gRPC cli update quotes commands * update mint melt quotes from cli * comment under get cli command group * keyset rotation not yet implemented * try fix * change back contact info default to be empty list * fix import * add server mTLS * ll * script for generating certificates * rename settings * move generation script * do not save TTL expiry into Cache object, rather always load from settings. * update lightning fees * update auth limits * auth rate limit cli * optional arguemnts * better error messages * tests for db update mint/melt quotes * start mint rpc tests * add tos_url field to get-info grpc response * format checks * add types to click groups where it's needed * tests on updating quotes * fix tests * skip updating mint quote state if on regtest * test edge case * unified test_add_remove_contact * mark pytest-asyncio * fix missing db argument * hopefully no more silly errors * fix test_db_update_mint_quote_state * pass in the quote id string. * add keyset rotation * test for keyset rotation through gRPC command * fix logger warning * remove rotation test because it breaks other tests * use different bolt11 invoices * assert returned melt quote has quote * is_postgres * try different things * skip if deprecated api * format checks * update .gitignore * default location for certificates
This commit is contained in:
@@ -117,6 +117,15 @@ LIGHTNING_FEE_PERCENT=1.0
|
|||||||
# minimum fee to reserve
|
# minimum fee to reserve
|
||||||
LIGHTNING_RESERVE_FEE_MIN=2000
|
LIGHTNING_RESERVE_FEE_MIN=2000
|
||||||
|
|
||||||
|
# Mint Management gRPC service configurations
|
||||||
|
MINT_RPC_SERVER_ENABLE=FALSE
|
||||||
|
MINT_RPC_SERVER_ADDR=localhost
|
||||||
|
MINT_RPC_SERVER_PORT=8086
|
||||||
|
MINT_RPC_SERVER_MUTUAL_TLS=TRUE
|
||||||
|
MINT_RPC_SERVER_KEY="./server_private.pem"
|
||||||
|
MINT_RPC_SERVER_CERT="./server_cert.pem"
|
||||||
|
MINT_RPC_SERVER_CA="./ca_cert.pem"
|
||||||
|
|
||||||
# Limits
|
# Limits
|
||||||
# Max mint balance in satoshis
|
# Max mint balance in satoshis
|
||||||
# MINT_MAX_BALANCE=1000000
|
# MINT_MAX_BALANCE=1000000
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -137,3 +137,7 @@ tor.pid
|
|||||||
|
|
||||||
# MacOS
|
# MacOS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.aider*
|
||||||
|
|
||||||
|
# PEM certs
|
||||||
|
*.pem
|
||||||
@@ -18,6 +18,7 @@ class MintInfo(BaseModel):
|
|||||||
contact: Optional[List[MintInfoContact]]
|
contact: Optional[List[MintInfoContact]]
|
||||||
motd: Optional[str]
|
motd: Optional[str]
|
||||||
icon_url: Optional[str]
|
icon_url: Optional[str]
|
||||||
|
urls: Optional[List[str]]
|
||||||
tos_url: Optional[str]
|
tos_url: Optional[str]
|
||||||
time: Optional[int]
|
time: Optional[int]
|
||||||
nuts: Dict[int, Any]
|
nuts: Dict[int, Any]
|
||||||
|
|||||||
@@ -203,6 +203,14 @@ class MintInformation(CashuSettings):
|
|||||||
mint_info_urls: List[str] = Field(default=None)
|
mint_info_urls: List[str] = Field(default=None)
|
||||||
mint_info_tos_url: str = Field(default=None)
|
mint_info_tos_url: str = Field(default=None)
|
||||||
|
|
||||||
|
class MintManagementRPCSettings(MintSettings):
|
||||||
|
mint_rpc_server_enable: bool = Field(default=False)
|
||||||
|
mint_rpc_server_ca: str = Field(default=None)
|
||||||
|
mint_rpc_server_cert: str = Field(default=None)
|
||||||
|
mint_rpc_server_key: str = Field(default=None)
|
||||||
|
mint_rpc_server_addr: str = Field(default="localhost")
|
||||||
|
mint_rpc_server_port: int = Field(default=8086)
|
||||||
|
mint_rpc_server_mutual_tls: bool = Field(default=True)
|
||||||
|
|
||||||
class WalletSettings(CashuSettings):
|
class WalletSettings(CashuSettings):
|
||||||
tor: bool = Field(default=False)
|
tor: bool = Field(default=False)
|
||||||
@@ -320,6 +328,7 @@ class Settings(
|
|||||||
AuthSettings,
|
AuthSettings,
|
||||||
MintRedisCache,
|
MintRedisCache,
|
||||||
MintDeprecationFlags,
|
MintDeprecationFlags,
|
||||||
|
MintManagementRPCSettings,
|
||||||
MintWatchdogSettings,
|
MintWatchdogSettings,
|
||||||
MintSettings,
|
MintSettings,
|
||||||
MintInformation,
|
MintInformation,
|
||||||
|
|||||||
@@ -16,7 +16,13 @@ from ..core.settings import settings
|
|||||||
from .auth.router import auth_router
|
from .auth.router import auth_router
|
||||||
from .router import redis, router
|
from .router import redis, router
|
||||||
from .router_deprecated import router_deprecated
|
from .router_deprecated import router_deprecated
|
||||||
from .startup import shutdown_mint, start_auth, start_mint
|
from .startup import (
|
||||||
|
shutdown_management_rpc,
|
||||||
|
shutdown_mint,
|
||||||
|
start_auth,
|
||||||
|
start_management_rpc,
|
||||||
|
start_mint,
|
||||||
|
)
|
||||||
|
|
||||||
if settings.debug_profiling:
|
if settings.debug_profiling:
|
||||||
pass
|
pass
|
||||||
@@ -32,6 +38,8 @@ async def lifespan(_: FastAPI) -> AsyncIterator[None]:
|
|||||||
await start_mint()
|
await start_mint()
|
||||||
if settings.mint_require_auth:
|
if settings.mint_require_auth:
|
||||||
await start_auth()
|
await start_auth()
|
||||||
|
if settings.mint_rpc_server_enable:
|
||||||
|
await start_management_rpc()
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
@@ -39,10 +47,11 @@ async def lifespan(_: FastAPI) -> AsyncIterator[None]:
|
|||||||
logger.info("Shutdown process interrupted by CancelledError")
|
logger.info("Shutdown process interrupted by CancelledError")
|
||||||
finally:
|
finally:
|
||||||
try:
|
try:
|
||||||
|
await shutdown_management_rpc()
|
||||||
await redis.disconnect()
|
await redis.disconnect()
|
||||||
await shutdown_mint()
|
await shutdown_mint()
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
logger.info("CancelledError during shutdown, shutting down forcefully")
|
logger.error("CancelledError during shutdown, shutting down forcefully")
|
||||||
|
|
||||||
|
|
||||||
def create_app(config_object="core.settings") -> FastAPI:
|
def create_app(config_object="core.settings") -> FastAPI:
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ from ..core.settings import settings
|
|||||||
|
|
||||||
class RedisCache:
|
class RedisCache:
|
||||||
initialized = False
|
initialized = False
|
||||||
expiry = settings.mint_redis_cache_ttl
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
if settings.mint_redis_cache_enabled:
|
if settings.mint_redis_cache_enabled:
|
||||||
@@ -58,7 +57,7 @@ class RedisCache:
|
|||||||
else:
|
else:
|
||||||
raise Exception(f"Found no cached response for key {key}")
|
raise Exception(f"Found no cached response for key {key}")
|
||||||
result = await func(request, payload)
|
result = await func(request, payload)
|
||||||
await self.redis.set(name=key, value=result.json(), ex=self.expiry)
|
await self.redis.set(name=key, value=result.json(), ex=settings.mint_redis_cache_ttl)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|||||||
@@ -256,3 +256,23 @@ class DbWriteHelper:
|
|||||||
|
|
||||||
await self.events.submit(quote_copy)
|
await self.events.submit(quote_copy)
|
||||||
return quote_copy
|
return quote_copy
|
||||||
|
|
||||||
|
async def _update_mint_quote_state(
|
||||||
|
self, quote_id: str, state: MintQuoteState
|
||||||
|
):
|
||||||
|
async with self.db.get_connection(lock_table="mint_quotes") as conn:
|
||||||
|
mint_quote = await self.crud.get_mint_quote(quote_id=quote_id, db=self.db, conn=conn)
|
||||||
|
if not mint_quote:
|
||||||
|
raise TransactionError("Mint quote not found.")
|
||||||
|
mint_quote.state = state
|
||||||
|
await self.crud.update_mint_quote(quote=mint_quote, db=self.db, conn=conn)
|
||||||
|
|
||||||
|
async def _update_melt_quote_state(
|
||||||
|
self, quote_id: str, state: MeltQuoteState,
|
||||||
|
):
|
||||||
|
async with self.db.get_connection(lock_table="melt_quotes") as conn:
|
||||||
|
melt_quote = await self.crud.get_melt_quote(quote_id=quote_id, db=self.db, conn=conn)
|
||||||
|
if not melt_quote:
|
||||||
|
raise TransactionError("Melt quote not found.")
|
||||||
|
melt_quote.state = state
|
||||||
|
await self.crud.update_melt_quote(quote=melt_quote, db=self.db, conn=conn)
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ class LedgerFeatures(SupportsBackends, SupportsPubkey):
|
|||||||
contact=contact_info,
|
contact=contact_info,
|
||||||
nuts=self.mint_features,
|
nuts=self.mint_features,
|
||||||
icon_url=settings.mint_info_icon_url,
|
icon_url=settings.mint_info_icon_url,
|
||||||
|
urls=settings.mint_info_urls,
|
||||||
tos_url=settings.mint_info_tos_url,
|
tos_url=settings.mint_info_tos_url,
|
||||||
motd=settings.mint_info_motd,
|
motd=settings.mint_info_motd,
|
||||||
time=None,
|
time=None,
|
||||||
|
|||||||
@@ -35,7 +35,10 @@ class LedgerKeysets(SupportsKeysets, SupportsSeed, SupportsDb):
|
|||||||
return derivation_path
|
return derivation_path
|
||||||
|
|
||||||
async def rotate_next_keyset(
|
async def rotate_next_keyset(
|
||||||
self, unit: Unit, max_order: Optional[int], input_fee_ppk: Optional[int]
|
self,
|
||||||
|
unit: Unit,
|
||||||
|
max_order: Optional[int] = None,
|
||||||
|
input_fee_ppk: Optional[int] = None,
|
||||||
) -> MintKeyset:
|
) -> MintKeyset:
|
||||||
"""
|
"""
|
||||||
This function:
|
This function:
|
||||||
@@ -93,6 +96,7 @@ class LedgerKeysets(SupportsKeysets, SupportsSeed, SupportsDb):
|
|||||||
seed=self.seed,
|
seed=self.seed,
|
||||||
amounts=amounts,
|
amounts=amounts,
|
||||||
input_fee_ppk=input_fee_ppk,
|
input_fee_ppk=input_fee_ppk,
|
||||||
|
active=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.debug(f"New keyset was generated with Id {new_keyset.id}. Saving...")
|
logger.debug(f"New keyset was generated with Id {new_keyset.id}. Saving...")
|
||||||
|
|||||||
0
cashu/mint/management_rpc/__init__.py
Normal file
0
cashu/mint/management_rpc/__init__.py
Normal file
0
cashu/mint/management_rpc/cli/__init__.py
Normal file
0
cashu/mint/management_rpc/cli/__init__.py
Normal file
328
cashu/mint/management_rpc/cli/cli.py
Normal file
328
cashu/mint/management_rpc/cli/cli.py
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
import os
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import click
|
||||||
|
import grpc
|
||||||
|
from click import Context
|
||||||
|
|
||||||
|
from cashu.mint.management_rpc.protos import management_pb2, management_pb2_grpc
|
||||||
|
|
||||||
|
|
||||||
|
class NaturalOrderGroup(click.Group):
|
||||||
|
"""For listing commands in help in order of definition"""
|
||||||
|
|
||||||
|
def list_commands(self, ctx):
|
||||||
|
return self.commands.keys()
|
||||||
|
|
||||||
|
'''
|
||||||
|
# https://github.com/pallets/click/issues/85#issuecomment-503464628
|
||||||
|
def coro(f):
|
||||||
|
@wraps(f)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
return asyncio.run(f(*args, **kwargs))
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
'''
|
||||||
|
|
||||||
|
@click.group(cls=NaturalOrderGroup)
|
||||||
|
@click.option(
|
||||||
|
"--host",
|
||||||
|
"-h",
|
||||||
|
default="localhost",
|
||||||
|
help="Mint address."
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
"--port",
|
||||||
|
"-p",
|
||||||
|
default=8086,
|
||||||
|
help="Mint gRPC port."
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
"--insecure",
|
||||||
|
"-i",
|
||||||
|
is_flag=True,
|
||||||
|
default=False,
|
||||||
|
help="Connect without mutual TLS."
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
"--ca-cert-path",
|
||||||
|
"-ca",
|
||||||
|
default="./ca_cert.pem",
|
||||||
|
help="path to the Certificate Authority (CA) certificate file."
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
"--client-key-path",
|
||||||
|
"-k",
|
||||||
|
default="./client_private.pem",
|
||||||
|
help="path to the client's TLS key file."
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
"--client-cert-path",
|
||||||
|
"-c",
|
||||||
|
default="./client_cert.pem",
|
||||||
|
help="path to the client's TLS certificate file."
|
||||||
|
)
|
||||||
|
@click.pass_context
|
||||||
|
def cli(
|
||||||
|
ctx: Context,
|
||||||
|
host: str,
|
||||||
|
port: int,
|
||||||
|
insecure: bool,
|
||||||
|
ca_cert_path: str,
|
||||||
|
client_key_path: str,
|
||||||
|
client_cert_path: str,
|
||||||
|
):
|
||||||
|
ctx.ensure_object(dict)
|
||||||
|
if not insecure:
|
||||||
|
# Verify the existence of the paths
|
||||||
|
for (what, path) in [("CA certificate", ca_cert_path), ("client key", client_key_path), ("client certificate", client_cert_path)]:
|
||||||
|
if not path or not os.path.exists(path):
|
||||||
|
click.echo(f"Error: Couldn't get {what}. The path '{path}' does not exist.", err=True)
|
||||||
|
ctx.exit(1)
|
||||||
|
|
||||||
|
with open(client_key_path, "rb") as key_file, open(client_cert_path, "rb") as cert_file, open(ca_cert_path, "rb") as ca_file:
|
||||||
|
credentials = grpc.ssl_channel_credentials(
|
||||||
|
root_certificates=ca_file.read(),
|
||||||
|
private_key=key_file.read(),
|
||||||
|
certificate_chain=cert_file.read()
|
||||||
|
)
|
||||||
|
|
||||||
|
channel = grpc.secure_channel(f"{host}:{port}", credentials)
|
||||||
|
ctx.obj['STUB'] = management_pb2_grpc.MintStub(channel)
|
||||||
|
else:
|
||||||
|
channel = grpc.insecure_channel(f"{host}:{port}")
|
||||||
|
ctx.obj['STUB'] = management_pb2_grpc.MintStub(channel)
|
||||||
|
|
||||||
|
@cli.command("get-info", help="Get Mint info")
|
||||||
|
@click.pass_context
|
||||||
|
def get_info(ctx: Context):
|
||||||
|
"""Fetch server information"""
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
response = stub.GetInfo(management_pb2.GetInfoRequest())
|
||||||
|
click.echo(f"Mint Info:\n{response}")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@cli.group()
|
||||||
|
@click.pass_context
|
||||||
|
def update(ctx: Context):
|
||||||
|
"""Update server information"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@update.command("motd", help="Set the message of the day.")
|
||||||
|
@click.argument("motd")
|
||||||
|
@click.pass_context
|
||||||
|
def update_motd(ctx: Context, motd: str):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.UpdateMotd(management_pb2.UpdateMotdRequest(motd=motd))
|
||||||
|
click.echo("Motd successfully updated!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@update.command("description", help="Update the short description.")
|
||||||
|
@click.argument("description")
|
||||||
|
@click.pass_context
|
||||||
|
def update_short_description(ctx: Context, description: str):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.UpdateShortDescription(management_pb2.UpdateDescriptionRequest(description=description))
|
||||||
|
click.echo("Short description successfully updated!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@update.command("long-description", help="Update the long description.")
|
||||||
|
@click.argument("description")
|
||||||
|
@click.pass_context
|
||||||
|
def update_long_description(ctx: Context, description: str):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.UpdateLongDescription(management_pb2.UpdateDescriptionRequest(description=description))
|
||||||
|
click.echo("Long description successfully updated!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@update.command("icon-url", help="Update the icon url.")
|
||||||
|
@click.argument("url")
|
||||||
|
@click.pass_context
|
||||||
|
def update_icon_url(ctx: Context, url: str):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.UpdateLongDescription(management_pb2.UpdateIconUrlRequest(icon_url=url))
|
||||||
|
click.echo("Icon url successfully updated!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@update.command("name", help="Set the Mint's name.")
|
||||||
|
@click.argument("name")
|
||||||
|
@click.pass_context
|
||||||
|
def update_name(ctx: Context, name: str):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.UpdateName(management_pb2.UpdateNameRequest(name=name))
|
||||||
|
click.echo("Name successfully updated!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@update.group()
|
||||||
|
@click.pass_context
|
||||||
|
def url(ctx: Context):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@url.command("add", help="Add a new URL for this Mint.")
|
||||||
|
@click.argument("url")
|
||||||
|
@click.pass_context
|
||||||
|
def add_mint_url(ctx: Context, url: str):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.AddUrl(management_pb2.UpdateUrlRequest(url=url))
|
||||||
|
click.echo("Url successfully added!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@url.command("remove", help="Remove a URL of this Mint.")
|
||||||
|
@click.argument("url")
|
||||||
|
@click.pass_context
|
||||||
|
def remove_mint_url(ctx: Context, url: str):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.RemoveUrl(management_pb2.UpdateUrlRequest(url=url))
|
||||||
|
click.echo("Url successfully removed!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@update.group()
|
||||||
|
@click.pass_context
|
||||||
|
def contact(context: Context):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@contact.command("add", help="Add contact information.")
|
||||||
|
@click.argument("method")
|
||||||
|
@click.argument("info")
|
||||||
|
@click.pass_context
|
||||||
|
def add_contact(ctx: Context, method: str, info: str):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.AddContact(management_pb2.UpdateContactRequest(method=method, info=info))
|
||||||
|
click.echo("Contact successfully added!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@contact.command("remove", help="Remove contact information.")
|
||||||
|
@click.argument("method")
|
||||||
|
@click.pass_context
|
||||||
|
def remove_contact(ctx: Context, method: str):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.RemoveContact(management_pb2.UpdateContactRequest(method=method, info=""))
|
||||||
|
click.echo("Contact successfully removed!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@update.command("mint-quote", help="Set the state for a specific mint quote")
|
||||||
|
@click.argument("quote_id")
|
||||||
|
@click.argument("state")
|
||||||
|
@click.pass_context
|
||||||
|
def update_mint_quote(ctx: Context, quote_id: str, state: str):
|
||||||
|
allowed_states = ["PENDING", "UNPAID", "PAID", "ISSUED"]
|
||||||
|
if state not in allowed_states:
|
||||||
|
click.echo(f"state must be one of: {allowed_states}", err=True)
|
||||||
|
ctx.exit(1)
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.UpdateNut04Quote(management_pb2.UpdateQuoteRequest(quote_id=quote_id, state=state))
|
||||||
|
click.echo("Successfully updated!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@update.command("melt-quote", help="Set the state for a specific melt quote.")
|
||||||
|
@click.argument("quote_id")
|
||||||
|
@click.argument("state")
|
||||||
|
@click.pass_context
|
||||||
|
def update_melt_quote(ctx: Context, quote_id: str, state: str):
|
||||||
|
allowed_states = ["PENDING", "UNPAID", "PAID"]
|
||||||
|
if state not in allowed_states:
|
||||||
|
click.echo(f"State must be one of: {allowed_states}", err=True)
|
||||||
|
ctx.exit(1)
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.UpdateNut05Quote(management_pb2.UpdateQuoteRequest(quote_id=quote_id, state=state))
|
||||||
|
click.echo("Successfully updated!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@update.command("lightning-fee", help="Set new lightning fees.")
|
||||||
|
@click.argument("fee_percent", required=False, type=float)
|
||||||
|
@click.argument("min_fee_reserve", required=False, type=int)
|
||||||
|
@click.pass_context
|
||||||
|
def update_lightning_fee(ctx: Context, fee_percent: Optional[float], min_fee_reserve: Optional[int]):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.UpdateLightningFee(management_pb2.UpdateLightningFeeRequest(
|
||||||
|
fee_percent=fee_percent,
|
||||||
|
fee_min_reserve=min_fee_reserve,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
click.echo("Lightning fee successfully updated!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@update.command("auth", help="Set the limits for auth requests")
|
||||||
|
@click.argument("rate_limit_per_minute", required=False, type=int)
|
||||||
|
@click.argument("max_tokens_per_request", required=False, type=int)
|
||||||
|
@click.pass_context
|
||||||
|
def update_auth_limits(ctx: Context, rate_limit_per_minute: Optional[int], max_tokens_per_request: Optional[int]):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
stub.UpdateAuthLimits(
|
||||||
|
management_pb2.UpdateAuthLimitsRequest(
|
||||||
|
auth_rate_limit_per_minute=rate_limit_per_minute,
|
||||||
|
auth_max_blind_tokens=max_tokens_per_request,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
click.echo("Rate limit per minute successfully updated!")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@cli.group()
|
||||||
|
@click.pass_context
|
||||||
|
def get(ctx: Context):
|
||||||
|
"""Get mint information"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@get.command("mint-quote", help="Get a mint quote by id.")
|
||||||
|
@click.argument("quote_id")
|
||||||
|
@click.pass_context
|
||||||
|
def get_mint_quote(ctx: Context, quote_id: str):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
mint_quote = stub.GetNut04Quote(management_pb2.GetNut04QuoteRequest(quote_id=quote_id))
|
||||||
|
click.echo(f"mint quote:\n{mint_quote}")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
@get.command("melt-quote", help="Get a melt quote by id.")
|
||||||
|
@click.argument("quote_id")
|
||||||
|
@click.pass_context
|
||||||
|
def get_melt_quote(ctx: Context, quote_id: str):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
melt_quote = stub.GetNut05Quote(management_pb2.GetNut05QuoteRequest(quote_id=quote_id))
|
||||||
|
click.echo(f"melt quote:\n{melt_quote}")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command("next-keyset", help="Rotate to the next keyset for the specified unit.")
|
||||||
|
@click.argument("unit")
|
||||||
|
@click.argument("input_fee_ppk", required=False, type=int)
|
||||||
|
@click.argument("max_order", required=False, type=int)
|
||||||
|
@click.pass_context
|
||||||
|
def rotate_next_keyset(ctx: Context, unit: str, input_fee_ppk: Optional[int], max_order: Optional[int]):
|
||||||
|
stub = ctx.obj['STUB']
|
||||||
|
try:
|
||||||
|
keyset = stub.RotateNextKeyset(management_pb2.RotateNextKeysetRequest(unit=unit, max_order=max_order, input_fee_ppk=input_fee_ppk))
|
||||||
|
click.echo(f"New keyset successfully created:\n{keyset.id = }\n{keyset.unit = }\n{keyset.max_order = }\n{keyset.input_fee_ppk = }")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
click.echo(f"Error: {e.details()}", err=True)
|
||||||
30
cashu/mint/management_rpc/generate_certificates.sh
Executable file
30
cashu/mint/management_rpc/generate_certificates.sh
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "*** WARNING: this script is only to be used for development/testing purposes! ***"
|
||||||
|
sleep 2
|
||||||
|
echo -n "Continue? [Y/n]: "
|
||||||
|
read -r response
|
||||||
|
if [[ "$response" =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Continuing..."
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Generating CA certificate..."
|
||||||
|
openssl genpkey -algorithm RSA -out ca_private.pem
|
||||||
|
openssl req -x509 -new -key ca_private.pem -sha256 -days 365 -out ca_cert.pem -subj "/CN=cashuCA"
|
||||||
|
|
||||||
|
echo "Generating server certificate"
|
||||||
|
openssl genpkey -algorithm RSA -out server_private.pem
|
||||||
|
openssl req -new -key server_private.pem -out server.csr -subj "/CN=localhost"
|
||||||
|
openssl x509 -req -in server.csr -CA ca_cert.pem -CAkey ca_private.pem -CAcreateserial -out server_cert.pem -days 365 -sha256
|
||||||
|
|
||||||
|
echo "Generating client certificate"
|
||||||
|
openssl genpkey -algorithm RSA -out client_private.pem
|
||||||
|
openssl req -new -key client_private.pem -out client.csr -subj "/CN=client"
|
||||||
|
openssl x509 -req -in client.csr -CA ca_cert.pem -CAkey ca_private.pem -CAcreateserial -out client_cert.pem -days 365 -sha256
|
||||||
|
|
||||||
|
echo "Removing intermediate fiels..."
|
||||||
|
rm server.csr client.csr ca_cert.srl
|
||||||
|
|
||||||
|
echo "All done!"
|
||||||
216
cashu/mint/management_rpc/management_rpc.py
Normal file
216
cashu/mint/management_rpc/management_rpc.py
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import grpc
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
import cashu.mint.management_rpc.protos.management_pb2 as management_pb2
|
||||||
|
import cashu.mint.management_rpc.protos.management_pb2_grpc as management_pb2_grpc
|
||||||
|
from cashu.core.base import (
|
||||||
|
MeltQuoteState,
|
||||||
|
MintQuoteState,
|
||||||
|
Unit,
|
||||||
|
)
|
||||||
|
from cashu.core.settings import settings
|
||||||
|
|
||||||
|
from ..ledger import Ledger
|
||||||
|
|
||||||
|
|
||||||
|
class MintManagementRPC(management_pb2_grpc.MintServicer):
|
||||||
|
|
||||||
|
def __init__(self, ledger: Ledger):
|
||||||
|
self.ledger = ledger
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def GetInfo(self, request, _):
|
||||||
|
logger.debug("gRPC GetInfo has been called")
|
||||||
|
mint_info_dict = self.ledger.mint_info.dict()
|
||||||
|
del mint_info_dict["nuts"]
|
||||||
|
response = management_pb2.GetInfoResponse(**mint_info_dict)
|
||||||
|
return response
|
||||||
|
|
||||||
|
async def UpdateMotd(self, request, _):
|
||||||
|
logger.debug("gRPC UpdateMotd has been called")
|
||||||
|
settings.mint_info_motd = request.motd
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
|
||||||
|
async def UpdateShortDescription(self, request, context):
|
||||||
|
logger.debug("gRPC UpdateShortDescription has been called")
|
||||||
|
settings.mint_info_description = request.description
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
|
||||||
|
async def UpdateLongDescription(self, request, context):
|
||||||
|
logger.debug("gRPC UpdateLongDescription has been called")
|
||||||
|
settings.mint_info_description_long = request.description
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
|
||||||
|
async def UpdateIconUrl(self, request, context):
|
||||||
|
logger.debug("gRPC UpdateIconUrl has been called")
|
||||||
|
settings.mint_info_icon_url = request.icon_url
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
|
||||||
|
async def UpdateName(self, request, context):
|
||||||
|
logger.debug("gRPC UpdateName has been called")
|
||||||
|
settings.mint_info_name = request.name
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
|
||||||
|
async def AddUrl(self, request, context):
|
||||||
|
logger.debug("gRPC AddUrl has been called")
|
||||||
|
if settings.mint_info_urls and request.url not in settings.mint_info_urls:
|
||||||
|
settings.mint_info_urls.append(request.url)
|
||||||
|
elif settings.mint_info_urls is None:
|
||||||
|
settings.mint_info_urls = [request.url]
|
||||||
|
else:
|
||||||
|
raise Exception("URL already in mint_info_urls")
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
|
||||||
|
async def RemoveUrl(self, request, context):
|
||||||
|
logger.debug("gRPC RemoveUrl has been called")
|
||||||
|
if settings.mint_info_urls and request.url in settings.mint_info_urls:
|
||||||
|
settings.mint_info_urls.remove(request.url)
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
else:
|
||||||
|
raise Exception("No such URL in mint_info_urls")
|
||||||
|
|
||||||
|
async def AddContact(self, request, context):
|
||||||
|
logger.debug("gRPC AddContact has been called")
|
||||||
|
for contact in settings.mint_info_contact:
|
||||||
|
if contact[0] == request.method:
|
||||||
|
raise Exception("Contact method already set")
|
||||||
|
settings.mint_info_contact.append([request.method, request.info])
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
|
||||||
|
async def RemoveContact(self, request, context):
|
||||||
|
logger.debug("gRPC RemoveContact has been called")
|
||||||
|
for i, contact in enumerate(settings.mint_info_contact):
|
||||||
|
if contact[0] == request.method:
|
||||||
|
del settings.mint_info_contact[i]
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
raise Exception("Contact method not found")
|
||||||
|
|
||||||
|
async def UpdateNut04(self, request, context):
|
||||||
|
"""Cannot implement this yet"""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
async def UpdateNut05(self, request, context):
|
||||||
|
"""Cannot implement this yet"""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
async def UpdateQuoteTtl(self, request, context):
|
||||||
|
logger.debug("gRPC UpdateQuoteTtl has been called")
|
||||||
|
settings.mint_redis_cache_ttl = request.ttl
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
|
||||||
|
async def GetNut04Quote(self, request, _):
|
||||||
|
logger.debug("gRPC GetNut04Quote has been called")
|
||||||
|
mint_quote = await self.ledger.get_mint_quote(request.quote_id)
|
||||||
|
mint_quote_dict = mint_quote.dict()
|
||||||
|
mint_quote_dict['state'] = str(mint_quote_dict['state'])
|
||||||
|
del mint_quote_dict['mint'] # unused
|
||||||
|
del mint_quote_dict['privkey'] # unused
|
||||||
|
return management_pb2.GetNut04QuoteResponse(
|
||||||
|
quote=management_pb2.Nut04Quote(**mint_quote_dict)
|
||||||
|
)
|
||||||
|
|
||||||
|
async def UpdateNut04Quote(self, request, _):
|
||||||
|
logger.debug("gRPC UpdateNut04Quote has been called")
|
||||||
|
state = MintQuoteState(request.state)
|
||||||
|
await self.ledger.db_write._update_mint_quote_state(request.quote_id, state)
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
|
||||||
|
async def GetNut05Quote(self, request, _):
|
||||||
|
logger.debug("gRPC GetNut05Quote has been called")
|
||||||
|
melt_quote = await self.ledger.get_melt_quote(request.quote_id)
|
||||||
|
melt_quote_dict = melt_quote.dict()
|
||||||
|
melt_quote_dict['state'] = str(melt_quote_dict['state'])
|
||||||
|
del melt_quote_dict['mint']
|
||||||
|
return management_pb2.GetNut05QuoteResponse(
|
||||||
|
quote=management_pb2.Nut05Quote(**melt_quote_dict)
|
||||||
|
)
|
||||||
|
|
||||||
|
async def UpdateNut05Quote(self, request, _):
|
||||||
|
logger.debug("gRPC UpdateNut05Quote has been called")
|
||||||
|
state = MeltQuoteState(request.state)
|
||||||
|
await self.ledger.db_write._update_melt_quote_state(request.quote_id, state)
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
|
||||||
|
async def RotateNextKeyset(self, request, context):
|
||||||
|
logger.debug("gRPC RotateNextKeyset has been called")
|
||||||
|
# TODO: Fix this. Currently, we do not allow setting a max_order because
|
||||||
|
# it influences the keyset ID and -in turn- the Mint behaviour when activating keysets
|
||||||
|
# upon a restar (it will activate a new keyset with the standard max order)
|
||||||
|
if request.max_order:
|
||||||
|
logger.warning(f"Ignoring custom max_order of 2**{request.max_order}. This functionality is restricted.")
|
||||||
|
new_keyset = await self.ledger.rotate_next_keyset(Unit[request.unit], input_fee_ppk=request.input_fee_ppk)
|
||||||
|
return management_pb2.RotateNextKeysetResponse(
|
||||||
|
id=new_keyset.id,
|
||||||
|
unit=str(new_keyset.unit),
|
||||||
|
max_order=new_keyset.amounts[-1].bit_length(), # Neat trick to get log_2(last_amount) + 1
|
||||||
|
input_fee_ppk=new_keyset.input_fee_ppk
|
||||||
|
)
|
||||||
|
|
||||||
|
async def UpdateLightningFee(self, request, _):
|
||||||
|
logger.debug("gRPC UpdateLightningFee has been called")
|
||||||
|
if request.fee_percent:
|
||||||
|
settings.lightning_fee_percent = request.fee_percent
|
||||||
|
elif request.fee_min_reserve:
|
||||||
|
settings.lightning_reserve_fee_min = request.fee_min_reserve
|
||||||
|
else:
|
||||||
|
raise Exception("No fee specified")
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
|
||||||
|
async def UpdateAuthLimits(self, request, _):
|
||||||
|
logger.debug("gRPC UpdateAuthLimits has been called")
|
||||||
|
if request.auth_rate_limit_per_minute:
|
||||||
|
settings.mint_auth_rate_limit_per_minute = request.auth_rate_limit_per_minute
|
||||||
|
elif request.auth_max_blind_tokens:
|
||||||
|
settings.mint_auth_max_blind_tokens = request.auth_max_blind_tokens
|
||||||
|
else:
|
||||||
|
raise Exception("No auth limit was specified")
|
||||||
|
return management_pb2.UpdateResponse()
|
||||||
|
|
||||||
|
async def serve(ledger: Ledger):
|
||||||
|
host = settings.mint_rpc_server_addr
|
||||||
|
port = settings.mint_rpc_server_port
|
||||||
|
server = grpc.aio.server()
|
||||||
|
management_pb2_grpc.add_MintServicer_to_server(MintManagementRPC(ledger=ledger), server)
|
||||||
|
|
||||||
|
if settings.mint_rpc_server_mutual_tls:
|
||||||
|
# Verify the existence of the required paths
|
||||||
|
mint_rpc_key_path = settings.mint_rpc_server_key
|
||||||
|
mint_rpc_ca_path = settings.mint_rpc_server_ca
|
||||||
|
mint_rpc_cert_path = settings.mint_rpc_server_cert
|
||||||
|
|
||||||
|
if not all(os.path.exists(path) if path else False for path in [mint_rpc_key_path, mint_rpc_ca_path, mint_rpc_cert_path]):
|
||||||
|
logger.error("One or more required files for mTLS are missing:")
|
||||||
|
if not mint_rpc_key_path or not os.path.exists(mint_rpc_key_path):
|
||||||
|
logger.error(f"Missing key file: {mint_rpc_key_path}")
|
||||||
|
if not mint_rpc_ca_path or not os.path.exists(mint_rpc_ca_path):
|
||||||
|
logger.error(f"Missing CA file: {mint_rpc_ca_path}")
|
||||||
|
if not mint_rpc_cert_path or not os.path.exists(mint_rpc_cert_path):
|
||||||
|
logger.error(f"Missing cert file: {mint_rpc_cert_path}")
|
||||||
|
raise FileNotFoundError("Required mTLS files are missing. Please check the paths.")
|
||||||
|
|
||||||
|
logger.info(f"Starting mTLS Management RPC service on {host}:{port}")
|
||||||
|
# Load server credentials
|
||||||
|
server_credentials = grpc.ssl_server_credentials(
|
||||||
|
((open(mint_rpc_key_path, 'rb').read(), open(mint_rpc_cert_path, 'rb').read()),),
|
||||||
|
root_certificates=open(mint_rpc_ca_path, 'rb').read(),
|
||||||
|
require_client_auth=True,
|
||||||
|
)
|
||||||
|
server.add_secure_port(f"{host}:{port}", server_credentials)
|
||||||
|
else:
|
||||||
|
logger.info(f"Starting INSECURE Management RPC service on {host}:{port}")
|
||||||
|
server.add_insecure_port(f"{host}:{port}")
|
||||||
|
|
||||||
|
await server.start()
|
||||||
|
return server
|
||||||
|
|
||||||
|
async def shutdown(server: grpc.aio.Server):
|
||||||
|
logger.info("Shutting down management RPC gracefully...")
|
||||||
|
await server.stop(grace=2) # Give clients 2 seconds to finish requests
|
||||||
|
logger.debug("Management RPC shut down.")
|
||||||
0
cashu/mint/management_rpc/protos/__init__.py
Normal file
0
cashu/mint/management_rpc/protos/__init__.py
Normal file
29
cashu/mint/management_rpc/protos/build.sh
Executable file
29
cashu/mint/management_rpc/protos/build.sh
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# *** RUN THIS FROM THE ROOT OF THE PROJECT ***
|
||||||
|
|
||||||
|
BASE_DIR=./cashu/mint/management_rpc/protos
|
||||||
|
|
||||||
|
# Check if the googleapis directory exists
|
||||||
|
if [ -d "$BASE_DIR/googleapis" ]; then
|
||||||
|
echo "$BASE_DIR/googleapis directory already exists. Skipping clone."
|
||||||
|
else
|
||||||
|
echo "Cloning googleapis..."
|
||||||
|
echo "If this doesn't work, clone it manually."
|
||||||
|
git clone https://github.com/googleapis/googleapis.git $BASE_DIR/googleapis
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Ensuring grpcio is installed..."
|
||||||
|
poetry add grpcio grpcio-tools
|
||||||
|
|
||||||
|
echo "Compiling proto files..."
|
||||||
|
poetry run python3 -m grpc_tools.protoc --proto_path=$BASE_DIR/googleapis:$BASE_DIR --mypy_out=$BASE_DIR --python_out=$BASE_DIR --grpc_python_out=$BASE_DIR $BASE_DIR/management.proto
|
||||||
|
|
||||||
|
echo "fixing imports on autogenerated files..."
|
||||||
|
for file in $BASE_DIR/*.{py,pyi}; do
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
sed -i -e 's/import management_pb2/import cashu.mint.management_rpc.protos.management_pb2/g' $file
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Finished!"
|
||||||
197
cashu/mint/management_rpc/protos/management.proto
Normal file
197
cashu/mint/management_rpc/protos/management.proto
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package management;
|
||||||
|
|
||||||
|
service Mint {
|
||||||
|
rpc GetInfo(GetInfoRequest) returns (GetInfoResponse) {}
|
||||||
|
rpc UpdateMotd(UpdateMotdRequest) returns (UpdateResponse) {}
|
||||||
|
rpc UpdateShortDescription(UpdateDescriptionRequest) returns (UpdateResponse) {}
|
||||||
|
rpc UpdateLongDescription(UpdateDescriptionRequest) returns (UpdateResponse) {}
|
||||||
|
rpc UpdateIconUrl(UpdateIconUrlRequest) returns (UpdateResponse) {}
|
||||||
|
rpc UpdateName(UpdateNameRequest) returns (UpdateResponse) {}
|
||||||
|
rpc AddUrl(UpdateUrlRequest) returns (UpdateResponse) {}
|
||||||
|
rpc RemoveUrl(UpdateUrlRequest) returns (UpdateResponse) {}
|
||||||
|
rpc AddContact(UpdateContactRequest) returns (UpdateResponse) {}
|
||||||
|
rpc RemoveContact(UpdateContactRequest) returns (UpdateResponse) {}
|
||||||
|
rpc GetNut04Quote(GetNut04QuoteRequest) returns (GetNut04QuoteResponse) {}
|
||||||
|
rpc GetNut05Quote(GetNut05QuoteRequest) returns (GetNut05QuoteResponse) {}
|
||||||
|
rpc UpdateNut04(UpdateNut04Request) returns (UpdateResponse) {}
|
||||||
|
rpc UpdateNut05(UpdateNut05Request) returns (UpdateResponse) {}
|
||||||
|
rpc UpdateQuoteTtl(UpdateQuoteTtlRequest) returns (UpdateResponse) {}
|
||||||
|
rpc UpdateNut04Quote(UpdateQuoteRequest) returns (UpdateResponse) {}
|
||||||
|
rpc UpdateNut05Quote(UpdateQuoteRequest) returns (UpdateResponse) {}
|
||||||
|
rpc RotateNextKeyset(RotateNextKeysetRequest) returns (RotateNextKeysetResponse) {}
|
||||||
|
rpc UpdateLightningFee(UpdateLightningFeeRequest) returns (UpdateResponse) {}
|
||||||
|
rpc UpdateAuthLimits(UpdateAuthLimitsRequest) returns (UpdateResponse) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetInfoRequest {
|
||||||
|
}
|
||||||
|
|
||||||
|
message MintInfoContact {
|
||||||
|
string method = 1;
|
||||||
|
string info = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetInfoResponse {
|
||||||
|
optional string name = 1;
|
||||||
|
optional string pubkey = 2;
|
||||||
|
optional string version = 3;
|
||||||
|
optional string description = 4;
|
||||||
|
optional string description_long = 5;
|
||||||
|
repeated MintInfoContact contact = 6;
|
||||||
|
optional string motd = 7;
|
||||||
|
optional string icon_url = 8;
|
||||||
|
repeated string urls = 9;
|
||||||
|
optional int64 time = 10;
|
||||||
|
optional string tos_url = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateResponse{
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateMotdRequest {
|
||||||
|
string motd = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateDescriptionRequest {
|
||||||
|
string description = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message UpdateIconUrlRequest {
|
||||||
|
string icon_url = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateNameRequest {
|
||||||
|
string name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message UpdateUrlRequest {
|
||||||
|
string url = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateContactRequest {
|
||||||
|
string method = 1;
|
||||||
|
string info = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateNut04Request {
|
||||||
|
string unit = 1;
|
||||||
|
string method = 2;
|
||||||
|
optional bool disabled = 3;
|
||||||
|
optional uint64 min = 4;
|
||||||
|
optional uint64 max = 5;
|
||||||
|
optional bool description = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message UpdateNut05Request {
|
||||||
|
string unit = 1;
|
||||||
|
string method = 2;
|
||||||
|
optional bool disabled = 3;
|
||||||
|
optional uint64 min = 4;
|
||||||
|
optional uint64 max = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateQuoteTtlRequest {
|
||||||
|
optional uint64 ttl = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Nut04Quote {
|
||||||
|
string quote = 1;
|
||||||
|
string method = 2;
|
||||||
|
string request = 3;
|
||||||
|
string checking_id = 4;
|
||||||
|
string unit = 5;
|
||||||
|
uint64 amount = 6;
|
||||||
|
optional string state = 7;
|
||||||
|
optional int64 created_time = 8;
|
||||||
|
optional int64 paid_time = 9;
|
||||||
|
optional int64 expiry = 10;
|
||||||
|
optional string pubkey = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BlindedMessage {
|
||||||
|
int32 amount = 1;
|
||||||
|
string id = 2;
|
||||||
|
string B_ = 3;
|
||||||
|
optional string witness = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DLEQ {
|
||||||
|
string e = 1;
|
||||||
|
string s = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BlindedSignature {
|
||||||
|
string id = 1;
|
||||||
|
int32 amount = 2;
|
||||||
|
string C_ = 3;
|
||||||
|
optional DLEQ dleq = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Nut05Quote {
|
||||||
|
string quote = 1;
|
||||||
|
string method = 2;
|
||||||
|
string request = 3;
|
||||||
|
string checking_id = 4;
|
||||||
|
string unit = 5;
|
||||||
|
int32 amount = 6;
|
||||||
|
int32 fee_reserve = 7;
|
||||||
|
string state = 8;
|
||||||
|
optional int64 created_time = 9;
|
||||||
|
optional int64 paid_time = 10;
|
||||||
|
int32 fee_paid = 11;
|
||||||
|
optional string payment_preimage = 12;
|
||||||
|
optional int64 expiry = 13;
|
||||||
|
repeated BlindedMessage outputs = 14;
|
||||||
|
repeated BlindedSignature change = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetNut04QuoteRequest {
|
||||||
|
string quote_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetNut04QuoteResponse {
|
||||||
|
Nut04Quote quote = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetNut05QuoteRequest {
|
||||||
|
string quote_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetNut05QuoteResponse {
|
||||||
|
Nut05Quote quote = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateQuoteRequest {
|
||||||
|
string quote_id = 1;
|
||||||
|
string state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RotateNextKeysetRequest {
|
||||||
|
string unit = 1;
|
||||||
|
optional uint32 max_order = 2;
|
||||||
|
optional uint64 input_fee_ppk = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message RotateNextKeysetResponse {
|
||||||
|
string id = 1;
|
||||||
|
string unit = 2;
|
||||||
|
uint32 max_order = 3;
|
||||||
|
uint64 input_fee_ppk = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message UpdateLightningFeeRequest {
|
||||||
|
optional double fee_percent = 1;
|
||||||
|
optional uint64 fee_min_reserve = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateAuthLimitsRequest {
|
||||||
|
optional uint64 auth_rate_limit_per_minute = 1;
|
||||||
|
optional uint64 auth_max_blind_tokens = 2;
|
||||||
|
}
|
||||||
91
cashu/mint/management_rpc/protos/management_pb2.py
Normal file
91
cashu/mint/management_rpc/protos/management_pb2.py
Normal file
File diff suppressed because one or more lines are too long
674
cashu/mint/management_rpc/protos/management_pb2.pyi
Normal file
674
cashu/mint/management_rpc/protos/management_pb2.pyi
Normal file
@@ -0,0 +1,674 @@
|
|||||||
|
"""
|
||||||
|
@generated by mypy-protobuf. Do not edit manually!
|
||||||
|
isort:skip_file
|
||||||
|
"""
|
||||||
|
|
||||||
|
import builtins
|
||||||
|
import collections.abc
|
||||||
|
import typing
|
||||||
|
|
||||||
|
import google.protobuf.descriptor
|
||||||
|
import google.protobuf.internal.containers
|
||||||
|
import google.protobuf.message
|
||||||
|
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class GetInfoRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
) -> None: ...
|
||||||
|
|
||||||
|
global___GetInfoRequest = GetInfoRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class MintInfoContact(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
METHOD_FIELD_NUMBER: builtins.int
|
||||||
|
INFO_FIELD_NUMBER: builtins.int
|
||||||
|
method: builtins.str
|
||||||
|
info: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
method: builtins.str = ...,
|
||||||
|
info: builtins.str = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["info", b"info", "method", b"method"]) -> None: ...
|
||||||
|
|
||||||
|
global___MintInfoContact = MintInfoContact
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class GetInfoResponse(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
NAME_FIELD_NUMBER: builtins.int
|
||||||
|
PUBKEY_FIELD_NUMBER: builtins.int
|
||||||
|
VERSION_FIELD_NUMBER: builtins.int
|
||||||
|
DESCRIPTION_FIELD_NUMBER: builtins.int
|
||||||
|
DESCRIPTION_LONG_FIELD_NUMBER: builtins.int
|
||||||
|
CONTACT_FIELD_NUMBER: builtins.int
|
||||||
|
MOTD_FIELD_NUMBER: builtins.int
|
||||||
|
ICON_URL_FIELD_NUMBER: builtins.int
|
||||||
|
URLS_FIELD_NUMBER: builtins.int
|
||||||
|
TIME_FIELD_NUMBER: builtins.int
|
||||||
|
TOS_URL_FIELD_NUMBER: builtins.int
|
||||||
|
name: builtins.str
|
||||||
|
pubkey: builtins.str
|
||||||
|
version: builtins.str
|
||||||
|
description: builtins.str
|
||||||
|
description_long: builtins.str
|
||||||
|
motd: builtins.str
|
||||||
|
icon_url: builtins.str
|
||||||
|
time: builtins.int
|
||||||
|
tos_url: builtins.str
|
||||||
|
@property
|
||||||
|
def contact(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___MintInfoContact]: ...
|
||||||
|
@property
|
||||||
|
def urls(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ...
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
name: builtins.str | None = ...,
|
||||||
|
pubkey: builtins.str | None = ...,
|
||||||
|
version: builtins.str | None = ...,
|
||||||
|
description: builtins.str | None = ...,
|
||||||
|
description_long: builtins.str | None = ...,
|
||||||
|
contact: collections.abc.Iterable[global___MintInfoContact] | None = ...,
|
||||||
|
motd: builtins.str | None = ...,
|
||||||
|
icon_url: builtins.str | None = ...,
|
||||||
|
urls: collections.abc.Iterable[builtins.str] | None = ...,
|
||||||
|
time: builtins.int | None = ...,
|
||||||
|
tos_url: builtins.str | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["_description", b"_description", "_description_long", b"_description_long", "_icon_url", b"_icon_url", "_motd", b"_motd", "_name", b"_name", "_pubkey", b"_pubkey", "_time", b"_time", "_tos_url", b"_tos_url", "_version", b"_version", "description", b"description", "description_long", b"description_long", "icon_url", b"icon_url", "motd", b"motd", "name", b"name", "pubkey", b"pubkey", "time", b"time", "tos_url", b"tos_url", "version", b"version"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["_description", b"_description", "_description_long", b"_description_long", "_icon_url", b"_icon_url", "_motd", b"_motd", "_name", b"_name", "_pubkey", b"_pubkey", "_time", b"_time", "_tos_url", b"_tos_url", "_version", b"_version", "contact", b"contact", "description", b"description", "description_long", b"description_long", "icon_url", b"icon_url", "motd", b"motd", "name", b"name", "pubkey", b"pubkey", "time", b"time", "tos_url", b"tos_url", "urls", b"urls", "version", b"version"]) -> None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_description", b"_description"]) -> typing.Literal["description"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_description_long", b"_description_long"]) -> typing.Literal["description_long"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_icon_url", b"_icon_url"]) -> typing.Literal["icon_url"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_motd", b"_motd"]) -> typing.Literal["motd"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_name", b"_name"]) -> typing.Literal["name"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_pubkey", b"_pubkey"]) -> typing.Literal["pubkey"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_time", b"_time"]) -> typing.Literal["time"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_tos_url", b"_tos_url"]) -> typing.Literal["tos_url"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_version", b"_version"]) -> typing.Literal["version"] | None: ...
|
||||||
|
|
||||||
|
global___GetInfoResponse = GetInfoResponse
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateResponse(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
) -> None: ...
|
||||||
|
|
||||||
|
global___UpdateResponse = UpdateResponse
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateMotdRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
MOTD_FIELD_NUMBER: builtins.int
|
||||||
|
motd: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
motd: builtins.str = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["motd", b"motd"]) -> None: ...
|
||||||
|
|
||||||
|
global___UpdateMotdRequest = UpdateMotdRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateDescriptionRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
DESCRIPTION_FIELD_NUMBER: builtins.int
|
||||||
|
description: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
description: builtins.str = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["description", b"description"]) -> None: ...
|
||||||
|
|
||||||
|
global___UpdateDescriptionRequest = UpdateDescriptionRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateIconUrlRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
ICON_URL_FIELD_NUMBER: builtins.int
|
||||||
|
icon_url: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
icon_url: builtins.str = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["icon_url", b"icon_url"]) -> None: ...
|
||||||
|
|
||||||
|
global___UpdateIconUrlRequest = UpdateIconUrlRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateNameRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
NAME_FIELD_NUMBER: builtins.int
|
||||||
|
name: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
name: builtins.str = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["name", b"name"]) -> None: ...
|
||||||
|
|
||||||
|
global___UpdateNameRequest = UpdateNameRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateUrlRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
URL_FIELD_NUMBER: builtins.int
|
||||||
|
url: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
url: builtins.str = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["url", b"url"]) -> None: ...
|
||||||
|
|
||||||
|
global___UpdateUrlRequest = UpdateUrlRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateContactRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
METHOD_FIELD_NUMBER: builtins.int
|
||||||
|
INFO_FIELD_NUMBER: builtins.int
|
||||||
|
method: builtins.str
|
||||||
|
info: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
method: builtins.str = ...,
|
||||||
|
info: builtins.str = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["info", b"info", "method", b"method"]) -> None: ...
|
||||||
|
|
||||||
|
global___UpdateContactRequest = UpdateContactRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateNut04Request(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
UNIT_FIELD_NUMBER: builtins.int
|
||||||
|
METHOD_FIELD_NUMBER: builtins.int
|
||||||
|
DISABLED_FIELD_NUMBER: builtins.int
|
||||||
|
MIN_FIELD_NUMBER: builtins.int
|
||||||
|
MAX_FIELD_NUMBER: builtins.int
|
||||||
|
DESCRIPTION_FIELD_NUMBER: builtins.int
|
||||||
|
unit: builtins.str
|
||||||
|
method: builtins.str
|
||||||
|
disabled: builtins.bool
|
||||||
|
min: builtins.int
|
||||||
|
max: builtins.int
|
||||||
|
description: builtins.bool
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
unit: builtins.str = ...,
|
||||||
|
method: builtins.str = ...,
|
||||||
|
disabled: builtins.bool | None = ...,
|
||||||
|
min: builtins.int | None = ...,
|
||||||
|
max: builtins.int | None = ...,
|
||||||
|
description: builtins.bool | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["_description", b"_description", "_disabled", b"_disabled", "_max", b"_max", "_min", b"_min", "description", b"description", "disabled", b"disabled", "max", b"max", "min", b"min"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["_description", b"_description", "_disabled", b"_disabled", "_max", b"_max", "_min", b"_min", "description", b"description", "disabled", b"disabled", "max", b"max", "method", b"method", "min", b"min", "unit", b"unit"]) -> None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_description", b"_description"]) -> typing.Literal["description"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_disabled", b"_disabled"]) -> typing.Literal["disabled"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_max", b"_max"]) -> typing.Literal["max"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_min", b"_min"]) -> typing.Literal["min"] | None: ...
|
||||||
|
|
||||||
|
global___UpdateNut04Request = UpdateNut04Request
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateNut05Request(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
UNIT_FIELD_NUMBER: builtins.int
|
||||||
|
METHOD_FIELD_NUMBER: builtins.int
|
||||||
|
DISABLED_FIELD_NUMBER: builtins.int
|
||||||
|
MIN_FIELD_NUMBER: builtins.int
|
||||||
|
MAX_FIELD_NUMBER: builtins.int
|
||||||
|
unit: builtins.str
|
||||||
|
method: builtins.str
|
||||||
|
disabled: builtins.bool
|
||||||
|
min: builtins.int
|
||||||
|
max: builtins.int
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
unit: builtins.str = ...,
|
||||||
|
method: builtins.str = ...,
|
||||||
|
disabled: builtins.bool | None = ...,
|
||||||
|
min: builtins.int | None = ...,
|
||||||
|
max: builtins.int | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["_disabled", b"_disabled", "_max", b"_max", "_min", b"_min", "disabled", b"disabled", "max", b"max", "min", b"min"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["_disabled", b"_disabled", "_max", b"_max", "_min", b"_min", "disabled", b"disabled", "max", b"max", "method", b"method", "min", b"min", "unit", b"unit"]) -> None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_disabled", b"_disabled"]) -> typing.Literal["disabled"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_max", b"_max"]) -> typing.Literal["max"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_min", b"_min"]) -> typing.Literal["min"] | None: ...
|
||||||
|
|
||||||
|
global___UpdateNut05Request = UpdateNut05Request
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateQuoteTtlRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
TTL_FIELD_NUMBER: builtins.int
|
||||||
|
ttl: builtins.int
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
ttl: builtins.int | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["_ttl", b"_ttl", "ttl", b"ttl"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["_ttl", b"_ttl", "ttl", b"ttl"]) -> None: ...
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_ttl", b"_ttl"]) -> typing.Literal["ttl"] | None: ...
|
||||||
|
|
||||||
|
global___UpdateQuoteTtlRequest = UpdateQuoteTtlRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class Nut04Quote(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
QUOTE_FIELD_NUMBER: builtins.int
|
||||||
|
METHOD_FIELD_NUMBER: builtins.int
|
||||||
|
REQUEST_FIELD_NUMBER: builtins.int
|
||||||
|
CHECKING_ID_FIELD_NUMBER: builtins.int
|
||||||
|
UNIT_FIELD_NUMBER: builtins.int
|
||||||
|
AMOUNT_FIELD_NUMBER: builtins.int
|
||||||
|
STATE_FIELD_NUMBER: builtins.int
|
||||||
|
CREATED_TIME_FIELD_NUMBER: builtins.int
|
||||||
|
PAID_TIME_FIELD_NUMBER: builtins.int
|
||||||
|
EXPIRY_FIELD_NUMBER: builtins.int
|
||||||
|
PUBKEY_FIELD_NUMBER: builtins.int
|
||||||
|
quote: builtins.str
|
||||||
|
method: builtins.str
|
||||||
|
request: builtins.str
|
||||||
|
checking_id: builtins.str
|
||||||
|
unit: builtins.str
|
||||||
|
amount: builtins.int
|
||||||
|
state: builtins.str
|
||||||
|
created_time: builtins.int
|
||||||
|
paid_time: builtins.int
|
||||||
|
expiry: builtins.int
|
||||||
|
pubkey: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
quote: builtins.str = ...,
|
||||||
|
method: builtins.str = ...,
|
||||||
|
request: builtins.str = ...,
|
||||||
|
checking_id: builtins.str = ...,
|
||||||
|
unit: builtins.str = ...,
|
||||||
|
amount: builtins.int = ...,
|
||||||
|
state: builtins.str | None = ...,
|
||||||
|
created_time: builtins.int | None = ...,
|
||||||
|
paid_time: builtins.int | None = ...,
|
||||||
|
expiry: builtins.int | None = ...,
|
||||||
|
pubkey: builtins.str | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["_created_time", b"_created_time", "_expiry", b"_expiry", "_paid_time", b"_paid_time", "_pubkey", b"_pubkey", "_state", b"_state", "created_time", b"created_time", "expiry", b"expiry", "paid_time", b"paid_time", "pubkey", b"pubkey", "state", b"state"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["_created_time", b"_created_time", "_expiry", b"_expiry", "_paid_time", b"_paid_time", "_pubkey", b"_pubkey", "_state", b"_state", "amount", b"amount", "checking_id", b"checking_id", "created_time", b"created_time", "expiry", b"expiry", "method", b"method", "paid_time", b"paid_time", "pubkey", b"pubkey", "quote", b"quote", "request", b"request", "state", b"state", "unit", b"unit"]) -> None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_created_time", b"_created_time"]) -> typing.Literal["created_time"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_expiry", b"_expiry"]) -> typing.Literal["expiry"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_paid_time", b"_paid_time"]) -> typing.Literal["paid_time"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_pubkey", b"_pubkey"]) -> typing.Literal["pubkey"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_state", b"_state"]) -> typing.Literal["state"] | None: ...
|
||||||
|
|
||||||
|
global___Nut04Quote = Nut04Quote
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class BlindedMessage(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
AMOUNT_FIELD_NUMBER: builtins.int
|
||||||
|
ID_FIELD_NUMBER: builtins.int
|
||||||
|
B__FIELD_NUMBER: builtins.int
|
||||||
|
WITNESS_FIELD_NUMBER: builtins.int
|
||||||
|
amount: builtins.int
|
||||||
|
id: builtins.str
|
||||||
|
B_: builtins.str
|
||||||
|
witness: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
amount: builtins.int = ...,
|
||||||
|
id: builtins.str = ...,
|
||||||
|
B_: builtins.str = ...,
|
||||||
|
witness: builtins.str | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["_witness", b"_witness", "witness", b"witness"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["B_", b"B_", "_witness", b"_witness", "amount", b"amount", "id", b"id", "witness", b"witness"]) -> None: ...
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_witness", b"_witness"]) -> typing.Literal["witness"] | None: ...
|
||||||
|
|
||||||
|
global___BlindedMessage = BlindedMessage
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class DLEQ(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
E_FIELD_NUMBER: builtins.int
|
||||||
|
S_FIELD_NUMBER: builtins.int
|
||||||
|
e: builtins.str
|
||||||
|
s: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
e: builtins.str = ...,
|
||||||
|
s: builtins.str = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["e", b"e", "s", b"s"]) -> None: ...
|
||||||
|
|
||||||
|
global___DLEQ = DLEQ
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class BlindedSignature(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
ID_FIELD_NUMBER: builtins.int
|
||||||
|
AMOUNT_FIELD_NUMBER: builtins.int
|
||||||
|
C__FIELD_NUMBER: builtins.int
|
||||||
|
DLEQ_FIELD_NUMBER: builtins.int
|
||||||
|
id: builtins.str
|
||||||
|
amount: builtins.int
|
||||||
|
C_: builtins.str
|
||||||
|
@property
|
||||||
|
def dleq(self) -> global___DLEQ: ...
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
id: builtins.str = ...,
|
||||||
|
amount: builtins.int = ...,
|
||||||
|
C_: builtins.str = ...,
|
||||||
|
dleq: global___DLEQ | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["_dleq", b"_dleq", "dleq", b"dleq"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["C_", b"C_", "_dleq", b"_dleq", "amount", b"amount", "dleq", b"dleq", "id", b"id"]) -> None: ...
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_dleq", b"_dleq"]) -> typing.Literal["dleq"] | None: ...
|
||||||
|
|
||||||
|
global___BlindedSignature = BlindedSignature
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class Nut05Quote(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
QUOTE_FIELD_NUMBER: builtins.int
|
||||||
|
METHOD_FIELD_NUMBER: builtins.int
|
||||||
|
REQUEST_FIELD_NUMBER: builtins.int
|
||||||
|
CHECKING_ID_FIELD_NUMBER: builtins.int
|
||||||
|
UNIT_FIELD_NUMBER: builtins.int
|
||||||
|
AMOUNT_FIELD_NUMBER: builtins.int
|
||||||
|
FEE_RESERVE_FIELD_NUMBER: builtins.int
|
||||||
|
STATE_FIELD_NUMBER: builtins.int
|
||||||
|
CREATED_TIME_FIELD_NUMBER: builtins.int
|
||||||
|
PAID_TIME_FIELD_NUMBER: builtins.int
|
||||||
|
FEE_PAID_FIELD_NUMBER: builtins.int
|
||||||
|
PAYMENT_PREIMAGE_FIELD_NUMBER: builtins.int
|
||||||
|
EXPIRY_FIELD_NUMBER: builtins.int
|
||||||
|
OUTPUTS_FIELD_NUMBER: builtins.int
|
||||||
|
CHANGE_FIELD_NUMBER: builtins.int
|
||||||
|
quote: builtins.str
|
||||||
|
method: builtins.str
|
||||||
|
request: builtins.str
|
||||||
|
checking_id: builtins.str
|
||||||
|
unit: builtins.str
|
||||||
|
amount: builtins.int
|
||||||
|
fee_reserve: builtins.int
|
||||||
|
state: builtins.str
|
||||||
|
created_time: builtins.int
|
||||||
|
paid_time: builtins.int
|
||||||
|
fee_paid: builtins.int
|
||||||
|
payment_preimage: builtins.str
|
||||||
|
expiry: builtins.int
|
||||||
|
@property
|
||||||
|
def outputs(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___BlindedMessage]: ...
|
||||||
|
@property
|
||||||
|
def change(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___BlindedSignature]: ...
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
quote: builtins.str = ...,
|
||||||
|
method: builtins.str = ...,
|
||||||
|
request: builtins.str = ...,
|
||||||
|
checking_id: builtins.str = ...,
|
||||||
|
unit: builtins.str = ...,
|
||||||
|
amount: builtins.int = ...,
|
||||||
|
fee_reserve: builtins.int = ...,
|
||||||
|
state: builtins.str = ...,
|
||||||
|
created_time: builtins.int | None = ...,
|
||||||
|
paid_time: builtins.int | None = ...,
|
||||||
|
fee_paid: builtins.int = ...,
|
||||||
|
payment_preimage: builtins.str | None = ...,
|
||||||
|
expiry: builtins.int | None = ...,
|
||||||
|
outputs: collections.abc.Iterable[global___BlindedMessage] | None = ...,
|
||||||
|
change: collections.abc.Iterable[global___BlindedSignature] | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["_created_time", b"_created_time", "_expiry", b"_expiry", "_paid_time", b"_paid_time", "_payment_preimage", b"_payment_preimage", "created_time", b"created_time", "expiry", b"expiry", "paid_time", b"paid_time", "payment_preimage", b"payment_preimage"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["_created_time", b"_created_time", "_expiry", b"_expiry", "_paid_time", b"_paid_time", "_payment_preimage", b"_payment_preimage", "amount", b"amount", "change", b"change", "checking_id", b"checking_id", "created_time", b"created_time", "expiry", b"expiry", "fee_paid", b"fee_paid", "fee_reserve", b"fee_reserve", "method", b"method", "outputs", b"outputs", "paid_time", b"paid_time", "payment_preimage", b"payment_preimage", "quote", b"quote", "request", b"request", "state", b"state", "unit", b"unit"]) -> None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_created_time", b"_created_time"]) -> typing.Literal["created_time"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_expiry", b"_expiry"]) -> typing.Literal["expiry"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_paid_time", b"_paid_time"]) -> typing.Literal["paid_time"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_payment_preimage", b"_payment_preimage"]) -> typing.Literal["payment_preimage"] | None: ...
|
||||||
|
|
||||||
|
global___Nut05Quote = Nut05Quote
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class GetNut04QuoteRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
QUOTE_ID_FIELD_NUMBER: builtins.int
|
||||||
|
quote_id: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
quote_id: builtins.str = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["quote_id", b"quote_id"]) -> None: ...
|
||||||
|
|
||||||
|
global___GetNut04QuoteRequest = GetNut04QuoteRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class GetNut04QuoteResponse(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
QUOTE_FIELD_NUMBER: builtins.int
|
||||||
|
@property
|
||||||
|
def quote(self) -> global___Nut04Quote: ...
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
quote: global___Nut04Quote | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["quote", b"quote"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["quote", b"quote"]) -> None: ...
|
||||||
|
|
||||||
|
global___GetNut04QuoteResponse = GetNut04QuoteResponse
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class GetNut05QuoteRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
QUOTE_ID_FIELD_NUMBER: builtins.int
|
||||||
|
quote_id: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
quote_id: builtins.str = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["quote_id", b"quote_id"]) -> None: ...
|
||||||
|
|
||||||
|
global___GetNut05QuoteRequest = GetNut05QuoteRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class GetNut05QuoteResponse(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
QUOTE_FIELD_NUMBER: builtins.int
|
||||||
|
@property
|
||||||
|
def quote(self) -> global___Nut05Quote: ...
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
quote: global___Nut05Quote | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["quote", b"quote"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["quote", b"quote"]) -> None: ...
|
||||||
|
|
||||||
|
global___GetNut05QuoteResponse = GetNut05QuoteResponse
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateQuoteRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
QUOTE_ID_FIELD_NUMBER: builtins.int
|
||||||
|
STATE_FIELD_NUMBER: builtins.int
|
||||||
|
quote_id: builtins.str
|
||||||
|
state: builtins.str
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
quote_id: builtins.str = ...,
|
||||||
|
state: builtins.str = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["quote_id", b"quote_id", "state", b"state"]) -> None: ...
|
||||||
|
|
||||||
|
global___UpdateQuoteRequest = UpdateQuoteRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class RotateNextKeysetRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
UNIT_FIELD_NUMBER: builtins.int
|
||||||
|
MAX_ORDER_FIELD_NUMBER: builtins.int
|
||||||
|
INPUT_FEE_PPK_FIELD_NUMBER: builtins.int
|
||||||
|
unit: builtins.str
|
||||||
|
max_order: builtins.int
|
||||||
|
input_fee_ppk: builtins.int
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
unit: builtins.str = ...,
|
||||||
|
max_order: builtins.int | None = ...,
|
||||||
|
input_fee_ppk: builtins.int | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["_input_fee_ppk", b"_input_fee_ppk", "_max_order", b"_max_order", "input_fee_ppk", b"input_fee_ppk", "max_order", b"max_order"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["_input_fee_ppk", b"_input_fee_ppk", "_max_order", b"_max_order", "input_fee_ppk", b"input_fee_ppk", "max_order", b"max_order", "unit", b"unit"]) -> None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_input_fee_ppk", b"_input_fee_ppk"]) -> typing.Literal["input_fee_ppk"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_max_order", b"_max_order"]) -> typing.Literal["max_order"] | None: ...
|
||||||
|
|
||||||
|
global___RotateNextKeysetRequest = RotateNextKeysetRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class RotateNextKeysetResponse(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
ID_FIELD_NUMBER: builtins.int
|
||||||
|
UNIT_FIELD_NUMBER: builtins.int
|
||||||
|
MAX_ORDER_FIELD_NUMBER: builtins.int
|
||||||
|
INPUT_FEE_PPK_FIELD_NUMBER: builtins.int
|
||||||
|
id: builtins.str
|
||||||
|
unit: builtins.str
|
||||||
|
max_order: builtins.int
|
||||||
|
input_fee_ppk: builtins.int
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
id: builtins.str = ...,
|
||||||
|
unit: builtins.str = ...,
|
||||||
|
max_order: builtins.int = ...,
|
||||||
|
input_fee_ppk: builtins.int = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["id", b"id", "input_fee_ppk", b"input_fee_ppk", "max_order", b"max_order", "unit", b"unit"]) -> None: ...
|
||||||
|
|
||||||
|
global___RotateNextKeysetResponse = RotateNextKeysetResponse
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateLightningFeeRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
FEE_PERCENT_FIELD_NUMBER: builtins.int
|
||||||
|
FEE_MIN_RESERVE_FIELD_NUMBER: builtins.int
|
||||||
|
fee_percent: builtins.float
|
||||||
|
fee_min_reserve: builtins.int
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
fee_percent: builtins.float | None = ...,
|
||||||
|
fee_min_reserve: builtins.int | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["_fee_min_reserve", b"_fee_min_reserve", "_fee_percent", b"_fee_percent", "fee_min_reserve", b"fee_min_reserve", "fee_percent", b"fee_percent"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["_fee_min_reserve", b"_fee_min_reserve", "_fee_percent", b"_fee_percent", "fee_min_reserve", b"fee_min_reserve", "fee_percent", b"fee_percent"]) -> None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_fee_min_reserve", b"_fee_min_reserve"]) -> typing.Literal["fee_min_reserve"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_fee_percent", b"_fee_percent"]) -> typing.Literal["fee_percent"] | None: ...
|
||||||
|
|
||||||
|
global___UpdateLightningFeeRequest = UpdateLightningFeeRequest
|
||||||
|
|
||||||
|
@typing.final
|
||||||
|
class UpdateAuthLimitsRequest(google.protobuf.message.Message):
|
||||||
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||||
|
|
||||||
|
AUTH_RATE_LIMIT_PER_MINUTE_FIELD_NUMBER: builtins.int
|
||||||
|
AUTH_MAX_BLIND_TOKENS_FIELD_NUMBER: builtins.int
|
||||||
|
auth_rate_limit_per_minute: builtins.int
|
||||||
|
auth_max_blind_tokens: builtins.int
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
auth_rate_limit_per_minute: builtins.int | None = ...,
|
||||||
|
auth_max_blind_tokens: builtins.int | None = ...,
|
||||||
|
) -> None: ...
|
||||||
|
def HasField(self, field_name: typing.Literal["_auth_max_blind_tokens", b"_auth_max_blind_tokens", "_auth_rate_limit_per_minute", b"_auth_rate_limit_per_minute", "auth_max_blind_tokens", b"auth_max_blind_tokens", "auth_rate_limit_per_minute", b"auth_rate_limit_per_minute"]) -> builtins.bool: ...
|
||||||
|
def ClearField(self, field_name: typing.Literal["_auth_max_blind_tokens", b"_auth_max_blind_tokens", "_auth_rate_limit_per_minute", b"_auth_rate_limit_per_minute", "auth_max_blind_tokens", b"auth_max_blind_tokens", "auth_rate_limit_per_minute", b"auth_rate_limit_per_minute"]) -> None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_auth_max_blind_tokens", b"_auth_max_blind_tokens"]) -> typing.Literal["auth_max_blind_tokens"] | None: ...
|
||||||
|
@typing.overload
|
||||||
|
def WhichOneof(self, oneof_group: typing.Literal["_auth_rate_limit_per_minute", b"_auth_rate_limit_per_minute"]) -> typing.Literal["auth_rate_limit_per_minute"] | None: ...
|
||||||
|
|
||||||
|
global___UpdateAuthLimitsRequest = UpdateAuthLimitsRequest
|
||||||
914
cashu/mint/management_rpc/protos/management_pb2_grpc.py
Normal file
914
cashu/mint/management_rpc/protos/management_pb2_grpc.py
Normal file
@@ -0,0 +1,914 @@
|
|||||||
|
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||||
|
"""Client and server classes corresponding to protobuf-defined services."""
|
||||||
|
|
||||||
|
import grpc
|
||||||
|
|
||||||
|
import cashu.mint.management_rpc.protos.management_pb2 as management__pb2
|
||||||
|
|
||||||
|
GRPC_GENERATED_VERSION = '1.69.0'
|
||||||
|
GRPC_VERSION = grpc.__version__
|
||||||
|
_version_not_supported = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
from grpc._utilities import first_version_is_lower
|
||||||
|
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
|
||||||
|
except ImportError:
|
||||||
|
_version_not_supported = True
|
||||||
|
|
||||||
|
if _version_not_supported:
|
||||||
|
raise RuntimeError(
|
||||||
|
f'The grpc package installed is at version {GRPC_VERSION},'
|
||||||
|
+ ' but the generated code in management_pb2_grpc.py depends on'
|
||||||
|
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
||||||
|
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
||||||
|
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MintStub(object):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
|
||||||
|
def __init__(self, channel):
|
||||||
|
"""Constructor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
channel: A grpc.Channel.
|
||||||
|
"""
|
||||||
|
self.GetInfo = channel.unary_unary(
|
||||||
|
'/management.Mint/GetInfo',
|
||||||
|
request_serializer=management__pb2.GetInfoRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.GetInfoResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.UpdateMotd = channel.unary_unary(
|
||||||
|
'/management.Mint/UpdateMotd',
|
||||||
|
request_serializer=management__pb2.UpdateMotdRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.UpdateShortDescription = channel.unary_unary(
|
||||||
|
'/management.Mint/UpdateShortDescription',
|
||||||
|
request_serializer=management__pb2.UpdateDescriptionRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.UpdateLongDescription = channel.unary_unary(
|
||||||
|
'/management.Mint/UpdateLongDescription',
|
||||||
|
request_serializer=management__pb2.UpdateDescriptionRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.UpdateIconUrl = channel.unary_unary(
|
||||||
|
'/management.Mint/UpdateIconUrl',
|
||||||
|
request_serializer=management__pb2.UpdateIconUrlRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.UpdateName = channel.unary_unary(
|
||||||
|
'/management.Mint/UpdateName',
|
||||||
|
request_serializer=management__pb2.UpdateNameRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.AddUrl = channel.unary_unary(
|
||||||
|
'/management.Mint/AddUrl',
|
||||||
|
request_serializer=management__pb2.UpdateUrlRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.RemoveUrl = channel.unary_unary(
|
||||||
|
'/management.Mint/RemoveUrl',
|
||||||
|
request_serializer=management__pb2.UpdateUrlRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.AddContact = channel.unary_unary(
|
||||||
|
'/management.Mint/AddContact',
|
||||||
|
request_serializer=management__pb2.UpdateContactRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.RemoveContact = channel.unary_unary(
|
||||||
|
'/management.Mint/RemoveContact',
|
||||||
|
request_serializer=management__pb2.UpdateContactRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.GetNut04Quote = channel.unary_unary(
|
||||||
|
'/management.Mint/GetNut04Quote',
|
||||||
|
request_serializer=management__pb2.GetNut04QuoteRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.GetNut04QuoteResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.GetNut05Quote = channel.unary_unary(
|
||||||
|
'/management.Mint/GetNut05Quote',
|
||||||
|
request_serializer=management__pb2.GetNut05QuoteRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.GetNut05QuoteResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.UpdateNut04 = channel.unary_unary(
|
||||||
|
'/management.Mint/UpdateNut04',
|
||||||
|
request_serializer=management__pb2.UpdateNut04Request.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.UpdateNut05 = channel.unary_unary(
|
||||||
|
'/management.Mint/UpdateNut05',
|
||||||
|
request_serializer=management__pb2.UpdateNut05Request.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.UpdateQuoteTtl = channel.unary_unary(
|
||||||
|
'/management.Mint/UpdateQuoteTtl',
|
||||||
|
request_serializer=management__pb2.UpdateQuoteTtlRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.UpdateNut04Quote = channel.unary_unary(
|
||||||
|
'/management.Mint/UpdateNut04Quote',
|
||||||
|
request_serializer=management__pb2.UpdateQuoteRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.UpdateNut05Quote = channel.unary_unary(
|
||||||
|
'/management.Mint/UpdateNut05Quote',
|
||||||
|
request_serializer=management__pb2.UpdateQuoteRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.RotateNextKeyset = channel.unary_unary(
|
||||||
|
'/management.Mint/RotateNextKeyset',
|
||||||
|
request_serializer=management__pb2.RotateNextKeysetRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.RotateNextKeysetResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.UpdateLightningFee = channel.unary_unary(
|
||||||
|
'/management.Mint/UpdateLightningFee',
|
||||||
|
request_serializer=management__pb2.UpdateLightningFeeRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
self.UpdateAuthLimits = channel.unary_unary(
|
||||||
|
'/management.Mint/UpdateAuthLimits',
|
||||||
|
request_serializer=management__pb2.UpdateAuthLimitsRequest.SerializeToString,
|
||||||
|
response_deserializer=management__pb2.UpdateResponse.FromString,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
|
||||||
|
class MintServicer(object):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
|
||||||
|
def GetInfo(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def UpdateMotd(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def UpdateShortDescription(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def UpdateLongDescription(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def UpdateIconUrl(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def UpdateName(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def AddUrl(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def RemoveUrl(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def AddContact(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def RemoveContact(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def GetNut04Quote(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def GetNut05Quote(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def UpdateNut04(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def UpdateNut05(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def UpdateQuoteTtl(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def UpdateNut04Quote(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def UpdateNut05Quote(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def RotateNextKeyset(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def UpdateLightningFee(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
def UpdateAuthLimits(self, request, context):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||||
|
context.set_details('Method not implemented!')
|
||||||
|
raise NotImplementedError('Method not implemented!')
|
||||||
|
|
||||||
|
|
||||||
|
def add_MintServicer_to_server(servicer, server):
|
||||||
|
rpc_method_handlers = {
|
||||||
|
'GetInfo': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.GetInfo,
|
||||||
|
request_deserializer=management__pb2.GetInfoRequest.FromString,
|
||||||
|
response_serializer=management__pb2.GetInfoResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'UpdateMotd': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.UpdateMotd,
|
||||||
|
request_deserializer=management__pb2.UpdateMotdRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'UpdateShortDescription': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.UpdateShortDescription,
|
||||||
|
request_deserializer=management__pb2.UpdateDescriptionRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'UpdateLongDescription': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.UpdateLongDescription,
|
||||||
|
request_deserializer=management__pb2.UpdateDescriptionRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'UpdateIconUrl': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.UpdateIconUrl,
|
||||||
|
request_deserializer=management__pb2.UpdateIconUrlRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'UpdateName': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.UpdateName,
|
||||||
|
request_deserializer=management__pb2.UpdateNameRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'AddUrl': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.AddUrl,
|
||||||
|
request_deserializer=management__pb2.UpdateUrlRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'RemoveUrl': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.RemoveUrl,
|
||||||
|
request_deserializer=management__pb2.UpdateUrlRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'AddContact': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.AddContact,
|
||||||
|
request_deserializer=management__pb2.UpdateContactRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'RemoveContact': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.RemoveContact,
|
||||||
|
request_deserializer=management__pb2.UpdateContactRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'GetNut04Quote': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.GetNut04Quote,
|
||||||
|
request_deserializer=management__pb2.GetNut04QuoteRequest.FromString,
|
||||||
|
response_serializer=management__pb2.GetNut04QuoteResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'GetNut05Quote': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.GetNut05Quote,
|
||||||
|
request_deserializer=management__pb2.GetNut05QuoteRequest.FromString,
|
||||||
|
response_serializer=management__pb2.GetNut05QuoteResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'UpdateNut04': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.UpdateNut04,
|
||||||
|
request_deserializer=management__pb2.UpdateNut04Request.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'UpdateNut05': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.UpdateNut05,
|
||||||
|
request_deserializer=management__pb2.UpdateNut05Request.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'UpdateQuoteTtl': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.UpdateQuoteTtl,
|
||||||
|
request_deserializer=management__pb2.UpdateQuoteTtlRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'UpdateNut04Quote': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.UpdateNut04Quote,
|
||||||
|
request_deserializer=management__pb2.UpdateQuoteRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'UpdateNut05Quote': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.UpdateNut05Quote,
|
||||||
|
request_deserializer=management__pb2.UpdateQuoteRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'RotateNextKeyset': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.RotateNextKeyset,
|
||||||
|
request_deserializer=management__pb2.RotateNextKeysetRequest.FromString,
|
||||||
|
response_serializer=management__pb2.RotateNextKeysetResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'UpdateLightningFee': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.UpdateLightningFee,
|
||||||
|
request_deserializer=management__pb2.UpdateLightningFeeRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
'UpdateAuthLimits': grpc.unary_unary_rpc_method_handler(
|
||||||
|
servicer.UpdateAuthLimits,
|
||||||
|
request_deserializer=management__pb2.UpdateAuthLimitsRequest.FromString,
|
||||||
|
response_serializer=management__pb2.UpdateResponse.SerializeToString,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
generic_handler = grpc.method_handlers_generic_handler(
|
||||||
|
'management.Mint', rpc_method_handlers)
|
||||||
|
server.add_generic_rpc_handlers((generic_handler,))
|
||||||
|
server.add_registered_method_handlers('management.Mint', rpc_method_handlers)
|
||||||
|
|
||||||
|
|
||||||
|
# This class is part of an EXPERIMENTAL API.
|
||||||
|
class Mint(object):
|
||||||
|
"""Missing associated documentation comment in .proto file."""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def GetInfo(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/GetInfo',
|
||||||
|
management__pb2.GetInfoRequest.SerializeToString,
|
||||||
|
management__pb2.GetInfoResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def UpdateMotd(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/UpdateMotd',
|
||||||
|
management__pb2.UpdateMotdRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def UpdateShortDescription(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/UpdateShortDescription',
|
||||||
|
management__pb2.UpdateDescriptionRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def UpdateLongDescription(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/UpdateLongDescription',
|
||||||
|
management__pb2.UpdateDescriptionRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def UpdateIconUrl(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/UpdateIconUrl',
|
||||||
|
management__pb2.UpdateIconUrlRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def UpdateName(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/UpdateName',
|
||||||
|
management__pb2.UpdateNameRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def AddUrl(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/AddUrl',
|
||||||
|
management__pb2.UpdateUrlRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def RemoveUrl(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/RemoveUrl',
|
||||||
|
management__pb2.UpdateUrlRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def AddContact(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/AddContact',
|
||||||
|
management__pb2.UpdateContactRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def RemoveContact(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/RemoveContact',
|
||||||
|
management__pb2.UpdateContactRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def GetNut04Quote(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/GetNut04Quote',
|
||||||
|
management__pb2.GetNut04QuoteRequest.SerializeToString,
|
||||||
|
management__pb2.GetNut04QuoteResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def GetNut05Quote(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/GetNut05Quote',
|
||||||
|
management__pb2.GetNut05QuoteRequest.SerializeToString,
|
||||||
|
management__pb2.GetNut05QuoteResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def UpdateNut04(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/UpdateNut04',
|
||||||
|
management__pb2.UpdateNut04Request.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def UpdateNut05(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/UpdateNut05',
|
||||||
|
management__pb2.UpdateNut05Request.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def UpdateQuoteTtl(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/UpdateQuoteTtl',
|
||||||
|
management__pb2.UpdateQuoteTtlRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def UpdateNut04Quote(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/UpdateNut04Quote',
|
||||||
|
management__pb2.UpdateQuoteRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def UpdateNut05Quote(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/UpdateNut05Quote',
|
||||||
|
management__pb2.UpdateQuoteRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def RotateNextKeyset(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/RotateNextKeyset',
|
||||||
|
management__pb2.RotateNextKeysetRequest.SerializeToString,
|
||||||
|
management__pb2.RotateNextKeysetResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def UpdateLightningFee(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/UpdateLightningFee',
|
||||||
|
management__pb2.UpdateLightningFeeRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def UpdateAuthLimits(request,
|
||||||
|
target,
|
||||||
|
options=(),
|
||||||
|
channel_credentials=None,
|
||||||
|
call_credentials=None,
|
||||||
|
insecure=False,
|
||||||
|
compression=None,
|
||||||
|
wait_for_ready=None,
|
||||||
|
timeout=None,
|
||||||
|
metadata=None):
|
||||||
|
return grpc.experimental.unary_unary(
|
||||||
|
request,
|
||||||
|
target,
|
||||||
|
'/management.Mint/UpdateAuthLimits',
|
||||||
|
management__pb2.UpdateAuthLimitsRequest.SerializeToString,
|
||||||
|
management__pb2.UpdateResponse.FromString,
|
||||||
|
options,
|
||||||
|
channel_credentials,
|
||||||
|
insecure,
|
||||||
|
call_credentials,
|
||||||
|
compression,
|
||||||
|
wait_for_ready,
|
||||||
|
timeout,
|
||||||
|
metadata,
|
||||||
|
_registered_method=True)
|
||||||
@@ -3,10 +3,13 @@
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import importlib
|
import importlib
|
||||||
|
from copy import copy
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
|
import cashu.mint.management_rpc.management_rpc as management_rpc
|
||||||
|
|
||||||
from ..core.base import Method, Unit
|
from ..core.base import Method, Unit
|
||||||
from ..core.db import Database
|
from ..core.db import Database
|
||||||
from ..core.migrations import migrate_databases
|
from ..core.migrations import migrate_databases
|
||||||
@@ -129,3 +132,12 @@ async def shutdown_mint():
|
|||||||
await ledger.shutdown_ledger()
|
await ledger.shutdown_ledger()
|
||||||
logger.info("Mint shutdown.")
|
logger.info("Mint shutdown.")
|
||||||
logger.remove()
|
logger.remove()
|
||||||
|
|
||||||
|
rpc_server = None
|
||||||
|
async def start_management_rpc():
|
||||||
|
global rpc_server
|
||||||
|
rpc_server = await management_rpc.serve(copy(ledger))
|
||||||
|
|
||||||
|
async def shutdown_management_rpc():
|
||||||
|
if rpc_server:
|
||||||
|
await management_rpc.shutdown(rpc_server)
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ asyncio_default_fixture_loop_scope = "function"
|
|||||||
[tool.poetry.scripts]
|
[tool.poetry.scripts]
|
||||||
mint = "cashu.mint.main:main"
|
mint = "cashu.mint.main:main"
|
||||||
cashu = "cashu.wallet.cli.cli:cli"
|
cashu = "cashu.wallet.cli.cli:cli"
|
||||||
|
mint-cli = "cashu.mint.management_rpc.cli.cli:cli"
|
||||||
wallet-test = "tests.test_wallet:test"
|
wallet-test = "tests.test_wallet:test"
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ settings.db_connection_pool = True
|
|||||||
settings.mint_require_auth = False
|
settings.mint_require_auth = False
|
||||||
settings.mint_watchdog_enabled = False
|
settings.mint_watchdog_enabled = False
|
||||||
|
|
||||||
|
settings.mint_rpc_server_enable = True
|
||||||
|
settings.mint_rpc_server_mutual_tls = False
|
||||||
|
|
||||||
assert "test" in settings.cashu_dir
|
assert "test" in settings.cashu_dir
|
||||||
shutil.rmtree(settings.cashu_dir, ignore_errors=True)
|
shutil.rmtree(settings.cashu_dir, ignore_errors=True)
|
||||||
Path(settings.cashu_dir).mkdir(parents=True, exist_ok=True)
|
Path(settings.cashu_dir).mkdir(parents=True, exist_ok=True)
|
||||||
|
|||||||
@@ -18,10 +18,15 @@ from cashu.wallet.wallet import Wallet
|
|||||||
from tests.conftest import SERVER_ENDPOINT
|
from tests.conftest import SERVER_ENDPOINT
|
||||||
from tests.helpers import (
|
from tests.helpers import (
|
||||||
assert_err,
|
assert_err,
|
||||||
|
is_deprecated_api_only,
|
||||||
is_github_actions,
|
is_github_actions,
|
||||||
pay_if_regtest,
|
pay_if_regtest,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
payment_request = (
|
||||||
|
"lnbc1u1p5qeft3sp5jn5cqclnxvucfqtjm8qnlar2vhevcuudpccv7tsuglruj3qm579spp5ygdhy0t7xu53myke8z3z024xhz4kzgk9fcqk64sp0fyeqzhmaswqdqqcqpjrzjq0euzzxv65mts5ngg8c2t3vzz2aeuevy5845jvyqulqucd8c9kkhzrtp55qq63qqqqqqqqqqqqqzwyqqyg9qxpqysgqscprcpnk8whs3askqhgu6z5a4hupyn8du2aahdcf00s5pxrs4g94sv9f95xdn4tu0wec7kfyzj439wu9z27k6m6e3q4ysjquf5agx7gp0eeye4"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest_asyncio.fixture(scope="function")
|
@pytest_asyncio.fixture(scope="function")
|
||||||
async def wallet(ledger: Ledger):
|
async def wallet(ledger: Ledger):
|
||||||
@@ -289,3 +294,31 @@ async def test_db_events_add_client(wallet: Wallet, ledger: Ledger):
|
|||||||
|
|
||||||
# remove subscription
|
# remove subscription
|
||||||
client.remove_subscription("subId")
|
client.remove_subscription("subId")
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_db_update_mint_quote_state(wallet: Wallet, ledger: Ledger):
|
||||||
|
mint_quote = await wallet.request_mint(128)
|
||||||
|
await ledger.db_write._update_mint_quote_state(mint_quote.quote, MintQuoteState.paid)
|
||||||
|
|
||||||
|
mint_quote_db = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
|
||||||
|
assert mint_quote_db.state == MintQuoteState.paid
|
||||||
|
|
||||||
|
# Update it to issued
|
||||||
|
await ledger.db_write._update_mint_quote_state(mint_quote_db.quote, MintQuoteState.issued)
|
||||||
|
|
||||||
|
# Try and revert it back to unpaid
|
||||||
|
await assert_err(ledger.db_write._update_mint_quote_state(mint_quote_db.quote, MintQuoteState.unpaid), "Cannot change state of an issued mint quote.")
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
is_deprecated_api_only,
|
||||||
|
reason=("Deprecated API")
|
||||||
|
)
|
||||||
|
async def test_db_update_melt_quote_state(wallet: Wallet, ledger: Ledger):
|
||||||
|
melt_quote = await wallet.melt_quote(payment_request)
|
||||||
|
await ledger.db_write._update_melt_quote_state(melt_quote.quote, MeltQuoteState.paid)
|
||||||
|
|
||||||
|
melt_quote_db = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db)
|
||||||
|
assert melt_quote_db.state == MeltQuoteState.paid
|
||||||
|
|
||||||
|
await assert_err(ledger.db_write._update_melt_quote_state(melt_quote.quote, MeltQuoteState.unpaid), "Cannot change state of a paid melt quote.")
|
||||||
165
tests/test_mint_rpc_cli.py
Normal file
165
tests/test_mint_rpc_cli.py
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
import asyncio
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from click.testing import CliRunner
|
||||||
|
|
||||||
|
from cashu.core.settings import settings
|
||||||
|
from cashu.mint.management_rpc.cli.cli import cli
|
||||||
|
from cashu.wallet.wallet import Wallet
|
||||||
|
|
||||||
|
from .helpers import is_deprecated_api_only, is_fake
|
||||||
|
|
||||||
|
payment_request = (
|
||||||
|
"lnbc10u1pjap7phpp50s9lzr3477j0tvacpfy2ucrs4q0q6cvn232ex7nt2zqxxxj8gxrsdpv2phhwetjv4jzqcneypqyc6t8dp6xu6twva2xjuzzda6qcqzzsxqrrsss"
|
||||||
|
"p575z0n39w2j7zgnpqtdlrgz9rycner4eptjm3lz363dzylnrm3h4s9qyyssqfz8jglcshnlcf0zkw4qu8fyr564lg59x5al724kms3h6gpuhx9xrfv27tgx3l3u3cyf6"
|
||||||
|
"3r52u0xmac6max8mdupghfzh84t4hfsvrfsqwnuszf"
|
||||||
|
)
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def cli_prefix():
|
||||||
|
yield ["--insecure", "--host", settings.mint_rpc_server_addr, "--port", settings.mint_rpc_server_port]
|
||||||
|
|
||||||
|
async def init_wallet():
|
||||||
|
settings.debug = False
|
||||||
|
wallet = await Wallet.with_db(
|
||||||
|
url=settings.mint_url,
|
||||||
|
db="test_data/test_cli_wallet",
|
||||||
|
name="test_cli_wallet",
|
||||||
|
)
|
||||||
|
await wallet.load_proofs()
|
||||||
|
return wallet
|
||||||
|
|
||||||
|
def test_get_info(cli_prefix):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "get-info"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Mint Info:" in result.output
|
||||||
|
|
||||||
|
def test_update_motd(cli_prefix):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "motd", "Updated MOTD"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Motd successfully updated!" in result.output
|
||||||
|
|
||||||
|
def test_update_short_description(cli_prefix):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "description", "New short description"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Short description successfully updated!" in result.output
|
||||||
|
|
||||||
|
def test_update_long_description(cli_prefix):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "long-description", "New long description"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Long description successfully updated!" in result.output
|
||||||
|
|
||||||
|
def test_update_icon_url(cli_prefix):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "icon-url", "http://example.com/icon.png"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Icon url successfully updated!" in result.output
|
||||||
|
|
||||||
|
def test_update_name(cli_prefix):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "name", "New Mint Name"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Name successfully updated!" in result.output
|
||||||
|
|
||||||
|
def test_add_mint_url(cli_prefix):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "url", "add", "http://example.com"])
|
||||||
|
assert "Url successfully added!" in result.output
|
||||||
|
|
||||||
|
def test_remove_mint_url(cli_prefix):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "url", "remove", "http://example.com"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Url successfully removed!" in result.output or "Contact method not found" in result.output
|
||||||
|
|
||||||
|
def test_add_remove_contact(cli_prefix):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "contact", "add", "signal", "@example.420"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Contact successfully added!" in result.output
|
||||||
|
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "contact", "remove", "signal"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Contact successfully removed!" in result.output
|
||||||
|
|
||||||
|
def test_update_lightning_fee(cli_prefix):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "lightning-fee", "2.5", "100"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Lightning fee successfully updated!" in result.output
|
||||||
|
|
||||||
|
def test_update_auth_limits(cli_prefix):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "auth", "60", "10"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Rate limit per minute successfully updated!" in result.output
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.skipif(not is_fake,
|
||||||
|
reason=(
|
||||||
|
"Only FakeWallet will mark the quote as paid"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
async def test_update_mint_quote(cli_prefix):
|
||||||
|
wallet = await init_wallet()
|
||||||
|
mint_quote = await wallet.request_mint(100)
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "mint-quote", mint_quote.quote, "ISSUED"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Successfully updated!" in result.output
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
is_deprecated_api_only,
|
||||||
|
reason=("Deprecated API"),
|
||||||
|
)
|
||||||
|
async def test_update_melt_quote(cli_prefix):
|
||||||
|
wallet = await init_wallet()
|
||||||
|
melt_quote = await wallet.melt_quote("lnbc1u1p5qefdgsp5xj5cl559ks226f3vf3d7x2ev2qadplmkswp4649h755cfekdufsspp5sxenacdev78ssuwn5vehycs7ch2ds23hhzytut4ncm27gywtv6rqdqqcqpjrzjqdgp5ar48c8k4cns58jw9lamcdlh57trvrn9psgjrsvwz94j9tqsvrqsvcqqvqsqqqqqqqlgqqqzwyqq2q9qxpqysgqzg8e75zkcxazmd0wqmre6xgkumt7sl4ftsw0q4c6zvz8hn6zjxwz9fmdmwpupw7tw79f7gmukyeeh8vusvt03pgwfud9shj849rvrnqpgcpusw")
|
||||||
|
assert melt_quote.quote
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "update", "melt-quote", melt_quote.quote, "PAID"])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "Successfully updated!" in result.output
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_mint_quote(cli_prefix):
|
||||||
|
wallet = await init_wallet()
|
||||||
|
mint_quote = await wallet.request_mint(100)
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "get", "mint-quote", mint_quote.quote])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "mint quote:" in result.output
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
is_deprecated_api_only,
|
||||||
|
reason=("Deprecated API"),
|
||||||
|
)
|
||||||
|
async def test_get_melt_quote(cli_prefix):
|
||||||
|
wallet = await init_wallet()
|
||||||
|
melt_quote = await wallet.melt_quote("lnbc1u1p5qefd7sp55l6kmcrnqz5rejy4lghmgf9de0ucmmn2s3lvkvtkrr0qkwk5r0espp5da4x63rspz5rcfretdh6573c6qlpnzpxc8yq26cyqjc4sk0srfwsdqqcqpjrzjqv3dpepm8kfdxrk3sl6wzqdf49s9c0h9ljtjrek6c08r6aejlwcnur2z3sqqrrgqqyqqqqqqqqqqfcsqjq9qxpqysgq4l5rfjd4h84w7prmtgzjvq79ddy266svuz0d7dg44jmnwjpxg0zxef6hn4j8nzfp4c67qjpe0c9aw63ghu7rtcdg6n4zka9hym69euqq8w5wmj")
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "get", "melt-quote", melt_quote.quote])
|
||||||
|
assert result.exception is None
|
||||||
|
assert "melt quote:" in result.output
|
||||||
|
|
||||||
|
'''
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_rotate_next_keyset(cli_prefix):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(cli, [*cli_prefix, "next-keyset", "sat", "2"]) # Rotate keyset and add a 2 sat ppk fee
|
||||||
|
assert result.exception is None
|
||||||
|
print(result.output)
|
||||||
|
assert "New keyset successfully created:" in result.output
|
||||||
|
assert "keyset.unit = 'sat'" in result.output
|
||||||
|
assert "keyset.input_fee_ppk = 2" in result.output
|
||||||
|
'''
|
||||||
Reference in New Issue
Block a user