From 5bbc458f92c8b63e28c21d4fc8d7ed905474802e Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 11:00:39 +0200 Subject: [PATCH 01/24] feat(mint): Add Spark L2 wallet backend with Node sidecar --- cashu/core/settings.py | 4 + cashu/lightning/__init__.py | 1 + cashu/lightning/sparkl2.py | 236 ++ cashu/lightning/sparkl2_bridge/.gitignore | 3 + cashu/lightning/sparkl2_bridge/README.md | 29 + .../sparkl2_bridge/package-lock.json | 2782 +++++++++++++++++ cashu/lightning/sparkl2_bridge/package.json | 22 + cashu/lightning/sparkl2_bridge/src/index.ts | 176 ++ cashu/lightning/sparkl2_bridge/tsconfig.json | 12 + 9 files changed, 3265 insertions(+) create mode 100644 cashu/lightning/sparkl2.py create mode 100644 cashu/lightning/sparkl2_bridge/.gitignore create mode 100644 cashu/lightning/sparkl2_bridge/README.md create mode 100644 cashu/lightning/sparkl2_bridge/package-lock.json create mode 100644 cashu/lightning/sparkl2_bridge/package.json create mode 100644 cashu/lightning/sparkl2_bridge/src/index.ts create mode 100644 cashu/lightning/sparkl2_bridge/tsconfig.json diff --git a/cashu/core/settings.py b/cashu/core/settings.py index 5723fe519..967a08119 100644 --- a/cashu/core/settings.py +++ b/cashu/core/settings.py @@ -116,6 +116,10 @@ class MintBackends(MintSettings): mint_strike_key: Optional[str] = Field(default=None) mint_blink_key: Optional[str] = Field(default=None) + mint_spark_bridge_host: str = Field(default="127.0.0.1") + mint_spark_bridge_port: int = Field(default=8426) + mint_spark_network: str = Field(default="TESTNET") + class MintLimits(MintSettings): mint_rate_limit: bool = Field( diff --git a/cashu/lightning/__init__.py b/cashu/lightning/__init__.py index dfa66b941..a1e4b35b4 100644 --- a/cashu/lightning/__init__.py +++ b/cashu/lightning/__init__.py @@ -7,6 +7,7 @@ from .lnbits import LNbitsWallet # noqa: F401 from .lnd_grpc.lnd_grpc import LndRPCWallet # noqa: F401 from .lndrest import LndRestWallet # noqa: F401 +from .sparkl2 import SparkL2Wallet # noqa: F401 from .strike import StrikeWallet # noqa: F401 backend_settings = [ diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py new file mode 100644 index 000000000..25180524c --- /dev/null +++ b/cashu/lightning/sparkl2.py @@ -0,0 +1,236 @@ +import asyncio +import os +from typing import Any, AsyncGenerator, Dict, Optional + +import bolt11 +import httpx + +from cashu.core.base import Amount, MeltQuote, Unit +from cashu.core.models import PostMeltQuoteRequest +from cashu.core.settings import settings +from cashu.lightning.base import ( + InvoiceResponse, + LightningBackend, + PaymentQuoteResponse, + PaymentResponse, + PaymentResult, + PaymentStatus, + StatusResponse, +) + + +class SparkL2Wallet(LightningBackend): + """ + Spark L2 Wallet backend. + Communicates with the local Node.js bridge which wraps the Spark TypeScript SDK. + """ + + supported_units = {Unit.sat, Unit.msat} + supports_mpp = False + supports_incoming_payment_stream = True + supports_description = True + + def __init__(self, unit: Unit, **kwargs): + self.assert_unit_supported(unit) + self.unit = unit + + # Read from config or defaults + host = getattr(settings, "mint_spark_bridge_host", "127.0.0.1") + port = getattr(settings, "mint_spark_bridge_port", 8426) + self.base_url = f"http://{host}:{port}" + + self.client = httpx.AsyncClient(base_url=self.base_url) + + async def _ensure_bridge_running(self): + try: + await self.client.get("/status", timeout=1) + # If we get a response (even 400 not initialized), it's running. + except httpx.RequestError: + import subprocess + bridge_dir = os.path.join(os.path.dirname(__file__), "sparkl2_bridge") + # Try to start it + try: + subprocess.Popen(["npm", "start"], cwd=bridge_dir, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + await asyncio.sleep(3) # Wait for it to start + except Exception as e: + print(f"Warning: Failed to start Spark L2 bridge automatically: {e}") + + async def status(self) -> StatusResponse: + await self._ensure_bridge_running() + try: + # Initialize the bridge if necessary + if settings.mint_private_key: + await self.client.post("/init", json={ + "seed": settings.mint_private_key, + "network": getattr(settings, "mint_spark_network", "TESTNET") + }, timeout=15) + + r = await self.client.get("/status", timeout=5) + r.raise_for_status() + data = r.json() + balance_sats = data.get("balanceSats", 0) + balance = Amount(Unit.sat, balance_sats) + if self.unit == Unit.msat: + balance = Amount(Unit.msat, balance_sats * 1000) + return StatusResponse(balance=balance) + except Exception as e: + return StatusResponse( + error_message=f"Failed to connect to Spark bridge: {str(e)}", + balance=Amount(self.unit, 0), + ) + + async def create_invoice( + self, + amount: Amount, + memo: Optional[str] = None, + description_hash: Optional[bytes] = None, + **kwargs, + ) -> InvoiceResponse: + self.assert_unit_supported(amount.unit) + amount_sats = amount.to(Unit.sat, round="up").amount + + payload: Dict[str, Any] = { + "amountSats": amount_sats, + "memo": memo, + } + if description_hash: + payload["descriptionHash"] = description_hash.hex() + # Spark SDK doesn't allow both memo and descriptionHash + payload.pop("memo", None) + + try: + r = await self.client.post("/invoice", json=payload, timeout=10) + r.raise_for_status() + data = r.json() + return InvoiceResponse( + ok=True, + checking_id=data["id"], + payment_request=data["invoice"], + ) + except Exception as e: + return InvoiceResponse( + ok=False, + error_message=f"Failed to create invoice: {str(e)}" + ) + + async def pay_invoice( + self, quote: MeltQuote, fee_limit_msat: int + ) -> PaymentResponse: + try: + payload = { + "invoice": quote.request, + "maxFeeSats": fee_limit_msat // 1000 + } + r = await self.client.post("/pay", json=payload, timeout=30) + r.raise_for_status() + data = r.json() + + return PaymentResponse( + result=PaymentResult.PENDING, + checking_id=data["id"], + ) + except Exception as e: + return PaymentResponse( + result=PaymentResult.FAILED, + error_message=f"Payment failed: {str(e)}" + ) + + async def get_invoice_status(self, checking_id: str) -> PaymentStatus: + try: + r = await self.client.get(f"/invoice/status/{checking_id}", timeout=5) + r.raise_for_status() + data = r.json() + + status_str = data.get("status", "") + if status_str in ("LIGHTNING_RECEIVE_SUCCEEDED", "CLAIMED", "PAID"): + return PaymentStatus(result=PaymentResult.SETTLED) + elif status_str in ("EXPIRED", "FAILED"): + return PaymentStatus(result=PaymentResult.FAILED) + else: + return PaymentStatus(result=PaymentResult.PENDING) + + except Exception as e: + return PaymentStatus(result=PaymentResult.UNKNOWN, error_message=str(e)) + + async def get_payment_status(self, checking_id: str) -> PaymentStatus: + try: + r = await self.client.get(f"/pay/status/{checking_id}", timeout=5) + r.raise_for_status() + data = r.json() + + status_str = data.get("status", "") + preimage = data.get("preimage") + fee_sats = data.get("feeSats") + + fee_amount = None + if fee_sats is not None: + fee_amount = Amount(Unit.sat, fee_sats) + if self.unit == Unit.msat: + fee_amount = Amount(Unit.msat, fee_sats * 1000) + + if status_str in ("LIGHTNING_PAYMENT_SUCCEEDED", "TRANSFER_COMPLETED"): + return PaymentStatus( + result=PaymentResult.SETTLED, + preimage=preimage, + fee=fee_amount + ) + elif status_str in ("LIGHTNING_PAYMENT_FAILED", "TRANSFER_FAILED", "USER_SWAP_RETURN_FAILED", "PREIMAGE_PROVIDING_FAILED"): + return PaymentStatus(result=PaymentResult.FAILED) + else: + return PaymentStatus(result=PaymentResult.PENDING) + + except Exception as e: + return PaymentStatus(result=PaymentResult.UNKNOWN, error_message=str(e)) + + async def get_payment_quote( + self, melt_quote: PostMeltQuoteRequest + ) -> PaymentQuoteResponse: + try: + payload = {"invoice": melt_quote.request} + r = await self.client.post("/pay/quote", json=payload, timeout=5) + r.raise_for_status() + data = r.json() + + fee_sats = data.get("feeSats", 0) + fee_amount = Amount(Unit.sat, fee_sats) + if self.unit == Unit.msat: + fee_amount = Amount(Unit.msat, fee_sats * 1000) + + # Normally parsed from invoice, but we need amount. + # Usually the Mint handles invoice parsing via decode_invoice. + # So amount is handled outside, but get_payment_quote requires checking_id and amount + + invoice_obj = bolt11.decode(melt_quote.request) + amount_msat = int(invoice_obj.amount_msat) if invoice_obj.amount_msat else 0 + amount_unit = Amount(Unit.msat, amount_msat) + + if self.unit == Unit.sat: + fee_amount = Amount(Unit.sat, fee_amount.to(Unit.sat, round="up").amount) + amount_unit = Amount(Unit.sat, amount_unit.to(Unit.sat, round="up").amount) + + return PaymentQuoteResponse( + checking_id=invoice_obj.payment_hash, + fee=fee_amount, + amount=amount_unit, + ) + except Exception as e: + raise Exception(f"Failed to get payment quote: {str(e)}") + + async def paid_invoices_stream(self) -> AsyncGenerator[str, None]: + while True: + try: + async with self.client.stream("GET", "/stream", timeout=None) as r: + async for line in r.aiter_lines(): + if line.startswith("data:"): + try: + import json + data = json.loads(line[5:].strip()) + # Assuming the bridge emits the full event object + # The event structure might have 'id' or 'transferId' + checking_id = data.get("id") or data.get("transferId") or data.get("paymentHash") + if checking_id: + yield checking_id + except Exception: + pass + except Exception: + await asyncio.sleep(5) diff --git a/cashu/lightning/sparkl2_bridge/.gitignore b/cashu/lightning/sparkl2_bridge/.gitignore new file mode 100644 index 000000000..deed335be --- /dev/null +++ b/cashu/lightning/sparkl2_bridge/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +dist/ +.env diff --git a/cashu/lightning/sparkl2_bridge/README.md b/cashu/lightning/sparkl2_bridge/README.md new file mode 100644 index 000000000..8775a1da5 --- /dev/null +++ b/cashu/lightning/sparkl2_bridge/README.md @@ -0,0 +1,29 @@ +# Spark L2 Bridge for Nutshell + +This directory contains a Node.js sidecar service that wraps the official `@buildonspark/spark-sdk` to provide a Spark L2 wallet backend for Nutshell. + +## Prerequisites +- Node.js (v18+) +- npm + +## Setup +Run the following command to install dependencies: +```bash +npm install +``` + +Nutshell will automatically try to start the bridge process via `npm start` if it is not already running. + +Alternatively, you can start it manually: +```bash +npm start +``` + +## Configuration +In your `.env` file, enable the backend by setting: +```env +MINT_BACKEND_BOLT11_SAT=SparkL2Wallet +MINT_SPARK_NETWORK=TESTNET # or MAINNET +``` + +Nutshell will automatically POST your `MINT_PRIVATE_KEY` to the bridge to initialize the deterministic wallet seed. diff --git a/cashu/lightning/sparkl2_bridge/package-lock.json b/cashu/lightning/sparkl2_bridge/package-lock.json new file mode 100644 index 000000000..bc69aff50 --- /dev/null +++ b/cashu/lightning/sparkl2_bridge/package-lock.json @@ -0,0 +1,2782 @@ +{ + "name": "sparkl2-bridge", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "sparkl2-bridge", + "version": "1.0.0", + "dependencies": { + "@buildonspark/spark-sdk": "^0.5.7", + "cors": "^2.8.5", + "express": "^4.19.2" + }, + "devDependencies": { + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/node": "^20.12.7", + "ts-node": "^10.9.2", + "typescript": "^5.4.5" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.12.0.tgz", + "integrity": "sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@buildonspark/spark-sdk": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@buildonspark/spark-sdk/-/spark-sdk-0.5.10.tgz", + "integrity": "sha512-7nKm54aS/V9ZsFgRQBT+HPvTQMqUGLQpboETXMFkHyppfBPhRj6T6dw4C50UwFBlz/qOJaleGP/ko5wuh+e4Jw==", + "license": "Apache-2.0", + "dependencies": { + "@bufbuild/protobuf": "^2.2.5", + "@lightsparkdev/core": "^1.4.4", + "@noble/curves": "^1.8.0", + "@noble/hashes": "^1.7.0", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^2.0.0", + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.203.0", + "@opentelemetry/instrumentation-undici": "^0.14.0", + "@opentelemetry/sdk-trace-base": "^2.0.0", + "@opentelemetry/sdk-trace-node": "^2.0.1", + "@opentelemetry/sdk-trace-web": "^2.0.1", + "@scure/base": "^1.2.4", + "@scure/bip32": "^1.6.2", + "@scure/bip39": "^1.5.4", + "@scure/btc-signer": "^1.5.0", + "abort-controller-x": "^0.4.3", + "abortcontroller-polyfill": "^1.7.8", + "async-mutex": "^0.5.0", + "bare-crypto": "^1.9.2", + "bare-fetch": "^2.4.1", + "buffer": "^6.0.3", + "eventemitter3": "^5.0.1", + "js-base64": "^3.7.7", + "light-bolt11-decoder": "^3.2.0", + "nice-grpc": "^2.1.10", + "nice-grpc-client-middleware-retry": "^3.1.10", + "nice-grpc-common": "^2.0.2", + "nice-grpc-opentelemetry": "^0.1.18", + "nice-grpc-web": "^3.3.7", + "ts-proto": "2.8.3", + "ua-parser-js": "^2.0.6", + "uuidv7": "^1.0.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": ">=18.2.0", + "react-native": ">=0.71.0", + "react-native-get-random-values": ">=1.11.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-native": { + "optional": true + }, + "react-native-get-random-values": { + "optional": true + } + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.4.tgz", + "integrity": "sha512-k9Dj3DV/itK9D06Y8f190Qgop7/Ui+D0njFV3LHMPwPT75DpXLQohE9Wmz0QElrJnzsjB7KPWiKJbOl7IPDArQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.8.0", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.1.tgz", + "integrity": "sha512-wtF6h+DY6M3YaDBPAmvuuA6jV8Sif9MjtOI5euKFWRgCDl5PeDpPsHR9u2l6St5ceY8AZgoNDww5+HvEsXFsGg==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.5.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@lightsparkdev/core": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@lightsparkdev/core/-/core-1.5.2.tgz", + "integrity": "sha512-7EiV/Ld+IqAQJYvSLN2gS6E/UrcCCQ/H4voUz+nAPUDSk8U1P06afTKALh1FeizAXIzqxt1jFQWmQlXPSXmxIA==", + "license": "Apache-2.0", + "dependencies": { + "@noble/curves": "^1.9.7", + "dayjs": "^1.11.7", + "graphql": "^16.6.0", + "graphql-ws": "^5.11.3", + "ws": "^8.12.1", + "zen-observable-ts": "^1.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", + "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz", + "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.7.1.tgz", + "integrity": "sha512-OPFBYuXEn1E4ja3Y6eeA7O+ZnLBNcXTV5Cgsn1VaqBZ6hC5FnpZPLBNme1LJY8ZtF4aOujPKFoeWN4ik487KuQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.7.1.tgz", + "integrity": "sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.203.0.tgz", + "integrity": "sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.203.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.14.0.tgz", + "integrity": "sha512-2HN+7ztxAReXuxzrtA3WboAKlfP5OsPA57KQn2AdYZbJ3zeRPcLXyW4uO/jpLE6PLm0QRtmeGCmfYpqRlwgSwg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.203.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.1.tgz", + "integrity": "sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-node": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.7.1.tgz", + "integrity": "sha512-pCpQxU68lV+I9s9svqMyVu5iHdDDUnqUpSxqwyCU8A9ejEsSnMPCbearwsUO4yk08ZJzAIUCFuReMdVQvHrdvg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/context-async-hooks": "2.7.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-web": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-web/-/sdk-trace-web-2.7.1.tgz", + "integrity": "sha512-K806OouCSOjMd8Nr7+ZCq3QT22tdAzzS/7h8vprfiKjkgFQ99/dvwU8d12WJANA6D5Qtme65hyBAqAu9CkQuxQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.41.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.41.1.tgz", + "integrity": "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz", + "integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", + "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", + "license": "BSD-3-Clause" + }, + "node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", + "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.9.0", + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", + "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/btc-signer": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@scure/btc-signer/-/btc-signer-1.8.1.tgz", + "integrity": "sha512-8nX9T++dFyKpvqksNHfSi9CgRsGnHAQtCdIQ1y1GmbCGLpV97v4MUyemUUT6uDumKL3oo3m4niyY6A32nmdLuQ==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.9.0", + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5", + "micro-packed": "~0.7.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "^1" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.41", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.41.tgz", + "integrity": "sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/zen-observable": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.3.tgz", + "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==", + "license": "MIT" + }, + "node_modules/abort-controller-x": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.4.3.tgz", + "integrity": "sha512-VtUwTNU8fpMwvWGn4xE93ywbogTYsuT+AUxAXOeelbXuQVIwNmC5YLeho9sH4vZ4ITW8414TTAOG1nW6uIVHCA==", + "license": "MIT" + }, + "node_modules/abortcontroller-polyfill": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.8.tgz", + "integrity": "sha512-9f1iZ2uWh92VcrU9Y8x+LdM4DLj75VE0MJB8zuF1iUnroEptStw+DQ8EQPMUdfe5k+PkB1uUfDQfWbhstH8LrQ==", + "license": "MIT" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/async-mutex": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", + "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/b4a": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", + "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/bare-ansi-escapes": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/bare-ansi-escapes/-/bare-ansi-escapes-2.2.3.tgz", + "integrity": "sha512-02ES4/E2RbrtZSnHJ9LntBhYkLA6lPpSEeP8iqS3MccBIVhVBlEmruF1I7HZqx5Q8aiTeYfQVeqmrU9YO2yYoQ==", + "license": "Apache-2.0", + "dependencies": { + "bare-stream": "^2.6.5" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-assert": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bare-assert/-/bare-assert-1.2.0.tgz", + "integrity": "sha512-c6uvgvTJBspTDxtVnPgrBKmLgcpW3Fp72NVKDLg6oT4QjQbhGtvrkHMhGYMK1sh4vjBHOBmuUalyt9hSzV37fQ==", + "license": "Apache-2.0", + "dependencies": { + "bare-inspect": "^3.1.2" + } + }, + "node_modules/bare-buffer": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/bare-buffer/-/bare-buffer-3.6.0.tgz", + "integrity": "sha512-/maRWEQ2eBkVNMbNFVsq1pHXJYVj4Y3AixwruB24eKZDs5Gtu0fixzvjYmBIuTsBMtVH5Yb27pQO9BhFa+IlIQ==", + "license": "Apache-2.0", + "engines": { + "bare": ">=1.20.0" + } + }, + "node_modules/bare-crypto": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/bare-crypto/-/bare-crypto-1.13.7.tgz", + "integrity": "sha512-gvYgECS1X1wDXFuipwgrN1kwOovMP+BNpaSnRcKRZeT0wYrZIDf9H48BpdWd0t81nmCWtfbpKZhWBziUwLY05Q==", + "license": "Apache-2.0", + "dependencies": { + "bare-assert": "^1.2.0", + "bare-stream": "^2.6.3" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-dns": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/bare-dns/-/bare-dns-2.1.4.tgz", + "integrity": "sha512-abwjHmpWqSRNB7V5615QxPH92L71AVzFm/kKTs8VYiNTAi2xVdonpv0BjJ0hwXLwomoW+xsSOPjW6PZPO14asg==", + "license": "Apache-2.0", + "engines": { + "bare": ">=1.7.0" + } + }, + "node_modules/bare-events": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.3.tgz", + "integrity": "sha512-HdUm8EMQBLaJvGUdidNNbqpA1kYkwNcb+MYxkxCLAPJGQzlv9J0C24h8V65Z4c5GLd/JEALDvpFCQgpLJqc0zw==", + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/bare-fetch": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/bare-fetch/-/bare-fetch-2.9.1.tgz", + "integrity": "sha512-OqyubfnEXu9BqIVXg+LcdsutZk+amvPey2N+FeG7zeIk+0qarDreAMtixcRGvpR95rM1SNJedHRpBv3BNjja5g==", + "license": "Apache-2.0", + "dependencies": { + "bare-form-data": "^1.2.0", + "bare-http1": "^4.5.2", + "bare-https": "^3.0.0", + "bare-mime": "^1.0.0", + "bare-stream": "^2.9.1", + "bare-url": "^2.4.0", + "bare-zlib": "^1.3.0" + }, + "peerDependencies": { + "bare-abort-controller": "*", + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + }, + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-form-data": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bare-form-data/-/bare-form-data-1.2.2.tgz", + "integrity": "sha512-DQyAkCf5mgKT07orewuvaJfoalw7RBSHia4wgkrG7+seI6aHLB+r6gMRdCGrlO+BmCqMwgTeHAHxDU2NrOjQnQ==", + "license": "Apache-2.0", + "dependencies": { + "bare-buffer": "^3.6.0", + "bare-stream": "^2.6.5" + } + }, + "node_modules/bare-http-parser": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bare-http-parser/-/bare-http-parser-1.1.4.tgz", + "integrity": "sha512-DL+7fTEUWzAEj/Baw9e/BwNAidARbxuUf5bonQ/Wt3VPUdJNyf562ydaono9ZkQBAUw0NydzYEI97rSs/93ruA==", + "license": "Apache-2.0" + }, + "node_modules/bare-http1": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/bare-http1/-/bare-http1-4.5.6.tgz", + "integrity": "sha512-31OAwMkSU+z1VuUOCk65hx3aWQgzCfH/zQ6LGxbJtmiy2Czsw0+uvOBM9YkqaL6zUSTSYG2pLbL0v/TjME3Buw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.6.0", + "bare-http-parser": "^1.1.1", + "bare-stream": "^2.10.0", + "bare-tcp": "^2.2.0" + }, + "peerDependencies": { + "bare-buffer": "*", + "bare-url": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + }, + "bare-url": { + "optional": true + } + } + }, + "node_modules/bare-https": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-https/-/bare-https-3.0.0.tgz", + "integrity": "sha512-W1GRSCzn+xXKf5bMcPs/hg6Ga1bxPqb7owGfS+tvlBQfPe5Q2STcanRuKZrgU60v5uKrhXH5cgWwM+DLqvXZgQ==", + "license": "Apache-2.0", + "dependencies": { + "bare-http1": "^4.4.0", + "bare-tcp": "^2.2.0", + "bare-tls": "^3.0.0" + } + }, + "node_modules/bare-inspect": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/bare-inspect/-/bare-inspect-3.1.4.tgz", + "integrity": "sha512-jfW5KRA84o3REpI6Vr4nbvMn+hqVAw8GU1mMdRwUsY5yJovQamxYeKGVKGqdzs+8ZbG4jRzGUXP/3Ji/DnqfPg==", + "license": "Apache-2.0", + "dependencies": { + "bare-ansi-escapes": "^2.1.0", + "bare-type": "^1.0.0" + }, + "engines": { + "bare": ">=1.18.0" + } + }, + "node_modules/bare-mime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bare-mime/-/bare-mime-1.0.0.tgz", + "integrity": "sha512-lUOswzBkfqham4zjLDueKOd4Qj3gS56BiZ3q2f0g0adoFhF+HFNupvTUfZBWoicl7fWJ7Hp2RUZjmkY47dxxOQ==", + "license": "Apache-2.0" + }, + "node_modules/bare-net": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/bare-net/-/bare-net-2.3.1.tgz", + "integrity": "sha512-MypSqDKpDU2Xt7FIfazn5yGvRnV09gFcIPHGWstW0gxuzA4tucTcwJSZeos97C4F89vtU5oGwXDN/HrGN6Y4Jw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.2.2", + "bare-pipe": "^4.0.0", + "bare-stream": "^2.0.0", + "bare-tcp": "^2.0.0" + } + }, + "node_modules/bare-os": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.9.1.tgz", + "integrity": "sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ==", + "license": "Apache-2.0", + "engines": { + "bare": ">=1.14.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "license": "Apache-2.0", + "dependencies": { + "bare-os": "^3.0.1" + } + }, + "node_modules/bare-pipe": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/bare-pipe/-/bare-pipe-4.1.5.tgz", + "integrity": "sha512-6OfxaG8JSkRh3Gc4hzHRsxNt+yu2PpN7lrv1V+T78GdknWQkVGwiEvu4m+1nbfk8cMVQ0TGxRvQ90XA4rhnTuw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.0.0", + "bare-stream": "^2.0.0" + }, + "engines": { + "bare": ">=1.16.0" + } + }, + "node_modules/bare-stream": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.1.tgz", + "integrity": "sha512-Vp0cnjYyrEC4whYTymQ+YZi6pBpfiICZO3cfRG8sy67ZNWe951urv1x4eW1BKNngw3U+3fPYb5JQvHbCtxH7Ow==", + "license": "Apache-2.0", + "dependencies": { + "streamx": "^2.25.0", + "teex": "^1.0.1" + }, + "peerDependencies": { + "bare-abort-controller": "*", + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + }, + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, + "node_modules/bare-tcp": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/bare-tcp/-/bare-tcp-2.2.13.tgz", + "integrity": "sha512-4KQPgqYugvK6QxcSnVGbl87XslBebxmXlv7Glf4M9iwwoSCDKtYmC1t6zsMctTNhzKXbWCId7mB4R9qLWj3JMw==", + "license": "Apache-2.0", + "dependencies": { + "bare-dns": "^2.0.4", + "bare-events": "^2.5.4", + "bare-stream": "^2.6.4" + }, + "engines": { + "bare": ">=1.16.0" + } + }, + "node_modules/bare-tls": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/bare-tls/-/bare-tls-3.1.5.tgz", + "integrity": "sha512-yoOtW3MyJF1mMwavLeuqOE7+qTKZ9cl1GRPxCUOXMUvYCfGltvXyRH48R4EKrRIfgUG6vil6n4Ea1i81fwmgZA==", + "license": "Apache-2.0", + "dependencies": { + "bare-net": "^2.0.1", + "bare-stream": "^2.6.4" + }, + "engines": { + "bare": ">=1.7.0" + } + }, + "node_modules/bare-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bare-type/-/bare-type-1.1.0.tgz", + "integrity": "sha512-LdtnnEEYldOc87Dr4GpsKnStStZk3zfgoEMXy8yvEZkXrcCv9RtYDrUYWFsBQHtaB0s1EUWmcvS6XmEZYIj3Bw==", + "license": "Apache-2.0", + "engines": { + "bare": ">=1.2.0" + } + }, + "node_modules/bare-url": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.3.tgz", + "integrity": "sha512-Kccpc7ACfXaxfeInfqKcZtW4pT5YBn1mesc4sCsun6sRwtbJ4h+sNOaksUpYEJUKfN65YWC6Bw2OJEFiKxq8nQ==", + "license": "Apache-2.0", + "dependencies": { + "bare-path": "^3.0.0" + } + }, + "node_modules/bare-zlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/bare-zlib/-/bare-zlib-1.3.3.tgz", + "integrity": "sha512-rXNczo+SQg6cn20olmh/mUiGeJK9maipFH/zI/QwYgwhEmOns1R7fl1GV5apNO+aAp4x2d4uUa7HLhO4mhOnBQ==", + "license": "Apache-2.0", + "dependencies": { + "bare-stream": "^2.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/case-anything": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.13.tgz", + "integrity": "sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==", + "license": "MIT", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-europe-js": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/detect-europe-js/-/detect-europe-js-0.1.2.tgz", + "integrity": "sha512-lgdERlL3u0aUdHocoouzT10d9I89VVhk0qNRmll7mXdGfJT1/wqZ2ZLA4oJAjeACPY5fT1wsbq2AT+GkuInsow==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "license": "Apache-2.0", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/diff": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dprint-node": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/dprint-node/-/dprint-node-1.0.8.tgz", + "integrity": "sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==", + "license": "MIT", + "dependencies": { + "detect-libc": "^1.0.3" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, + "node_modules/express": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.15.1", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphql": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.14.0.tgz", + "integrity": "sha512-BBvQ/406p+4CZbTpCbVPSxfzrZrbnuWSP1ELYgyS6B+hNeKzgrdB4JczCa5VZUBQrDa9hUngm0KnexY6pJRN5Q==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-ws": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.16.2.tgz", + "integrity": "sha512-E1uccsZxt/96jH/OwmLPuXMACILs76pKF2i3W861LpKBCYtGIyPQGtWLuBLkND4ox1KHns70e83PS4te50nvPQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": ">=0.11 <=16" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz", + "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-standalone-pwa": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-standalone-pwa/-/is-standalone-pwa-0.1.1.tgz", + "integrity": "sha512-9Cbovsa52vNQCjdXOzeQq5CnCbAcRk05aU62K20WO372NrTv0NxibLFCK6lQ4/iZEFdEA3p3t2VNOn8AJ53F5g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT" + }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/js-base64": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.8.tgz", + "integrity": "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==", + "license": "BSD-3-Clause" + }, + "node_modules/light-bolt11-decoder": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/light-bolt11-decoder/-/light-bolt11-decoder-3.2.0.tgz", + "integrity": "sha512-3QEofgiBOP4Ehs9BI+RkZdXZNtSys0nsJ6fyGeSiAGCBsMwHGUDS/JQlY/sTnWs91A2Nh0S9XXfA8Sy9g6QpuQ==", + "license": "MIT", + "dependencies": { + "@scure/base": "1.1.1" + } + }, + "node_modules/light-bolt11-decoder/node_modules/@scure/base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", + "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micro-packed": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.7.3.tgz", + "integrity": "sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg==", + "license": "MIT", + "dependencies": { + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nice-grpc": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/nice-grpc/-/nice-grpc-2.1.16.tgz", + "integrity": "sha512-Cl3Pn00212Hl8/U6bpgMxmhZj5lyv3nWoJov4cd3FjWarktrMHP4DNvSjCnDwkMWYx4W1tyscEia4JX6Y4GVCQ==", + "license": "MIT", + "dependencies": { + "@grpc/grpc-js": "^1.14.0", + "abort-controller-x": "^0.5.0", + "nice-grpc-common": "^2.0.3" + } + }, + "node_modules/nice-grpc-client-middleware-retry": { + "version": "3.1.15", + "resolved": "https://registry.npmjs.org/nice-grpc-client-middleware-retry/-/nice-grpc-client-middleware-retry-3.1.15.tgz", + "integrity": "sha512-fXfNNdtjCQzc3O/w3WsK1AOU+xdE1V7FCm4FEQWS/UUVsV1616S2oryvWqsZAF8aOvuMir8lFtNmgH3DeP+PBg==", + "license": "MIT", + "dependencies": { + "abort-controller-x": "^0.5.0", + "nice-grpc-common": "^2.0.3" + } + }, + "node_modules/nice-grpc-client-middleware-retry/node_modules/abort-controller-x": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.5.0.tgz", + "integrity": "sha512-yTt9CI0x+nRfX6BFMenEGP8ooPvErGH6AbFz20C2IeOLIlDsrw/VHpgne3GsCEuTA410IiFiaLVFKmgM4bKEPQ==", + "license": "MIT" + }, + "node_modules/nice-grpc-common": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/nice-grpc-common/-/nice-grpc-common-2.0.3.tgz", + "integrity": "sha512-MEhnD3JMah0mgyivpb9hpRDbOBuXBxI/TVO+OK1h6rC97WM42HsPMR+zzRNQ0C5BqYJTw1nyWiQRD0DucO+pjQ==", + "license": "MIT", + "dependencies": { + "ts-error": "^1.0.6" + } + }, + "node_modules/nice-grpc-opentelemetry": { + "version": "0.1.22", + "resolved": "https://registry.npmjs.org/nice-grpc-opentelemetry/-/nice-grpc-opentelemetry-0.1.22.tgz", + "integrity": "sha512-Azmn6JhkDeenXk6jag5tq7cRrp7UqIOsNVjtchmXjZp3BaSMI3E8FVk1DSaT+QjO59ftU0tqOofeE/5MixiZKw==", + "license": "MIT", + "dependencies": { + "@opentelemetry/api": "^1.8.0", + "@opentelemetry/semantic-conventions": "^1.22.0", + "abort-controller-x": "^0.5.0", + "ipaddr.js": "^2.0.1", + "nice-grpc-common": "^2.0.3" + } + }, + "node_modules/nice-grpc-opentelemetry/node_modules/abort-controller-x": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.5.0.tgz", + "integrity": "sha512-yTt9CI0x+nRfX6BFMenEGP8ooPvErGH6AbFz20C2IeOLIlDsrw/VHpgne3GsCEuTA410IiFiaLVFKmgM4bKEPQ==", + "license": "MIT" + }, + "node_modules/nice-grpc-web": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/nice-grpc-web/-/nice-grpc-web-3.3.10.tgz", + "integrity": "sha512-8XyCtbs7uL0mWQEjpkjZy57bnLbtheRbIWgj8p98XPbjFqXOBkTLu+ebj5H4fUu/yxqt+6ULPPDHT/icUsyieA==", + "license": "MIT", + "dependencies": { + "abort-controller-x": "^0.5.0", + "isomorphic-ws": "^5.0.0", + "js-base64": "^3.7.2", + "nice-grpc-common": "^2.0.3" + } + }, + "node_modules/nice-grpc-web/node_modules/abort-controller-x": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.5.0.tgz", + "integrity": "sha512-yTt9CI0x+nRfX6BFMenEGP8ooPvErGH6AbFz20C2IeOLIlDsrw/VHpgne3GsCEuTA410IiFiaLVFKmgM4bKEPQ==", + "license": "MIT" + }, + "node_modules/nice-grpc/node_modules/abort-controller-x": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.5.0.tgz", + "integrity": "sha512-yTt9CI0x+nRfX6BFMenEGP8ooPvErGH6AbFz20C2IeOLIlDsrw/VHpgne3GsCEuTA410IiFiaLVFKmgM4bKEPQ==", + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "license": "MIT" + }, + "node_modules/protobufjs": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.1.tgz", + "integrity": "sha512-4K0myLaWL5EteuSAro91EGFgcfVgxb64Jx+7oDAY6GOkXD4M69yuSEljNcInGVCA5sOPxmZ/EqDLj2x0Q0+Ygg==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-in-the-middle": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", + "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/require-in-the-middle/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/require-in-the-middle/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamx": { + "version": "2.25.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz", + "integrity": "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==", + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/text-decoder": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-error": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/ts-error/-/ts-error-1.0.6.tgz", + "integrity": "sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==", + "license": "MIT" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-poet": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ts-poet/-/ts-poet-6.12.0.tgz", + "integrity": "sha512-xo+iRNMWqyvXpFTaOAvLPA5QAWO6TZrSUs5s4Odaya3epqofBu/fMLHEWl8jPmjhA0s9sgj9sNvF1BmaQlmQkA==", + "license": "Apache-2.0", + "dependencies": { + "dprint-node": "^1.0.8" + } + }, + "node_modules/ts-proto": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-2.8.3.tgz", + "integrity": "sha512-TdXInqG+61pj/TvORqITWjvjTTsL1EZxwX49iEj89+xFAcqPT8tjChpAGQXzfcF4MJwvNiuoCEbBOKqVf3ds3g==", + "license": "ISC", + "dependencies": { + "@bufbuild/protobuf": "^2.0.0", + "case-anything": "^2.1.13", + "ts-poet": "^6.12.0", + "ts-proto-descriptors": "2.0.0" + }, + "bin": { + "protoc-gen-ts_proto": "protoc-gen-ts_proto" + } + }, + "node_modules/ts-proto-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-2.0.0.tgz", + "integrity": "sha512-wHcTH3xIv11jxgkX5OyCSFfw27agpInAd6yh89hKG6zqIXnjW9SYqSER2CVQxdPj4czeOhGagNvZBEbJPy7qkw==", + "license": "ISC", + "dependencies": { + "@bufbuild/protobuf": "^2.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ua-is-frozen": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ua-is-frozen/-/ua-is-frozen-0.1.2.tgz", + "integrity": "sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT" + }, + "node_modules/ua-parser-js": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-2.0.10.tgz", + "integrity": "sha512-t+3Ktbq0Ies2vaSezfOaWiolH4OigQIO1dk+1xDpOydB1COVPocVYOrEV5rqZ0kFY9XYG1v9LutCyMgYBpABcw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "AGPL-3.0-or-later", + "dependencies": { + "detect-europe-js": "^0.1.2", + "is-standalone-pwa": "^0.1.1", + "ua-is-frozen": "^0.1.2" + }, + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuidv7": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/uuidv7/-/uuidv7-1.2.1.tgz", + "integrity": "sha512-4kPkK3/XTQW9Hbm4CaqfICn+kY9LJtDVEOfgsRRra/+n2Ofg4NqzRFceAkxvQ/Ud/6BpHOPzj8cirqM7TzTN5Q==", + "license": "Apache-2.0", + "bin": { + "uuidv7": "cli.js" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==", + "license": "MIT" + }, + "node_modules/zen-observable-ts": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz", + "integrity": "sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==", + "license": "MIT", + "dependencies": { + "@types/zen-observable": "0.8.3", + "zen-observable": "0.8.15" + } + } + } +} diff --git a/cashu/lightning/sparkl2_bridge/package.json b/cashu/lightning/sparkl2_bridge/package.json new file mode 100644 index 000000000..7f3c7713b --- /dev/null +++ b/cashu/lightning/sparkl2_bridge/package.json @@ -0,0 +1,22 @@ +{ + "name": "sparkl2-bridge", + "version": "1.0.0", + "description": "Spark L2 Bridge for Nutshell", + "main": "dist/index.js", + "scripts": { + "start": "ts-node src/index.ts", + "build": "tsc" + }, + "dependencies": { + "@buildonspark/spark-sdk": "^0.5.7", + "express": "^4.19.2", + "cors": "^2.8.5" + }, + "devDependencies": { + "@types/express": "^4.17.21", + "@types/cors": "^2.8.17", + "@types/node": "^20.12.7", + "ts-node": "^10.9.2", + "typescript": "^5.4.5" + } +} diff --git a/cashu/lightning/sparkl2_bridge/src/index.ts b/cashu/lightning/sparkl2_bridge/src/index.ts new file mode 100644 index 000000000..a695c02d9 --- /dev/null +++ b/cashu/lightning/sparkl2_bridge/src/index.ts @@ -0,0 +1,176 @@ +import express from 'express'; +import cors from 'cors'; +import { SparkWallet } from '@buildonspark/spark-sdk'; + +const app = express(); +app.use(cors()); +app.use(express.json()); + +const PORT = process.env.PORT || 8426; + +let sparkWallet: SparkWallet | null = null; + +app.post('/init', async (req, res) => { + try { + const { seed, network } = req.body; + if (sparkWallet) { + res.json({ message: "Already initialized" }); + return; + } + + let seedInput: Uint8Array | string = seed; + if (/^[0-9a-fA-F]+$/.test(seed) && seed.length >= 32) { + seedInput = new Uint8Array(Buffer.from(seed, 'hex')); + } + + const net = (network || 'TESTNET') as any; + console.log(`Initializing SparkWallet on ${net}...`); + + const { wallet } = await SparkWallet.initialize({ + mnemonicOrSeed: seedInput, + options: { network: net } + }); + sparkWallet = wallet; + console.log(`SparkWallet initialized successfully! Address: ${await wallet.getSparkAddress()}`); + res.json({ status: "ok" }); + } catch (error: any) { + console.error("Init error:", error); + res.status(500).json({ error: error.message }); + } +}); + +const requireInit = (req: any, res: any, next: any) => { + if (!sparkWallet) { + res.status(400).json({ error: "Wallet not initialized" }); + return; + } + next(); +}; + +app.get('/status', requireInit, async (req, res) => { + try { + const balance = await sparkWallet!.getBalance(); + res.json({ balanceSats: Number(balance.balance) }); + } catch (error: any) { + res.status(500).json({ error: error.message }); + } +}); + +app.post('/invoice', requireInit, async (req, res) => { + try { + const { amountSats, memo, descriptionHash } = req.body; + + const request = await sparkWallet!.createLightningInvoice({ + amountSats: parseInt(amountSats), + memo, + descriptionHash + }); + + res.json({ + id: request.id, + invoice: request.invoice.encodedInvoice, + paymentHash: request.invoice.paymentHash + }); + } catch (error: any) { + res.status(500).json({ error: error.message }); + } +}); + +app.post('/pay', requireInit, async (req, res) => { + try { + const { invoice, maxFeeSats } = req.body; + + const result = await sparkWallet!.payLightningInvoice({ + invoice, + maxFeeSats: Number(maxFeeSats) + }); + + res.json({ + id: result.id, + status: result.status + }); + } catch (error: any) { + res.status(500).json({ error: error.message }); + } +}); + +app.get('/stream', requireInit, (req, res) => { + res.setHeader('Content-Type', 'text/event-stream'); + res.setHeader('Cache-Control', 'no-cache'); + res.setHeader('Connection', 'keep-alive'); + res.flushHeaders(); + + const pingInterval = setInterval(() => { + res.write(': keepalive\n\n'); + }, 25000); + + const handleEvent = (event: any) => { + // According to SDK docs, we can subscribe to wallet events. + // Wait, the SDK events might be different. I'll just push any event. + res.write(`event: inv-paid\ndata: ${JSON.stringify(event)}\n\n`); + }; + + // Assuming sparkWallet.eventEmitter exists based on docs: "Subscribe to wallet events" + // The exact event name might be 'lightningPaymentReceived' or something. We'll listen to 'transfer' or similar. + sparkWallet!.on('transfer:claimed', handleEvent); + sparkWallet!.on('deposit:confirmed', handleEvent); + + req.on('close', () => { + clearInterval(pingInterval); + sparkWallet!.off('transfer:claimed', handleEvent); + sparkWallet!.off('deposit:confirmed', handleEvent); + }); +}); + +app.get('/invoice/status/:id', requireInit, async (req, res) => { + try { + const id = req.params.id; + const request = await (sparkWallet! as any).getLightningReceiveRequest(id); + if (request) { + res.json({ + status: request.status, + paymentHash: request.invoice.paymentHash + }); + return; + } + res.json({ status: 'unknown' }); + } catch (error: any) { + res.status(500).json({ error: error.message }); + } +}); + + + +app.get('/pay/status/:id', requireInit, async (req, res) => { + try { + const id = req.params.id; + const reqState = await sparkWallet!.getLightningSendRequest(id); + if (reqState) { + const anyReq = reqState as any; + res.json({ + status: reqState.status, + preimage: anyReq.preimage || anyReq.paymentPreimage, + feeSats: anyReq.feeSats || anyReq.fee + }); + return; + } + res.json({ status: 'unknown' }); + } catch (error: any) { + res.status(500).json({ error: error.message }); + } +}); + +app.post('/pay/quote', requireInit, async (req, res) => { + try { + const { invoice } = req.body; + const estimate = await sparkWallet!.getLightningSendFeeEstimate({ encodedInvoice: invoice }); + res.json({ feeSats: estimate }); + } catch (error: any) { + res.status(500).json({ error: error.message }); + } +}); + + +app.listen(PORT, () => { + console.log(`Spark L2 Bridge running on port ${PORT}`); +}); diff --git a/cashu/lightning/sparkl2_bridge/tsconfig.json b/cashu/lightning/sparkl2_bridge/tsconfig.json new file mode 100644 index 000000000..042a88d27 --- /dev/null +++ b/cashu/lightning/sparkl2_bridge/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "es2022", + "module": "commonjs", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "outDir": "./dist" + }, + "include": ["src/**/*"] +} From bcc5ce4063ab899f9efcb61f1ee7522dc900624b Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 11:04:21 +0200 Subject: [PATCH 02/24] fix(mint): hoist imports to the top of the file in sparkl2.py --- cashu/lightning/sparkl2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index 25180524c..73d32afd7 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -1,5 +1,7 @@ import asyncio +import json import os +import subprocess from typing import Any, AsyncGenerator, Dict, Optional import bolt11 @@ -46,7 +48,6 @@ async def _ensure_bridge_running(self): await self.client.get("/status", timeout=1) # If we get a response (even 400 not initialized), it's running. except httpx.RequestError: - import subprocess bridge_dir = os.path.join(os.path.dirname(__file__), "sparkl2_bridge") # Try to start it try: @@ -223,7 +224,6 @@ async def paid_invoices_stream(self) -> AsyncGenerator[str, None]: async for line in r.aiter_lines(): if line.startswith("data:"): try: - import json data = json.loads(line[5:].strip()) # Assuming the bridge emits the full event object # The event structure might have 'id' or 'transferId' From 1e82d793da51b8fdd4e1dca32547319eedfe8926 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 11:18:46 +0200 Subject: [PATCH 03/24] fix(mint): spawn bridge in backend init instead of status method --- cashu/lightning/sparkl2.py | 47 +++++++++++++-------- cashu/lightning/sparkl2_bridge/package.json | 2 +- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index 73d32afd7..2fe2a8689 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -43,28 +43,39 @@ def __init__(self, unit: Unit, **kwargs): self.client = httpx.AsyncClient(base_url=self.base_url) - async def _ensure_bridge_running(self): + self.bridge_process: Optional[subprocess.Popen] = None + # Start the bridge process + bridge_dir = os.path.join(os.path.dirname(__file__), "sparkl2_bridge") try: - await self.client.get("/status", timeout=1) - # If we get a response (even 400 not initialized), it's running. - except httpx.RequestError: - bridge_dir = os.path.join(os.path.dirname(__file__), "sparkl2_bridge") - # Try to start it - try: - subprocess.Popen(["npm", "start"], cwd=bridge_dir, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - await asyncio.sleep(3) # Wait for it to start - except Exception as e: - print(f"Warning: Failed to start Spark L2 bridge automatically: {e}") + self.bridge_process = subprocess.Popen( + ["npm", "start"], + cwd=bridge_dir, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL + ) + except Exception as e: + print(f"Warning: Failed to start Spark L2 bridge: {e}") async def status(self) -> StatusResponse: - await self._ensure_bridge_running() + # Check if the bridge process has terminated + if self.bridge_process and self.bridge_process.poll() is not None: + return StatusResponse( + error_message="Spark L2 bridge process has terminated unexpectedly.", + balance=Amount(self.unit, 0), + ) + try: - # Initialize the bridge if necessary - if settings.mint_private_key: - await self.client.post("/init", json={ - "seed": settings.mint_private_key, - "network": getattr(settings, "mint_spark_network", "TESTNET") - }, timeout=15) + # We may need to retry initialization if the bridge is still booting up + for _ in range(5): + try: + if settings.mint_private_key: + await self.client.post("/init", json={ + "seed": settings.mint_private_key, + "network": getattr(settings, "mint_spark_network", "TESTNET") + }, timeout=15) + break + except httpx.RequestError: + await asyncio.sleep(1) r = await self.client.get("/status", timeout=5) r.raise_for_status() diff --git a/cashu/lightning/sparkl2_bridge/package.json b/cashu/lightning/sparkl2_bridge/package.json index 7f3c7713b..81a47d1d8 100644 --- a/cashu/lightning/sparkl2_bridge/package.json +++ b/cashu/lightning/sparkl2_bridge/package.json @@ -4,7 +4,7 @@ "description": "Spark L2 Bridge for Nutshell", "main": "dist/index.js", "scripts": { - "start": "ts-node src/index.ts", + "start": "node dist/index.js", "build": "tsc" }, "dependencies": { From 0abeb431fcc9b091a05b73aae93dc8aa3c2635e8 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 11:42:25 +0200 Subject: [PATCH 04/24] docs: Update .env.example to include Spark L2 Wallet --- .env.example | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index d54b97629..a22840d0e 100644 --- a/.env.example +++ b/.env.example @@ -63,10 +63,8 @@ MINT_DATABASE=data/mint # Funding source backends # Set one funding source backend for each unit -# Supported: FakeWallet, LndRestWallet, LndRPCWallet, CLNRestWallet, BlinkWallet, LNbitsWallet, StrikeWallet, CoreLightningRestWallet (deprecated) - +# Available backends: FakeWallet, LNbitsWallet, StrikeWallet, BlinkWallet, CoreLightningRestWallet, LndRestWallet, LndRPCWallet, SparkL2Wallet MINT_BACKEND_BOLT11_SAT=FakeWallet -# Only works if a usd derivation path is set # MINT_BACKEND_BOLT11_USD=FakeWallet # MINT_BACKEND_BOLT11_EUR=FakeWallet @@ -111,6 +109,11 @@ MINT_BLINK_KEY=blink_abcdefgh # Use with StrikeWallet for BTC, USD, and EUR MINT_STRIKE_KEY=ABC123 +# Use with SparkL2Wallet +# MINT_SPARK_NETWORK="TESTNET" # or "MAINNET", "REGTEST" +# MINT_SPARK_BRIDGE_HOST="127.0.0.1" +# MINT_SPARK_BRIDGE_PORT=8426 + # fee to reserve in percent of the amount LIGHTNING_FEE_PERCENT=1.0 # minimum fee to reserve From 3f4a8a8a1263ac29734d5f886b3070b37f10876d Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 12:10:25 +0200 Subject: [PATCH 05/24] fix(mint): map correct Spark L2 status enums for invoice tracking --- cashu/lightning/sparkl2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index 2fe2a8689..bd6f04190 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -154,9 +154,9 @@ async def get_invoice_status(self, checking_id: str) -> PaymentStatus: data = r.json() status_str = data.get("status", "") - if status_str in ("LIGHTNING_RECEIVE_SUCCEEDED", "CLAIMED", "PAID"): + if status_str in ("LIGHTNING_PAYMENT_RECEIVED", "PAYMENT_PREIMAGE_RECOVERED", "TRANSFER_COMPLETED", "CLAIMED", "PAID"): return PaymentStatus(result=PaymentResult.SETTLED) - elif status_str in ("EXPIRED", "FAILED"): + elif status_str in ("EXPIRED", "FAILED", "TRANSFER_FAILED", "LIGHTNING_PAYMENT_FAILED", "REFUND_SIGNING_FAILED"): return PaymentStatus(result=PaymentResult.FAILED) else: return PaymentStatus(result=PaymentResult.PENDING) @@ -180,7 +180,7 @@ async def get_payment_status(self, checking_id: str) -> PaymentStatus: if self.unit == Unit.msat: fee_amount = Amount(Unit.msat, fee_sats * 1000) - if status_str in ("LIGHTNING_PAYMENT_SUCCEEDED", "TRANSFER_COMPLETED"): + if status_str in ("LIGHTNING_PAYMENT_SUCCEEDED", "PREIMAGE_PROVIDED", "TRANSFER_COMPLETED"): return PaymentStatus( result=PaymentResult.SETTLED, preimage=preimage, From e7f3eae918263f1574b6d7fca6491c699969cf63 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 12:57:29 +0200 Subject: [PATCH 06/24] chore(mint): clean up stale comments in Spark L2 bridge --- cashu/lightning/sparkl2_bridge/src/index.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cashu/lightning/sparkl2_bridge/src/index.ts b/cashu/lightning/sparkl2_bridge/src/index.ts index a695c02d9..6a5753204 100644 --- a/cashu/lightning/sparkl2_bridge/src/index.ts +++ b/cashu/lightning/sparkl2_bridge/src/index.ts @@ -105,13 +105,11 @@ app.get('/stream', requireInit, (req, res) => { }, 25000); const handleEvent = (event: any) => { - // According to SDK docs, we can subscribe to wallet events. - // Wait, the SDK events might be different. I'll just push any event. + // Forward incoming transfer/deposit events as 'inv-paid' so the mint can process them res.write(`event: inv-paid\ndata: ${JSON.stringify(event)}\n\n`); }; - // Assuming sparkWallet.eventEmitter exists based on docs: "Subscribe to wallet events" - // The exact event name might be 'lightningPaymentReceived' or something. We'll listen to 'transfer' or similar. + // Subscribe to the correct Spark SDK events for incoming funds sparkWallet!.on('transfer:claimed', handleEvent); sparkWallet!.on('deposit:confirmed', handleEvent); From d52be5fbea91d7b3d2e64f481b0c86c9336347b6 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 13:16:33 +0200 Subject: [PATCH 07/24] fix(mint): fix fee parsing from Spark SDK's CurrencyAmount object --- cashu/lightning/sparkl2_bridge/src/index.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cashu/lightning/sparkl2_bridge/src/index.ts b/cashu/lightning/sparkl2_bridge/src/index.ts index 6a5753204..22c30ab62 100644 --- a/cashu/lightning/sparkl2_bridge/src/index.ts +++ b/cashu/lightning/sparkl2_bridge/src/index.ts @@ -145,10 +145,18 @@ app.get('/pay/status/:id', requireInit, async (req, res) => { const reqState = await sparkWallet!.getLightningSendRequest(id); if (reqState) { const anyReq = reqState as any; + let feeSats = anyReq.feeSats; + if (anyReq.fee && anyReq.fee.originalValue) { + // If it's a CurrencyAmount object, Spark fee is usually in msats, so divide by 1000 + feeSats = anyReq.fee.originalValue / 1000; + } else if (typeof anyReq.fee === 'number') { + feeSats = anyReq.fee; + } + res.json({ status: reqState.status, preimage: anyReq.preimage || anyReq.paymentPreimage, - feeSats: anyReq.feeSats || anyReq.fee + feeSats: feeSats }); return; } From 17761f2a2e7dec18a63f3f7250b0e66c82937f7e Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 13:34:56 +0200 Subject: [PATCH 08/24] fix(mint): ensure fee calculation safely parses Spark CurrencyAmount and correctly converts to sats --- cashu/lightning/sparkl2.py | 23 +++++++++++------ cashu/lightning/sparkl2_bridge/src/index.ts | 28 ++++++++++++++------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index bd6f04190..25f9e0219 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -1,5 +1,6 @@ import asyncio import json +import math import os import subprocess from typing import Any, AsyncGenerator, Dict, Optional @@ -172,13 +173,14 @@ async def get_payment_status(self, checking_id: str) -> PaymentStatus: status_str = data.get("status", "") preimage = data.get("preimage") - fee_sats = data.get("feeSats") + fee_msats = data.get("feeMsats") fee_amount = None - if fee_sats is not None: - fee_amount = Amount(Unit.sat, fee_sats) + if fee_msats is not None: if self.unit == Unit.msat: - fee_amount = Amount(Unit.msat, fee_sats * 1000) + fee_amount = Amount(Unit.msat, int(fee_msats)) + else: + fee_amount = Amount(Unit.sat, math.ceil(fee_msats / 1000.0)) if status_str in ("LIGHTNING_PAYMENT_SUCCEEDED", "PREIMAGE_PROVIDED", "TRANSFER_COMPLETED"): return PaymentStatus( @@ -203,10 +205,15 @@ async def get_payment_quote( r.raise_for_status() data = r.json() - fee_sats = data.get("feeSats", 0) - fee_amount = Amount(Unit.sat, fee_sats) - if self.unit == Unit.msat: - fee_amount = Amount(Unit.msat, fee_sats * 1000) + fee_msats = data.get("feeMsats", 0) + + if fee_msats is not None: + if self.unit == Unit.msat: + fee_amount = Amount(Unit.msat, int(fee_msats)) + else: + fee_amount = Amount(Unit.sat, math.ceil(fee_msats / 1000.0)) + else: + fee_amount = Amount(self.unit, 0) # Normally parsed from invoice, but we need amount. # Usually the Mint handles invoice parsing via decode_invoice. diff --git a/cashu/lightning/sparkl2_bridge/src/index.ts b/cashu/lightning/sparkl2_bridge/src/index.ts index 22c30ab62..c91200154 100644 --- a/cashu/lightning/sparkl2_bridge/src/index.ts +++ b/cashu/lightning/sparkl2_bridge/src/index.ts @@ -7,6 +7,22 @@ app.use(cors()); app.use(express.json()); const PORT = process.env.PORT || 8426; +const parseFeeToMsats = (feeObj: any, feeSatsPrimitive?: number): number | undefined => { + if (feeObj && typeof feeObj.originalValue === 'number') { + const val = feeObj.originalValue; + switch (feeObj.originalUnit) { + case 'MILLISATOSHI': return val; + case 'SATOSHI': return val * 1000; + case 'BITCOIN': return val * 100000000000; + default: return val * 1000; // Assume SATOSHI fallback + } + } else if (typeof feeObj === 'number') { + return feeObj * 1000; + } else if (typeof feeSatsPrimitive === 'number') { + return feeSatsPrimitive * 1000; + } + return undefined; +}; let sparkWallet: SparkWallet | null = null; @@ -145,18 +161,12 @@ app.get('/pay/status/:id', requireInit, async (req, res) => { const reqState = await sparkWallet!.getLightningSendRequest(id); if (reqState) { const anyReq = reqState as any; - let feeSats = anyReq.feeSats; - if (anyReq.fee && anyReq.fee.originalValue) { - // If it's a CurrencyAmount object, Spark fee is usually in msats, so divide by 1000 - feeSats = anyReq.fee.originalValue / 1000; - } else if (typeof anyReq.fee === 'number') { - feeSats = anyReq.fee; - } + const feeMsats = parseFeeToMsats(anyReq.fee, anyReq.feeSats); res.json({ status: reqState.status, preimage: anyReq.preimage || anyReq.paymentPreimage, - feeSats: feeSats + feeMsats: feeMsats }); return; } @@ -170,7 +180,7 @@ app.post('/pay/quote', requireInit, async (req, res) => { try { const { invoice } = req.body; const estimate = await sparkWallet!.getLightningSendFeeEstimate({ encodedInvoice: invoice }); - res.json({ feeSats: estimate }); + res.json({ feeMsats: typeof estimate === 'number' ? estimate * 1000 : parseFeeToMsats(estimate) }); } catch (error: any) { res.status(500).json({ error: error.message }); } From 653d28148efb92b88711795464dc6401ad20523e Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 13:41:33 +0200 Subject: [PATCH 09/24] fix(mint): map all failure enum variants in Spark L2 backend --- cashu/lightning/sparkl2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index 25f9e0219..fc65f66d4 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -157,7 +157,7 @@ async def get_invoice_status(self, checking_id: str) -> PaymentStatus: status_str = data.get("status", "") if status_str in ("LIGHTNING_PAYMENT_RECEIVED", "PAYMENT_PREIMAGE_RECOVERED", "TRANSFER_COMPLETED", "CLAIMED", "PAID"): return PaymentStatus(result=PaymentResult.SETTLED) - elif status_str in ("EXPIRED", "FAILED", "TRANSFER_FAILED", "LIGHTNING_PAYMENT_FAILED", "REFUND_SIGNING_FAILED"): + elif status_str in ("EXPIRED", "FAILED", "TRANSFER_FAILED", "LIGHTNING_PAYMENT_FAILED", "REFUND_SIGNING_FAILED", "TRANSFER_CREATION_FAILED", "REFUND_SIGNING_COMMITMENTS_QUERYING_FAILED", "PAYMENT_PREIMAGE_RECOVERING_FAILED"): return PaymentStatus(result=PaymentResult.FAILED) else: return PaymentStatus(result=PaymentResult.PENDING) @@ -188,7 +188,7 @@ async def get_payment_status(self, checking_id: str) -> PaymentStatus: preimage=preimage, fee=fee_amount ) - elif status_str in ("LIGHTNING_PAYMENT_FAILED", "TRANSFER_FAILED", "USER_SWAP_RETURN_FAILED", "PREIMAGE_PROVIDING_FAILED"): + elif status_str in ("LIGHTNING_PAYMENT_FAILED", "TRANSFER_FAILED", "USER_SWAP_RETURN_FAILED", "PREIMAGE_PROVIDING_FAILED", "USER_TRANSFER_VALIDATION_FAILED"): return PaymentStatus(result=PaymentResult.FAILED) else: return PaymentStatus(result=PaymentResult.PENDING) From 4ef1d78c153a8022a38989bcf81b315d3590f0e3 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 15:30:50 +0200 Subject: [PATCH 10/24] refactor(mint): replace Node.js sidecar with Python breez-sdk-spark for Spark L2 backend --- .env.example | 3 +- cashu/core/settings.py | 3 +- cashu/lightning/sparkl2.py | 362 ++- cashu/lightning/sparkl2_bridge/.gitignore | 3 - cashu/lightning/sparkl2_bridge/README.md | 29 - .../sparkl2_bridge/package-lock.json | 2782 ----------------- cashu/lightning/sparkl2_bridge/package.json | 22 - cashu/lightning/sparkl2_bridge/src/index.ts | 192 -- cashu/lightning/sparkl2_bridge/tsconfig.json | 12 - poetry.lock | 47 +- pyproject.toml | 1 + 11 files changed, 288 insertions(+), 3168 deletions(-) delete mode 100644 cashu/lightning/sparkl2_bridge/.gitignore delete mode 100644 cashu/lightning/sparkl2_bridge/README.md delete mode 100644 cashu/lightning/sparkl2_bridge/package-lock.json delete mode 100644 cashu/lightning/sparkl2_bridge/package.json delete mode 100644 cashu/lightning/sparkl2_bridge/src/index.ts delete mode 100644 cashu/lightning/sparkl2_bridge/tsconfig.json diff --git a/.env.example b/.env.example index a22840d0e..e626f7507 100644 --- a/.env.example +++ b/.env.example @@ -111,8 +111,7 @@ MINT_STRIKE_KEY=ABC123 # Use with SparkL2Wallet # MINT_SPARK_NETWORK="TESTNET" # or "MAINNET", "REGTEST" -# MINT_SPARK_BRIDGE_HOST="127.0.0.1" -# MINT_SPARK_BRIDGE_PORT=8426 +# MINT_SPARK_API_KEY="your_api_key" # fee to reserve in percent of the amount LIGHTNING_FEE_PERCENT=1.0 diff --git a/cashu/core/settings.py b/cashu/core/settings.py index 967a08119..8114bfe18 100644 --- a/cashu/core/settings.py +++ b/cashu/core/settings.py @@ -116,9 +116,8 @@ class MintBackends(MintSettings): mint_strike_key: Optional[str] = Field(default=None) mint_blink_key: Optional[str] = Field(default=None) - mint_spark_bridge_host: str = Field(default="127.0.0.1") - mint_spark_bridge_port: int = Field(default=8426) mint_spark_network: str = Field(default="TESTNET") + mint_spark_api_key: Optional[str] = Field(default=None) class MintLimits(MintSettings): diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index fc65f66d4..dd2715caf 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -1,12 +1,11 @@ import asyncio -import json -import math +import inspect import os -import subprocess -from typing import Any, AsyncGenerator, Dict, Optional +from typing import AsyncGenerator, Optional import bolt11 -import httpx +import breez_sdk_spark +from loguru import logger from cashu.core.base import Amount, MeltQuote, Unit from cashu.core.models import PostMeltQuoteRequest @@ -22,10 +21,34 @@ ) +class _SdkEventListener(breez_sdk_spark.EventListener): + def __init__(self, wallet: "SparkL2Wallet"): + self.wallet = wallet + + def on_event(self, event: breez_sdk_spark.SdkEvent): + # We only care about incoming payments + if event.is_payment_succeeded(): + payment = event.payment_succeeded.payment + # Only track incoming payments + if payment.payment_type == breez_sdk_spark.PaymentType.RECEIVE: + # The payment.details will contain the invoice if it's a lightning payment + # We extract the checking_id (payment hash) + details = payment.details + if details and details.is_lightning(): + htlc = details.lightning.htlc_details + if htlc and htlc.payment_hash: + asyncio.run_coroutine_threadsafe( + self.wallet.payment_queue.put(htlc.payment_hash), + asyncio.get_event_loop() + ) + # If it's a spark payment (on-chain/deposit/etc), we might not have a simple payment hash + # but for bolt11 invoices created via this backend, it will be lightning. + + class SparkL2Wallet(LightningBackend): """ Spark L2 Wallet backend. - Communicates with the local Node.js bridge which wraps the Spark TypeScript SDK. + Uses the official Breez Spark SDK for Python (`breez-sdk-spark`). """ supported_units = {Unit.sat, Unit.msat} @@ -36,59 +59,92 @@ class SparkL2Wallet(LightningBackend): def __init__(self, unit: Unit, **kwargs): self.assert_unit_supported(unit) self.unit = unit + self.sdk: Optional[breez_sdk_spark.BreezSdk] = None + self.payment_queue: asyncio.Queue[str] = asyncio.Queue() + self.listener: Optional[_SdkEventListener] = None + + async def _ensure_sdk(self): + if self.sdk is not None: + return + + if not settings.mint_private_key: + raise Exception("MINT_PRIVATE_KEY is required to initialize SparkL2Wallet") + + # Initialize the Breez SDK + seed = breez_sdk_spark.Seed.MNEMONIC( + mnemonic=settings.mint_private_key, + passphrase=None + ) - # Read from config or defaults - host = getattr(settings, "mint_spark_bridge_host", "127.0.0.1") - port = getattr(settings, "mint_spark_bridge_port", 8426) - self.base_url = f"http://{host}:{port}" - - self.client = httpx.AsyncClient(base_url=self.base_url) + network_str = getattr(settings, "mint_spark_network", "TESTNET").upper() + if network_str == "MAINNET": + network = breez_sdk_spark.Network.MAINNET + elif network_str == "REGTEST": + network = breez_sdk_spark.Network.REGTEST + elif network_str == "SIGNET": + network = breez_sdk_spark.Network.SIGNET + else: + network = breez_sdk_spark.Network.TESTNET + + config = breez_sdk_spark.default_config(network) + if settings.mint_spark_api_key: + config.api_key = settings.mint_spark_api_key + + # Use a safe storage directory specific to this mint + storage_dir = os.path.join(settings.cashu_dir, "sparkl2_data") + os.makedirs(storage_dir, exist_ok=True) - self.bridge_process: Optional[subprocess.Popen] = None - # Start the bridge process - bridge_dir = os.path.join(os.path.dirname(__file__), "sparkl2_bridge") try: - self.bridge_process = subprocess.Popen( - ["npm", "start"], - cwd=bridge_dir, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL - ) + # We run this in a thread because breez SDK connect is blocking in python (currently) + # Actually, `connect` is async in Python. Let's await it. + # wait, breez_sdk_spark python binding functions are actually async? No they are sync. + import inspect + if inspect.iscoroutinefunction(breez_sdk_spark.connect): + self.sdk = await breez_sdk_spark.connect( + request=breez_sdk_spark.ConnectRequest( + config=config, + seed=seed, + storage_dir=storage_dir + ) + ) + else: + self.sdk = await asyncio.to_thread( + breez_sdk_spark.connect, + request=breez_sdk_spark.ConnectRequest( + config=config, + seed=seed, + storage_dir=storage_dir + ) + ) + + self.listener = _SdkEventListener(self) + self.sdk.add_event_listener(self.listener) + + logger.info("Breez Spark SDK initialized successfully.") + except Exception as e: - print(f"Warning: Failed to start Spark L2 bridge: {e}") + logger.error(f"Failed to initialize Breez Spark SDK: {e}") + raise Exception(f"Failed to initialize Breez Spark SDK: {e}") async def status(self) -> StatusResponse: - # Check if the bridge process has terminated - if self.bridge_process and self.bridge_process.poll() is not None: - return StatusResponse( - error_message="Spark L2 bridge process has terminated unexpectedly.", - balance=Amount(self.unit, 0), - ) - try: - # We may need to retry initialization if the bridge is still booting up - for _ in range(5): - try: - if settings.mint_private_key: - await self.client.post("/init", json={ - "seed": settings.mint_private_key, - "network": getattr(settings, "mint_spark_network", "TESTNET") - }, timeout=15) - break - except httpx.RequestError: - await asyncio.sleep(1) - - r = await self.client.get("/status", timeout=5) - r.raise_for_status() - data = r.json() - balance_sats = data.get("balanceSats", 0) + await self._ensure_sdk() + + if not self.sdk: + return StatusResponse( + error_message="Spark SDK not initialized", + balance=Amount(self.unit, 0), + ) + + info = self.sdk.get_info() + balance_sats = info.balance_sats balance = Amount(Unit.sat, balance_sats) if self.unit == Unit.msat: balance = Amount(Unit.msat, balance_sats * 1000) return StatusResponse(balance=balance) except Exception as e: return StatusResponse( - error_message=f"Failed to connect to Spark bridge: {str(e)}", + error_message=f"Failed to get status from Spark SDK: {str(e)}", balance=Amount(self.unit, 0), ) @@ -100,25 +156,41 @@ async def create_invoice( **kwargs, ) -> InvoiceResponse: self.assert_unit_supported(amount.unit) + await self._ensure_sdk() + amount_sats = amount.to(Unit.sat, round="up").amount - payload: Dict[str, Any] = { - "amountSats": amount_sats, - "memo": memo, - } - if description_hash: - payload["descriptionHash"] = description_hash.hex() - # Spark SDK doesn't allow both memo and descriptionHash - payload.pop("memo", None) - + if not self.sdk: + raise Exception("SDK not initialized") + try: - r = await self.client.post("/invoice", json=payload, timeout=10) - r.raise_for_status() - data = r.json() + # We want to create a bolt11 invoice + req = breez_sdk_spark.ReceivePaymentRequest( + payment_method=breez_sdk_spark.ReceivePaymentMethod.BOLT11_INVOICE( + amount_sats=amount_sats, + description=memo if not description_hash else "", + payment_hash=description_hash.hex() if description_hash else None + ) + ) + + if inspect.iscoroutinefunction(self.sdk.receive_payment): + res = await self.sdk.receive_payment(req) + else: + res = await asyncio.to_thread(self.sdk.receive_payment, req) + + # The response contains the invoice + if not res.destination.is_bolt11_invoice(): + raise Exception("Failed to get bolt11 invoice destination") + + invoice = res.destination.bolt11_invoice.invoice + + # The payment hash is our checking ID + invoice_obj = bolt11.decode(invoice) + return InvoiceResponse( ok=True, - checking_id=data["id"], - payment_request=data["invoice"], + checking_id=invoice_obj.payment_hash, + payment_request=invoice, ) except Exception as e: return InvoiceResponse( @@ -129,18 +201,43 @@ async def create_invoice( async def pay_invoice( self, quote: MeltQuote, fee_limit_msat: int ) -> PaymentResponse: + await self._ensure_sdk() + if not self.sdk: + raise Exception("SDK not initialized") + try: - payload = { - "invoice": quote.request, - "maxFeeSats": fee_limit_msat // 1000 - } - r = await self.client.post("/pay", json=payload, timeout=30) - r.raise_for_status() - data = r.json() + # The Spark SDK has prepare_send_payment -> send_payment flow + prepare_req = breez_sdk_spark.PrepareSendPaymentRequest( + payment_request=quote.request, + amount=None, # Already in invoice + fee_policy=None # Can pass fee limits here if supported + ) + + if inspect.iscoroutinefunction(self.sdk.prepare_send_payment): + prepare_res = await self.sdk.prepare_send_payment(prepare_req) + else: + prepare_res = await asyncio.to_thread(self.sdk.prepare_send_payment, prepare_req) + + # Ensure fee is within limits + fee_sats = prepare_res.fees.original_value + if fee_sats * 1000 > fee_limit_msat: + return PaymentResponse( + result=PaymentResult.FAILED, + error_message=f"Fee estimate ({fee_sats} sats) exceeds limit ({fee_limit_msat // 1000} sats)" + ) + + send_req = breez_sdk_spark.SendPaymentRequest( + prepare_response=prepare_res + ) + if inspect.iscoroutinefunction(self.sdk.send_payment): + send_res = await self.sdk.send_payment(send_req) + else: + send_res = await asyncio.to_thread(self.sdk.send_payment, send_req) + return PaymentResponse( result=PaymentResult.PENDING, - checking_id=data["id"], + checking_id=send_res.payment.id, ) except Exception as e: return PaymentResponse( @@ -149,46 +246,76 @@ async def pay_invoice( ) async def get_invoice_status(self, checking_id: str) -> PaymentStatus: + # checking_id is the payment hash + await self._ensure_sdk() + if not self.sdk: + raise Exception("SDK not initialized") + try: - r = await self.client.get(f"/invoice/status/{checking_id}", timeout=5) - r.raise_for_status() - data = r.json() - - status_str = data.get("status", "") - if status_str in ("LIGHTNING_PAYMENT_RECEIVED", "PAYMENT_PREIMAGE_RECOVERED", "TRANSFER_COMPLETED", "CLAIMED", "PAID"): - return PaymentStatus(result=PaymentResult.SETTLED) - elif status_str in ("EXPIRED", "FAILED", "TRANSFER_FAILED", "LIGHTNING_PAYMENT_FAILED", "REFUND_SIGNING_FAILED", "TRANSFER_CREATION_FAILED", "REFUND_SIGNING_COMMITMENTS_QUERYING_FAILED", "PAYMENT_PREIMAGE_RECOVERING_FAILED"): - return PaymentStatus(result=PaymentResult.FAILED) + # We must list payments and find the receive payment by hash + # Breez SDK provides list_payments but it might be inefficient. + # However, for Spark L2 it's local. + req = breez_sdk_spark.ListPaymentsRequest( + filters=None, + offset=0, + limit=100 # Fetch recent payments + ) + + if inspect.iscoroutinefunction(self.sdk.list_payments): + payments = await self.sdk.list_payments(req) else: - return PaymentStatus(result=PaymentResult.PENDING) + payments = await asyncio.to_thread(self.sdk.list_payments, req) + + for p in payments: + if p.payment_type == breez_sdk_spark.PaymentType.RECEIVE: + if p.details and p.details.is_lightning(): + htlc = p.details.lightning.htlc_details + if htlc and htlc.payment_hash == checking_id: + if p.status == breez_sdk_spark.PaymentStatus.COMPLETED: + return PaymentStatus(result=PaymentResult.SETTLED) + elif p.status == breez_sdk_spark.PaymentStatus.FAILED: + return PaymentStatus(result=PaymentResult.FAILED) + + # If not found in recent, assume pending + return PaymentStatus(result=PaymentResult.PENDING) except Exception as e: return PaymentStatus(result=PaymentResult.UNKNOWN, error_message=str(e)) async def get_payment_status(self, checking_id: str) -> PaymentStatus: - try: - r = await self.client.get(f"/pay/status/{checking_id}", timeout=5) - r.raise_for_status() - data = r.json() - - status_str = data.get("status", "") - preimage = data.get("preimage") - fee_msats = data.get("feeMsats") + await self._ensure_sdk() + if not self.sdk: + raise Exception("SDK not initialized") + try: + if inspect.iscoroutinefunction(self.sdk.get_payment): + payment = await self.sdk.get_payment(checking_id) + else: + payment = await asyncio.to_thread(self.sdk.get_payment, checking_id) + + if not payment: + return PaymentStatus(result=PaymentResult.UNKNOWN, error_message="Payment not found") + + fee_sats = payment.fee fee_amount = None - if fee_msats is not None: + if fee_sats is not None: + fee_amount = Amount(Unit.sat, fee_sats) if self.unit == Unit.msat: - fee_amount = Amount(Unit.msat, int(fee_msats)) - else: - fee_amount = Amount(Unit.sat, math.ceil(fee_msats / 1000.0)) + fee_amount = Amount(Unit.msat, fee_sats * 1000) - if status_str in ("LIGHTNING_PAYMENT_SUCCEEDED", "PREIMAGE_PROVIDED", "TRANSFER_COMPLETED"): + preimage = None + if payment.details and payment.details.is_lightning(): + htlc = payment.details.lightning.htlc_details + if htlc: + preimage = htlc.payment_preimage + + if payment.status == breez_sdk_spark.PaymentStatus.COMPLETED: return PaymentStatus( result=PaymentResult.SETTLED, preimage=preimage, fee=fee_amount ) - elif status_str in ("LIGHTNING_PAYMENT_FAILED", "TRANSFER_FAILED", "USER_SWAP_RETURN_FAILED", "PREIMAGE_PROVIDING_FAILED", "USER_TRANSFER_VALIDATION_FAILED"): + elif payment.status == breez_sdk_spark.PaymentStatus.FAILED: return PaymentStatus(result=PaymentResult.FAILED) else: return PaymentStatus(result=PaymentResult.PENDING) @@ -199,26 +326,27 @@ async def get_payment_status(self, checking_id: str) -> PaymentStatus: async def get_payment_quote( self, melt_quote: PostMeltQuoteRequest ) -> PaymentQuoteResponse: - try: - payload = {"invoice": melt_quote.request} - r = await self.client.post("/pay/quote", json=payload, timeout=5) - r.raise_for_status() - data = r.json() + await self._ensure_sdk() + if not self.sdk: + raise Exception("SDK not initialized") - fee_msats = data.get("feeMsats", 0) + try: + prepare_req = breez_sdk_spark.PrepareSendPaymentRequest( + payment_request=melt_quote.request, + amount=None, + fee_policy=None + ) - if fee_msats is not None: - if self.unit == Unit.msat: - fee_amount = Amount(Unit.msat, int(fee_msats)) - else: - fee_amount = Amount(Unit.sat, math.ceil(fee_msats / 1000.0)) + if inspect.iscoroutinefunction(self.sdk.prepare_send_payment): + prepare_res = await self.sdk.prepare_send_payment(prepare_req) else: - fee_amount = Amount(self.unit, 0) - - # Normally parsed from invoice, but we need amount. - # Usually the Mint handles invoice parsing via decode_invoice. - # So amount is handled outside, but get_payment_quote requires checking_id and amount + prepare_res = await asyncio.to_thread(self.sdk.prepare_send_payment, prepare_req) + fee_sats = prepare_res.fees.original_value + fee_amount = Amount(Unit.sat, fee_sats) + if self.unit == Unit.msat: + fee_amount = Amount(Unit.msat, fee_sats * 1000) + invoice_obj = bolt11.decode(melt_quote.request) amount_msat = int(invoice_obj.amount_msat) if invoice_obj.amount_msat else 0 amount_unit = Amount(Unit.msat, amount_msat) @@ -236,19 +364,7 @@ async def get_payment_quote( raise Exception(f"Failed to get payment quote: {str(e)}") async def paid_invoices_stream(self) -> AsyncGenerator[str, None]: + await self._ensure_sdk() while True: - try: - async with self.client.stream("GET", "/stream", timeout=None) as r: - async for line in r.aiter_lines(): - if line.startswith("data:"): - try: - data = json.loads(line[5:].strip()) - # Assuming the bridge emits the full event object - # The event structure might have 'id' or 'transferId' - checking_id = data.get("id") or data.get("transferId") or data.get("paymentHash") - if checking_id: - yield checking_id - except Exception: - pass - except Exception: - await asyncio.sleep(5) + checking_id = await self.payment_queue.get() + yield checking_id diff --git a/cashu/lightning/sparkl2_bridge/.gitignore b/cashu/lightning/sparkl2_bridge/.gitignore deleted file mode 100644 index deed335be..000000000 --- a/cashu/lightning/sparkl2_bridge/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -node_modules/ -dist/ -.env diff --git a/cashu/lightning/sparkl2_bridge/README.md b/cashu/lightning/sparkl2_bridge/README.md deleted file mode 100644 index 8775a1da5..000000000 --- a/cashu/lightning/sparkl2_bridge/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Spark L2 Bridge for Nutshell - -This directory contains a Node.js sidecar service that wraps the official `@buildonspark/spark-sdk` to provide a Spark L2 wallet backend for Nutshell. - -## Prerequisites -- Node.js (v18+) -- npm - -## Setup -Run the following command to install dependencies: -```bash -npm install -``` - -Nutshell will automatically try to start the bridge process via `npm start` if it is not already running. - -Alternatively, you can start it manually: -```bash -npm start -``` - -## Configuration -In your `.env` file, enable the backend by setting: -```env -MINT_BACKEND_BOLT11_SAT=SparkL2Wallet -MINT_SPARK_NETWORK=TESTNET # or MAINNET -``` - -Nutshell will automatically POST your `MINT_PRIVATE_KEY` to the bridge to initialize the deterministic wallet seed. diff --git a/cashu/lightning/sparkl2_bridge/package-lock.json b/cashu/lightning/sparkl2_bridge/package-lock.json deleted file mode 100644 index bc69aff50..000000000 --- a/cashu/lightning/sparkl2_bridge/package-lock.json +++ /dev/null @@ -1,2782 +0,0 @@ -{ - "name": "sparkl2-bridge", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "sparkl2-bridge", - "version": "1.0.0", - "dependencies": { - "@buildonspark/spark-sdk": "^0.5.7", - "cors": "^2.8.5", - "express": "^4.19.2" - }, - "devDependencies": { - "@types/cors": "^2.8.17", - "@types/express": "^4.17.21", - "@types/node": "^20.12.7", - "ts-node": "^10.9.2", - "typescript": "^5.4.5" - } - }, - "node_modules/@bufbuild/protobuf": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.12.0.tgz", - "integrity": "sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA==", - "license": "(Apache-2.0 AND BSD-3-Clause)" - }, - "node_modules/@buildonspark/spark-sdk": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/@buildonspark/spark-sdk/-/spark-sdk-0.5.10.tgz", - "integrity": "sha512-7nKm54aS/V9ZsFgRQBT+HPvTQMqUGLQpboETXMFkHyppfBPhRj6T6dw4C50UwFBlz/qOJaleGP/ko5wuh+e4Jw==", - "license": "Apache-2.0", - "dependencies": { - "@bufbuild/protobuf": "^2.2.5", - "@lightsparkdev/core": "^1.4.4", - "@noble/curves": "^1.8.0", - "@noble/hashes": "^1.7.0", - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^2.0.0", - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.203.0", - "@opentelemetry/instrumentation-undici": "^0.14.0", - "@opentelemetry/sdk-trace-base": "^2.0.0", - "@opentelemetry/sdk-trace-node": "^2.0.1", - "@opentelemetry/sdk-trace-web": "^2.0.1", - "@scure/base": "^1.2.4", - "@scure/bip32": "^1.6.2", - "@scure/bip39": "^1.5.4", - "@scure/btc-signer": "^1.5.0", - "abort-controller-x": "^0.4.3", - "abortcontroller-polyfill": "^1.7.8", - "async-mutex": "^0.5.0", - "bare-crypto": "^1.9.2", - "bare-fetch": "^2.4.1", - "buffer": "^6.0.3", - "eventemitter3": "^5.0.1", - "js-base64": "^3.7.7", - "light-bolt11-decoder": "^3.2.0", - "nice-grpc": "^2.1.10", - "nice-grpc-client-middleware-retry": "^3.1.10", - "nice-grpc-common": "^2.0.2", - "nice-grpc-opentelemetry": "^0.1.18", - "nice-grpc-web": "^3.3.7", - "ts-proto": "2.8.3", - "ua-parser-js": "^2.0.6", - "uuidv7": "^1.0.2" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "react": ">=18.2.0", - "react-native": ">=0.71.0", - "react-native-get-random-values": ">=1.11.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-native": { - "optional": true - }, - "react-native-get-random-values": { - "optional": true - } - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@grpc/grpc-js": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.4.tgz", - "integrity": "sha512-k9Dj3DV/itK9D06Y8f190Qgop7/Ui+D0njFV3LHMPwPT75DpXLQohE9Wmz0QElrJnzsjB7KPWiKJbOl7IPDArQ==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/proto-loader": "^0.8.0", - "@js-sdsl/ordered-map": "^4.4.2" - }, - "engines": { - "node": ">=12.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.1.tgz", - "integrity": "sha512-wtF6h+DY6M3YaDBPAmvuuA6jV8Sif9MjtOI5euKFWRgCDl5PeDpPsHR9u2l6St5ceY8AZgoNDww5+HvEsXFsGg==", - "license": "Apache-2.0", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.5.5", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@js-sdsl/ordered-map": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/@lightsparkdev/core": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@lightsparkdev/core/-/core-1.5.2.tgz", - "integrity": "sha512-7EiV/Ld+IqAQJYvSLN2gS6E/UrcCCQ/H4voUz+nAPUDSk8U1P06afTKALh1FeizAXIzqxt1jFQWmQlXPSXmxIA==", - "license": "Apache-2.0", - "dependencies": { - "@noble/curves": "^1.9.7", - "dayjs": "^1.11.7", - "graphql": "^16.6.0", - "graphql-ws": "^5.11.3", - "ws": "^8.12.1", - "zen-observable-ts": "^1.1.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@noble/curves": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", - "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.8.0" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@opentelemetry/api": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", - "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@opentelemetry/api-logs": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz", - "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.3.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@opentelemetry/context-async-hooks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.7.1.tgz", - "integrity": "sha512-OPFBYuXEn1E4ja3Y6eeA7O+ZnLBNcXTV5Cgsn1VaqBZ6hC5FnpZPLBNme1LJY8ZtF4aOujPKFoeWN4ik487KuQ==", - "license": "Apache-2.0", - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/core": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.7.1.tgz", - "integrity": "sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/instrumentation": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.203.0.tgz", - "integrity": "sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.203.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-undici": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.14.0.tgz", - "integrity": "sha512-2HN+7ztxAReXuxzrtA3WboAKlfP5OsPA57KQn2AdYZbJ3zeRPcLXyW4uO/jpLE6PLm0QRtmeGCmfYpqRlwgSwg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.203.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.7.0" - } - }, - "node_modules/@opentelemetry/resources": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.1.tgz", - "integrity": "sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.7.1", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", - "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.7.1", - "@opentelemetry/resources": "2.7.1", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-node": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.7.1.tgz", - "integrity": "sha512-pCpQxU68lV+I9s9svqMyVu5iHdDDUnqUpSxqwyCU8A9ejEsSnMPCbearwsUO4yk08ZJzAIUCFuReMdVQvHrdvg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/context-async-hooks": "2.7.1", - "@opentelemetry/core": "2.7.1", - "@opentelemetry/sdk-trace-base": "2.7.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-web": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-web/-/sdk-trace-web-2.7.1.tgz", - "integrity": "sha512-K806OouCSOjMd8Nr7+ZCq3QT22tdAzzS/7h8vprfiKjkgFQ99/dvwU8d12WJANA6D5Qtme65hyBAqAu9CkQuxQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.7.1", - "@opentelemetry/sdk-trace-base": "2.7.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.41.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.41.1.tgz", - "integrity": "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", - "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", - "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", - "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz", - "integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", - "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", - "license": "BSD-3-Clause" - }, - "node_modules/@scure/base": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", - "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", - "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", - "license": "MIT", - "dependencies": { - "@noble/curves": "~1.9.0", - "@noble/hashes": "~1.8.0", - "@scure/base": "~1.2.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", - "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.8.0", - "@scure/base": "~1.2.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/btc-signer": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@scure/btc-signer/-/btc-signer-1.8.1.tgz", - "integrity": "sha512-8nX9T++dFyKpvqksNHfSi9CgRsGnHAQtCdIQ1y1GmbCGLpV97v4MUyemUUT6uDumKL3oo3m4niyY6A32nmdLuQ==", - "license": "MIT", - "dependencies": { - "@noble/curves": "~1.9.0", - "@noble/hashes": "~1.8.0", - "@scure/base": "~1.2.5", - "micro-packed": "~0.7.3" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", - "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/body-parser": { - "version": "1.19.6", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cors": { - "version": "2.8.19", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", - "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/express": { - "version": "4.17.25", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", - "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "^1" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/http-errors": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.19.41", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.41.tgz", - "integrity": "sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/qs": { - "version": "6.15.1", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", - "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", - "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", - "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "<1" - } - }, - "node_modules/@types/serve-static/node_modules/@types/send": { - "version": "0.17.6", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", - "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/zen-observable": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.3.tgz", - "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==", - "license": "MIT" - }, - "node_modules/abort-controller-x": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.4.3.tgz", - "integrity": "sha512-VtUwTNU8fpMwvWGn4xE93ywbogTYsuT+AUxAXOeelbXuQVIwNmC5YLeho9sH4vZ4ITW8414TTAOG1nW6uIVHCA==", - "license": "MIT" - }, - "node_modules/abortcontroller-polyfill": { - "version": "1.7.8", - "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.8.tgz", - "integrity": "sha512-9f1iZ2uWh92VcrU9Y8x+LdM4DLj75VE0MJB8zuF1iUnroEptStw+DQ8EQPMUdfe5k+PkB1uUfDQfWbhstH8LrQ==", - "license": "MIT" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.5", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", - "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "node_modules/async-mutex": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", - "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/b4a": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", - "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", - "license": "Apache-2.0", - "peerDependencies": { - "react-native-b4a": "*" - }, - "peerDependenciesMeta": { - "react-native-b4a": { - "optional": true - } - } - }, - "node_modules/bare-ansi-escapes": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/bare-ansi-escapes/-/bare-ansi-escapes-2.2.3.tgz", - "integrity": "sha512-02ES4/E2RbrtZSnHJ9LntBhYkLA6lPpSEeP8iqS3MccBIVhVBlEmruF1I7HZqx5Q8aiTeYfQVeqmrU9YO2yYoQ==", - "license": "Apache-2.0", - "dependencies": { - "bare-stream": "^2.6.5" - }, - "peerDependencies": { - "bare-buffer": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - } - } - }, - "node_modules/bare-assert": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bare-assert/-/bare-assert-1.2.0.tgz", - "integrity": "sha512-c6uvgvTJBspTDxtVnPgrBKmLgcpW3Fp72NVKDLg6oT4QjQbhGtvrkHMhGYMK1sh4vjBHOBmuUalyt9hSzV37fQ==", - "license": "Apache-2.0", - "dependencies": { - "bare-inspect": "^3.1.2" - } - }, - "node_modules/bare-buffer": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/bare-buffer/-/bare-buffer-3.6.0.tgz", - "integrity": "sha512-/maRWEQ2eBkVNMbNFVsq1pHXJYVj4Y3AixwruB24eKZDs5Gtu0fixzvjYmBIuTsBMtVH5Yb27pQO9BhFa+IlIQ==", - "license": "Apache-2.0", - "engines": { - "bare": ">=1.20.0" - } - }, - "node_modules/bare-crypto": { - "version": "1.13.7", - "resolved": "https://registry.npmjs.org/bare-crypto/-/bare-crypto-1.13.7.tgz", - "integrity": "sha512-gvYgECS1X1wDXFuipwgrN1kwOovMP+BNpaSnRcKRZeT0wYrZIDf9H48BpdWd0t81nmCWtfbpKZhWBziUwLY05Q==", - "license": "Apache-2.0", - "dependencies": { - "bare-assert": "^1.2.0", - "bare-stream": "^2.6.3" - }, - "peerDependencies": { - "bare-buffer": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - } - } - }, - "node_modules/bare-dns": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/bare-dns/-/bare-dns-2.1.4.tgz", - "integrity": "sha512-abwjHmpWqSRNB7V5615QxPH92L71AVzFm/kKTs8VYiNTAi2xVdonpv0BjJ0hwXLwomoW+xsSOPjW6PZPO14asg==", - "license": "Apache-2.0", - "engines": { - "bare": ">=1.7.0" - } - }, - "node_modules/bare-events": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.3.tgz", - "integrity": "sha512-HdUm8EMQBLaJvGUdidNNbqpA1kYkwNcb+MYxkxCLAPJGQzlv9J0C24h8V65Z4c5GLd/JEALDvpFCQgpLJqc0zw==", - "license": "Apache-2.0", - "peerDependencies": { - "bare-abort-controller": "*" - }, - "peerDependenciesMeta": { - "bare-abort-controller": { - "optional": true - } - } - }, - "node_modules/bare-fetch": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/bare-fetch/-/bare-fetch-2.9.1.tgz", - "integrity": "sha512-OqyubfnEXu9BqIVXg+LcdsutZk+amvPey2N+FeG7zeIk+0qarDreAMtixcRGvpR95rM1SNJedHRpBv3BNjja5g==", - "license": "Apache-2.0", - "dependencies": { - "bare-form-data": "^1.2.0", - "bare-http1": "^4.5.2", - "bare-https": "^3.0.0", - "bare-mime": "^1.0.0", - "bare-stream": "^2.9.1", - "bare-url": "^2.4.0", - "bare-zlib": "^1.3.0" - }, - "peerDependencies": { - "bare-abort-controller": "*", - "bare-buffer": "*" - }, - "peerDependenciesMeta": { - "bare-abort-controller": { - "optional": true - }, - "bare-buffer": { - "optional": true - } - } - }, - "node_modules/bare-form-data": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bare-form-data/-/bare-form-data-1.2.2.tgz", - "integrity": "sha512-DQyAkCf5mgKT07orewuvaJfoalw7RBSHia4wgkrG7+seI6aHLB+r6gMRdCGrlO+BmCqMwgTeHAHxDU2NrOjQnQ==", - "license": "Apache-2.0", - "dependencies": { - "bare-buffer": "^3.6.0", - "bare-stream": "^2.6.5" - } - }, - "node_modules/bare-http-parser": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bare-http-parser/-/bare-http-parser-1.1.4.tgz", - "integrity": "sha512-DL+7fTEUWzAEj/Baw9e/BwNAidARbxuUf5bonQ/Wt3VPUdJNyf562ydaono9ZkQBAUw0NydzYEI97rSs/93ruA==", - "license": "Apache-2.0" - }, - "node_modules/bare-http1": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/bare-http1/-/bare-http1-4.5.6.tgz", - "integrity": "sha512-31OAwMkSU+z1VuUOCk65hx3aWQgzCfH/zQ6LGxbJtmiy2Czsw0+uvOBM9YkqaL6zUSTSYG2pLbL0v/TjME3Buw==", - "license": "Apache-2.0", - "dependencies": { - "bare-events": "^2.6.0", - "bare-http-parser": "^1.1.1", - "bare-stream": "^2.10.0", - "bare-tcp": "^2.2.0" - }, - "peerDependencies": { - "bare-buffer": "*", - "bare-url": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - }, - "bare-url": { - "optional": true - } - } - }, - "node_modules/bare-https": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bare-https/-/bare-https-3.0.0.tgz", - "integrity": "sha512-W1GRSCzn+xXKf5bMcPs/hg6Ga1bxPqb7owGfS+tvlBQfPe5Q2STcanRuKZrgU60v5uKrhXH5cgWwM+DLqvXZgQ==", - "license": "Apache-2.0", - "dependencies": { - "bare-http1": "^4.4.0", - "bare-tcp": "^2.2.0", - "bare-tls": "^3.0.0" - } - }, - "node_modules/bare-inspect": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/bare-inspect/-/bare-inspect-3.1.4.tgz", - "integrity": "sha512-jfW5KRA84o3REpI6Vr4nbvMn+hqVAw8GU1mMdRwUsY5yJovQamxYeKGVKGqdzs+8ZbG4jRzGUXP/3Ji/DnqfPg==", - "license": "Apache-2.0", - "dependencies": { - "bare-ansi-escapes": "^2.1.0", - "bare-type": "^1.0.0" - }, - "engines": { - "bare": ">=1.18.0" - } - }, - "node_modules/bare-mime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/bare-mime/-/bare-mime-1.0.0.tgz", - "integrity": "sha512-lUOswzBkfqham4zjLDueKOd4Qj3gS56BiZ3q2f0g0adoFhF+HFNupvTUfZBWoicl7fWJ7Hp2RUZjmkY47dxxOQ==", - "license": "Apache-2.0" - }, - "node_modules/bare-net": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/bare-net/-/bare-net-2.3.1.tgz", - "integrity": "sha512-MypSqDKpDU2Xt7FIfazn5yGvRnV09gFcIPHGWstW0gxuzA4tucTcwJSZeos97C4F89vtU5oGwXDN/HrGN6Y4Jw==", - "license": "Apache-2.0", - "dependencies": { - "bare-events": "^2.2.2", - "bare-pipe": "^4.0.0", - "bare-stream": "^2.0.0", - "bare-tcp": "^2.0.0" - } - }, - "node_modules/bare-os": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.9.1.tgz", - "integrity": "sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ==", - "license": "Apache-2.0", - "engines": { - "bare": ">=1.14.0" - } - }, - "node_modules/bare-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", - "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", - "license": "Apache-2.0", - "dependencies": { - "bare-os": "^3.0.1" - } - }, - "node_modules/bare-pipe": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/bare-pipe/-/bare-pipe-4.1.5.tgz", - "integrity": "sha512-6OfxaG8JSkRh3Gc4hzHRsxNt+yu2PpN7lrv1V+T78GdknWQkVGwiEvu4m+1nbfk8cMVQ0TGxRvQ90XA4rhnTuw==", - "license": "Apache-2.0", - "dependencies": { - "bare-events": "^2.0.0", - "bare-stream": "^2.0.0" - }, - "engines": { - "bare": ">=1.16.0" - } - }, - "node_modules/bare-stream": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.1.tgz", - "integrity": "sha512-Vp0cnjYyrEC4whYTymQ+YZi6pBpfiICZO3cfRG8sy67ZNWe951urv1x4eW1BKNngw3U+3fPYb5JQvHbCtxH7Ow==", - "license": "Apache-2.0", - "dependencies": { - "streamx": "^2.25.0", - "teex": "^1.0.1" - }, - "peerDependencies": { - "bare-abort-controller": "*", - "bare-buffer": "*", - "bare-events": "*" - }, - "peerDependenciesMeta": { - "bare-abort-controller": { - "optional": true - }, - "bare-buffer": { - "optional": true - }, - "bare-events": { - "optional": true - } - } - }, - "node_modules/bare-tcp": { - "version": "2.2.13", - "resolved": "https://registry.npmjs.org/bare-tcp/-/bare-tcp-2.2.13.tgz", - "integrity": "sha512-4KQPgqYugvK6QxcSnVGbl87XslBebxmXlv7Glf4M9iwwoSCDKtYmC1t6zsMctTNhzKXbWCId7mB4R9qLWj3JMw==", - "license": "Apache-2.0", - "dependencies": { - "bare-dns": "^2.0.4", - "bare-events": "^2.5.4", - "bare-stream": "^2.6.4" - }, - "engines": { - "bare": ">=1.16.0" - } - }, - "node_modules/bare-tls": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/bare-tls/-/bare-tls-3.1.5.tgz", - "integrity": "sha512-yoOtW3MyJF1mMwavLeuqOE7+qTKZ9cl1GRPxCUOXMUvYCfGltvXyRH48R4EKrRIfgUG6vil6n4Ea1i81fwmgZA==", - "license": "Apache-2.0", - "dependencies": { - "bare-net": "^2.0.1", - "bare-stream": "^2.6.4" - }, - "engines": { - "bare": ">=1.7.0" - } - }, - "node_modules/bare-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/bare-type/-/bare-type-1.1.0.tgz", - "integrity": "sha512-LdtnnEEYldOc87Dr4GpsKnStStZk3zfgoEMXy8yvEZkXrcCv9RtYDrUYWFsBQHtaB0s1EUWmcvS6XmEZYIj3Bw==", - "license": "Apache-2.0", - "engines": { - "bare": ">=1.2.0" - } - }, - "node_modules/bare-url": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.3.tgz", - "integrity": "sha512-Kccpc7ACfXaxfeInfqKcZtW4pT5YBn1mesc4sCsun6sRwtbJ4h+sNOaksUpYEJUKfN65YWC6Bw2OJEFiKxq8nQ==", - "license": "Apache-2.0", - "dependencies": { - "bare-path": "^3.0.0" - } - }, - "node_modules/bare-zlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/bare-zlib/-/bare-zlib-1.3.3.tgz", - "integrity": "sha512-rXNczo+SQg6cn20olmh/mUiGeJK9maipFH/zI/QwYgwhEmOns1R7fl1GV5apNO+aAp4x2d4uUa7HLhO4mhOnBQ==", - "license": "Apache-2.0", - "dependencies": { - "bare-stream": "^2.0.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.5", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", - "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.15.1", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/case-anything": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.13.tgz", - "integrity": "sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==", - "license": "MIT", - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", - "license": "MIT" - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", - "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/dayjs": { - "version": "1.11.21", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", - "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-europe-js": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/detect-europe-js/-/detect-europe-js-0.1.2.tgz", - "integrity": "sha512-lgdERlL3u0aUdHocoouzT10d9I89VVhk0qNRmll7mXdGfJT1/wqZ2ZLA4oJAjeACPY5fT1wsbq2AT+GkuInsow==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - } - ], - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "license": "Apache-2.0", - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/diff": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", - "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dprint-node": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/dprint-node/-/dprint-node-1.0.8.tgz", - "integrity": "sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==", - "license": "MIT", - "dependencies": { - "detect-libc": "^1.0.3" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", - "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "license": "MIT" - }, - "node_modules/events-universal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", - "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", - "license": "Apache-2.0", - "dependencies": { - "bare-events": "^2.7.0" - } - }, - "node_modules/express": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", - "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.5", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.15.1", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "license": "MIT" - }, - "node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graphql": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.14.0.tgz", - "integrity": "sha512-BBvQ/406p+4CZbTpCbVPSxfzrZrbnuWSP1ELYgyS6B+hNeKzgrdB4JczCa5VZUBQrDa9hUngm0KnexY6pJRN5Q==", - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" - } - }, - "node_modules/graphql-ws": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.16.2.tgz", - "integrity": "sha512-E1uccsZxt/96jH/OwmLPuXMACILs76pKF2i3W861LpKBCYtGIyPQGtWLuBLkND4ox1KHns70e83PS4te50nvPQ==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": ">=0.11 <=16" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", - "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/import-in-the-middle": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", - "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", - "license": "Apache-2.0", - "dependencies": { - "acorn": "^8.14.0", - "acorn-import-attributes": "^1.9.5", - "cjs-module-lexer": "^1.2.2", - "module-details-from-path": "^1.0.3" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz", - "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-core-module": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", - "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", - "license": "MIT", - "dependencies": { - "hasown": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-standalone-pwa": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-standalone-pwa/-/is-standalone-pwa-0.1.1.tgz", - "integrity": "sha512-9Cbovsa52vNQCjdXOzeQq5CnCbAcRk05aU62K20WO372NrTv0NxibLFCK6lQ4/iZEFdEA3p3t2VNOn8AJ53F5g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - } - ], - "license": "MIT" - }, - "node_modules/isomorphic-ws": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", - "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", - "license": "MIT", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/js-base64": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.8.tgz", - "integrity": "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==", - "license": "BSD-3-Clause" - }, - "node_modules/light-bolt11-decoder": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/light-bolt11-decoder/-/light-bolt11-decoder-3.2.0.tgz", - "integrity": "sha512-3QEofgiBOP4Ehs9BI+RkZdXZNtSys0nsJ6fyGeSiAGCBsMwHGUDS/JQlY/sTnWs91A2Nh0S9XXfA8Sy9g6QpuQ==", - "license": "MIT", - "dependencies": { - "@scure/base": "1.1.1" - } - }, - "node_modules/light-bolt11-decoder/node_modules/@scure/base": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", - "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "license": "MIT" - }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "license": "ISC" - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micro-packed": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.7.3.tgz", - "integrity": "sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg==", - "license": "MIT", - "dependencies": { - "@scure/base": "~1.2.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/module-details-from-path": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", - "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/nice-grpc": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/nice-grpc/-/nice-grpc-2.1.16.tgz", - "integrity": "sha512-Cl3Pn00212Hl8/U6bpgMxmhZj5lyv3nWoJov4cd3FjWarktrMHP4DNvSjCnDwkMWYx4W1tyscEia4JX6Y4GVCQ==", - "license": "MIT", - "dependencies": { - "@grpc/grpc-js": "^1.14.0", - "abort-controller-x": "^0.5.0", - "nice-grpc-common": "^2.0.3" - } - }, - "node_modules/nice-grpc-client-middleware-retry": { - "version": "3.1.15", - "resolved": "https://registry.npmjs.org/nice-grpc-client-middleware-retry/-/nice-grpc-client-middleware-retry-3.1.15.tgz", - "integrity": "sha512-fXfNNdtjCQzc3O/w3WsK1AOU+xdE1V7FCm4FEQWS/UUVsV1616S2oryvWqsZAF8aOvuMir8lFtNmgH3DeP+PBg==", - "license": "MIT", - "dependencies": { - "abort-controller-x": "^0.5.0", - "nice-grpc-common": "^2.0.3" - } - }, - "node_modules/nice-grpc-client-middleware-retry/node_modules/abort-controller-x": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.5.0.tgz", - "integrity": "sha512-yTt9CI0x+nRfX6BFMenEGP8ooPvErGH6AbFz20C2IeOLIlDsrw/VHpgne3GsCEuTA410IiFiaLVFKmgM4bKEPQ==", - "license": "MIT" - }, - "node_modules/nice-grpc-common": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/nice-grpc-common/-/nice-grpc-common-2.0.3.tgz", - "integrity": "sha512-MEhnD3JMah0mgyivpb9hpRDbOBuXBxI/TVO+OK1h6rC97WM42HsPMR+zzRNQ0C5BqYJTw1nyWiQRD0DucO+pjQ==", - "license": "MIT", - "dependencies": { - "ts-error": "^1.0.6" - } - }, - "node_modules/nice-grpc-opentelemetry": { - "version": "0.1.22", - "resolved": "https://registry.npmjs.org/nice-grpc-opentelemetry/-/nice-grpc-opentelemetry-0.1.22.tgz", - "integrity": "sha512-Azmn6JhkDeenXk6jag5tq7cRrp7UqIOsNVjtchmXjZp3BaSMI3E8FVk1DSaT+QjO59ftU0tqOofeE/5MixiZKw==", - "license": "MIT", - "dependencies": { - "@opentelemetry/api": "^1.8.0", - "@opentelemetry/semantic-conventions": "^1.22.0", - "abort-controller-x": "^0.5.0", - "ipaddr.js": "^2.0.1", - "nice-grpc-common": "^2.0.3" - } - }, - "node_modules/nice-grpc-opentelemetry/node_modules/abort-controller-x": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.5.0.tgz", - "integrity": "sha512-yTt9CI0x+nRfX6BFMenEGP8ooPvErGH6AbFz20C2IeOLIlDsrw/VHpgne3GsCEuTA410IiFiaLVFKmgM4bKEPQ==", - "license": "MIT" - }, - "node_modules/nice-grpc-web": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/nice-grpc-web/-/nice-grpc-web-3.3.10.tgz", - "integrity": "sha512-8XyCtbs7uL0mWQEjpkjZy57bnLbtheRbIWgj8p98XPbjFqXOBkTLu+ebj5H4fUu/yxqt+6ULPPDHT/icUsyieA==", - "license": "MIT", - "dependencies": { - "abort-controller-x": "^0.5.0", - "isomorphic-ws": "^5.0.0", - "js-base64": "^3.7.2", - "nice-grpc-common": "^2.0.3" - } - }, - "node_modules/nice-grpc-web/node_modules/abort-controller-x": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.5.0.tgz", - "integrity": "sha512-yTt9CI0x+nRfX6BFMenEGP8ooPvErGH6AbFz20C2IeOLIlDsrw/VHpgne3GsCEuTA410IiFiaLVFKmgM4bKEPQ==", - "license": "MIT" - }, - "node_modules/nice-grpc/node_modules/abort-controller-x": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.5.0.tgz", - "integrity": "sha512-yTt9CI0x+nRfX6BFMenEGP8ooPvErGH6AbFz20C2IeOLIlDsrw/VHpgne3GsCEuTA410IiFiaLVFKmgM4bKEPQ==", - "license": "MIT" - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "license": "MIT" - }, - "node_modules/path-to-regexp": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", - "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", - "license": "MIT" - }, - "node_modules/protobufjs": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.1.tgz", - "integrity": "sha512-4K0myLaWL5EteuSAro91EGFgcfVgxb64Jx+7oDAY6GOkXD4M69yuSEljNcInGVCA5sOPxmZ/EqDLj2x0Q0+Ygg==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.5", - "@protobufjs/eventemitter": "^1.1.1", - "@protobufjs/fetch": "^1.1.1", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.2", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.1", - "@types/node": ">=13.7.0", - "long": "^5.3.2" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.15.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", - "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-in-the-middle": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", - "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/require-in-the-middle/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/require-in-the-middle/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.12", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", - "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/send": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.4.1", - "range-parser": "~1.2.1", - "statuses": "~2.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/serve-static": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "~0.19.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", - "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/streamx": { - "version": "2.25.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz", - "integrity": "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==", - "license": "MIT", - "dependencies": { - "events-universal": "^1.0.0", - "fast-fifo": "^1.3.2", - "text-decoder": "^1.1.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/teex": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", - "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", - "license": "MIT", - "dependencies": { - "streamx": "^2.12.5" - } - }, - "node_modules/text-decoder": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", - "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", - "license": "Apache-2.0", - "dependencies": { - "b4a": "^1.6.4" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/ts-error": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/ts-error/-/ts-error-1.0.6.tgz", - "integrity": "sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==", - "license": "MIT" - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-poet": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/ts-poet/-/ts-poet-6.12.0.tgz", - "integrity": "sha512-xo+iRNMWqyvXpFTaOAvLPA5QAWO6TZrSUs5s4Odaya3epqofBu/fMLHEWl8jPmjhA0s9sgj9sNvF1BmaQlmQkA==", - "license": "Apache-2.0", - "dependencies": { - "dprint-node": "^1.0.8" - } - }, - "node_modules/ts-proto": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-2.8.3.tgz", - "integrity": "sha512-TdXInqG+61pj/TvORqITWjvjTTsL1EZxwX49iEj89+xFAcqPT8tjChpAGQXzfcF4MJwvNiuoCEbBOKqVf3ds3g==", - "license": "ISC", - "dependencies": { - "@bufbuild/protobuf": "^2.0.0", - "case-anything": "^2.1.13", - "ts-poet": "^6.12.0", - "ts-proto-descriptors": "2.0.0" - }, - "bin": { - "protoc-gen-ts_proto": "protoc-gen-ts_proto" - } - }, - "node_modules/ts-proto-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-2.0.0.tgz", - "integrity": "sha512-wHcTH3xIv11jxgkX5OyCSFfw27agpInAd6yh89hKG6zqIXnjW9SYqSER2CVQxdPj4czeOhGagNvZBEbJPy7qkw==", - "license": "ISC", - "dependencies": { - "@bufbuild/protobuf": "^2.0.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/ua-is-frozen": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ua-is-frozen/-/ua-is-frozen-0.1.2.tgz", - "integrity": "sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - } - ], - "license": "MIT" - }, - "node_modules/ua-parser-js": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-2.0.10.tgz", - "integrity": "sha512-t+3Ktbq0Ies2vaSezfOaWiolH4OigQIO1dk+1xDpOydB1COVPocVYOrEV5rqZ0kFY9XYG1v9LutCyMgYBpABcw==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], - "license": "AGPL-3.0-or-later", - "dependencies": { - "detect-europe-js": "^0.1.2", - "is-standalone-pwa": "^0.1.1", - "ua-is-frozen": "^0.1.2" - }, - "bin": { - "ua-parser-js": "script/cli.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "license": "MIT" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuidv7": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/uuidv7/-/uuidv7-1.2.1.tgz", - "integrity": "sha512-4kPkK3/XTQW9Hbm4CaqfICn+kY9LJtDVEOfgsRRra/+n2Ofg4NqzRFceAkxvQ/Ud/6BpHOPzj8cirqM7TzTN5Q==", - "license": "Apache-2.0", - "bin": { - "uuidv7": "cli.js" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "license": "MIT" - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/ws": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", - "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/zen-observable": { - "version": "0.8.15", - "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", - "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==", - "license": "MIT" - }, - "node_modules/zen-observable-ts": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz", - "integrity": "sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==", - "license": "MIT", - "dependencies": { - "@types/zen-observable": "0.8.3", - "zen-observable": "0.8.15" - } - } - } -} diff --git a/cashu/lightning/sparkl2_bridge/package.json b/cashu/lightning/sparkl2_bridge/package.json deleted file mode 100644 index 81a47d1d8..000000000 --- a/cashu/lightning/sparkl2_bridge/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "sparkl2-bridge", - "version": "1.0.0", - "description": "Spark L2 Bridge for Nutshell", - "main": "dist/index.js", - "scripts": { - "start": "node dist/index.js", - "build": "tsc" - }, - "dependencies": { - "@buildonspark/spark-sdk": "^0.5.7", - "express": "^4.19.2", - "cors": "^2.8.5" - }, - "devDependencies": { - "@types/express": "^4.17.21", - "@types/cors": "^2.8.17", - "@types/node": "^20.12.7", - "ts-node": "^10.9.2", - "typescript": "^5.4.5" - } -} diff --git a/cashu/lightning/sparkl2_bridge/src/index.ts b/cashu/lightning/sparkl2_bridge/src/index.ts deleted file mode 100644 index c91200154..000000000 --- a/cashu/lightning/sparkl2_bridge/src/index.ts +++ /dev/null @@ -1,192 +0,0 @@ -import express from 'express'; -import cors from 'cors'; -import { SparkWallet } from '@buildonspark/spark-sdk'; - -const app = express(); -app.use(cors()); -app.use(express.json()); - -const PORT = process.env.PORT || 8426; -const parseFeeToMsats = (feeObj: any, feeSatsPrimitive?: number): number | undefined => { - if (feeObj && typeof feeObj.originalValue === 'number') { - const val = feeObj.originalValue; - switch (feeObj.originalUnit) { - case 'MILLISATOSHI': return val; - case 'SATOSHI': return val * 1000; - case 'BITCOIN': return val * 100000000000; - default: return val * 1000; // Assume SATOSHI fallback - } - } else if (typeof feeObj === 'number') { - return feeObj * 1000; - } else if (typeof feeSatsPrimitive === 'number') { - return feeSatsPrimitive * 1000; - } - return undefined; -}; - -let sparkWallet: SparkWallet | null = null; - -app.post('/init', async (req, res) => { - try { - const { seed, network } = req.body; - if (sparkWallet) { - res.json({ message: "Already initialized" }); - return; - } - - let seedInput: Uint8Array | string = seed; - if (/^[0-9a-fA-F]+$/.test(seed) && seed.length >= 32) { - seedInput = new Uint8Array(Buffer.from(seed, 'hex')); - } - - const net = (network || 'TESTNET') as any; - console.log(`Initializing SparkWallet on ${net}...`); - - const { wallet } = await SparkWallet.initialize({ - mnemonicOrSeed: seedInput, - options: { network: net } - }); - sparkWallet = wallet; - console.log(`SparkWallet initialized successfully! Address: ${await wallet.getSparkAddress()}`); - res.json({ status: "ok" }); - } catch (error: any) { - console.error("Init error:", error); - res.status(500).json({ error: error.message }); - } -}); - -const requireInit = (req: any, res: any, next: any) => { - if (!sparkWallet) { - res.status(400).json({ error: "Wallet not initialized" }); - return; - } - next(); -}; - -app.get('/status', requireInit, async (req, res) => { - try { - const balance = await sparkWallet!.getBalance(); - res.json({ balanceSats: Number(balance.balance) }); - } catch (error: any) { - res.status(500).json({ error: error.message }); - } -}); - -app.post('/invoice', requireInit, async (req, res) => { - try { - const { amountSats, memo, descriptionHash } = req.body; - - const request = await sparkWallet!.createLightningInvoice({ - amountSats: parseInt(amountSats), - memo, - descriptionHash - }); - - res.json({ - id: request.id, - invoice: request.invoice.encodedInvoice, - paymentHash: request.invoice.paymentHash - }); - } catch (error: any) { - res.status(500).json({ error: error.message }); - } -}); - -app.post('/pay', requireInit, async (req, res) => { - try { - const { invoice, maxFeeSats } = req.body; - - const result = await sparkWallet!.payLightningInvoice({ - invoice, - maxFeeSats: Number(maxFeeSats) - }); - - res.json({ - id: result.id, - status: result.status - }); - } catch (error: any) { - res.status(500).json({ error: error.message }); - } -}); - -app.get('/stream', requireInit, (req, res) => { - res.setHeader('Content-Type', 'text/event-stream'); - res.setHeader('Cache-Control', 'no-cache'); - res.setHeader('Connection', 'keep-alive'); - res.flushHeaders(); - - const pingInterval = setInterval(() => { - res.write(': keepalive\n\n'); - }, 25000); - - const handleEvent = (event: any) => { - // Forward incoming transfer/deposit events as 'inv-paid' so the mint can process them - res.write(`event: inv-paid\ndata: ${JSON.stringify(event)}\n\n`); - }; - - // Subscribe to the correct Spark SDK events for incoming funds - sparkWallet!.on('transfer:claimed', handleEvent); - sparkWallet!.on('deposit:confirmed', handleEvent); - - req.on('close', () => { - clearInterval(pingInterval); - sparkWallet!.off('transfer:claimed', handleEvent); - sparkWallet!.off('deposit:confirmed', handleEvent); - }); -}); - -app.get('/invoice/status/:id', requireInit, async (req, res) => { - try { - const id = req.params.id; - const request = await (sparkWallet! as any).getLightningReceiveRequest(id); - if (request) { - res.json({ - status: request.status, - paymentHash: request.invoice.paymentHash - }); - return; - } - res.json({ status: 'unknown' }); - } catch (error: any) { - res.status(500).json({ error: error.message }); - } -}); - - - -app.get('/pay/status/:id', requireInit, async (req, res) => { - try { - const id = req.params.id; - const reqState = await sparkWallet!.getLightningSendRequest(id); - if (reqState) { - const anyReq = reqState as any; - const feeMsats = parseFeeToMsats(anyReq.fee, anyReq.feeSats); - - res.json({ - status: reqState.status, - preimage: anyReq.preimage || anyReq.paymentPreimage, - feeMsats: feeMsats - }); - return; - } - res.json({ status: 'unknown' }); - } catch (error: any) { - res.status(500).json({ error: error.message }); - } -}); - -app.post('/pay/quote', requireInit, async (req, res) => { - try { - const { invoice } = req.body; - const estimate = await sparkWallet!.getLightningSendFeeEstimate({ encodedInvoice: invoice }); - res.json({ feeMsats: typeof estimate === 'number' ? estimate * 1000 : parseFeeToMsats(estimate) }); - } catch (error: any) { - res.status(500).json({ error: error.message }); - } -}); - - -app.listen(PORT, () => { - console.log(`Spark L2 Bridge running on port ${PORT}`); -}); diff --git a/cashu/lightning/sparkl2_bridge/tsconfig.json b/cashu/lightning/sparkl2_bridge/tsconfig.json deleted file mode 100644 index 042a88d27..000000000 --- a/cashu/lightning/sparkl2_bridge/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "target": "es2022", - "module": "commonjs", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "skipLibCheck": true, - "outDir": "./dist" - }, - "include": ["src/**/*"] -} diff --git a/poetry.lock b/poetry.lock index 16fcfaaf7..8367d0a9b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -220,6 +220,51 @@ bitstring = "*" click = "*" coincurve = "*" +[[package]] +name = "breez-sdk-spark" +version = "0.15.0" +description = "Python language bindings for the Breez Spark SDK" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "breez_sdk_spark-0.15.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9bdc307a5ad08d08a964da394205b7656245d8500f68a705ca49f9a38f664587"}, + {file = "breez_sdk_spark-0.15.0-cp310-cp310-manylinux_2_31_aarch64.whl", hash = "sha256:fc9dd493a87132b9830613473b73b04e0183f9dd5d9b483d4b557ad07cec4604"}, + {file = "breez_sdk_spark-0.15.0-cp310-cp310-manylinux_2_31_x86_64.whl", hash = "sha256:a1f515c9a8dd68b6b7e596609abadf3508fcbb07206d974d4b0261c3e1b393a7"}, + {file = "breez_sdk_spark-0.15.0-cp310-cp310-win32.whl", hash = "sha256:6ace7c7dd9e0372d0ce8a24f377a85de12f7ee1356d39a1b4ee3528c8ca5a99b"}, + {file = "breez_sdk_spark-0.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:8e1c1876f6d2d79d51f8b5d4b4ed6c84243286491974d716c4f62e94be53b679"}, + {file = "breez_sdk_spark-0.15.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8d9e0fe33faf6cce7a450bc5e6a13fbf88c68d13e49d295c7802464d5679dabe"}, + {file = "breez_sdk_spark-0.15.0-cp311-cp311-manylinux_2_31_aarch64.whl", hash = "sha256:4a78add31b108a48f9f0825229abfa4e85665f335a822504f43b4320a4f59333"}, + {file = "breez_sdk_spark-0.15.0-cp311-cp311-manylinux_2_31_x86_64.whl", hash = "sha256:0a0d3d155832b96224ef1ca0ed22fde9b3b2a84a4ea30361df556aea0ceafa53"}, + {file = "breez_sdk_spark-0.15.0-cp311-cp311-win32.whl", hash = "sha256:d725e06548edeba4a65c5fa9466672aeb9b741e1c4bb890cffa7b144023912b9"}, + {file = "breez_sdk_spark-0.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:ffd0251cba5c68aa023e9529a8ac97b04907564844c27a0e61d638d56ef3936d"}, + {file = "breez_sdk_spark-0.15.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:40e2b289009dfb18edf38c990299c37feff6c71f5a5beee57bde9e18a9d4fcd1"}, + {file = "breez_sdk_spark-0.15.0-cp312-cp312-manylinux_2_31_aarch64.whl", hash = "sha256:5eb6f39c9b673a0cf2b3edb35d648cf3e33758eca44e3d26c84a51c26e3890f9"}, + {file = "breez_sdk_spark-0.15.0-cp312-cp312-manylinux_2_31_x86_64.whl", hash = "sha256:1e3aa503ac85d4463e6fccd077492373662497e40035444498514cb60b18a0e0"}, + {file = "breez_sdk_spark-0.15.0-cp312-cp312-win32.whl", hash = "sha256:933e45597e889aa546508e823914050784fcdae05fde5c2185d5754163281611"}, + {file = "breez_sdk_spark-0.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:3967a729410bde2ca7f5b2a395bc1eb4dd63f1bb4ec86f6358373747532d58d0"}, + {file = "breez_sdk_spark-0.15.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:c4a8fa8f52167a0aa1b2977844567421c9f4c87d957591187fce83dad054e296"}, + {file = "breez_sdk_spark-0.15.0-cp313-cp313-manylinux_2_31_aarch64.whl", hash = "sha256:c74c6005d226c129c7f1f2726c20eccd4755b85c7c776bc583b66a696c59dd57"}, + {file = "breez_sdk_spark-0.15.0-cp313-cp313-manylinux_2_31_x86_64.whl", hash = "sha256:50a05396da436c0881373ac918eac187d1ba13afebcf66d685bc56e7492c301a"}, + {file = "breez_sdk_spark-0.15.0-cp313-cp313-win32.whl", hash = "sha256:efb2a820c002bb7130061eade8bf3818fa79514b69af05cd21009deb20ee033c"}, + {file = "breez_sdk_spark-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:371b992f33d14d1147241b042d0614731634dceb5e688dafe0fb4cfa31d821c3"}, + {file = "breez_sdk_spark-0.15.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:dea96e42631b261aeccf7f61baed760f7c366968d33187c2adcd79e6e79531ac"}, + {file = "breez_sdk_spark-0.15.0-cp314-cp314-manylinux_2_31_aarch64.whl", hash = "sha256:3e008ff640967aef1891ba7a43828c3ab295297f1825080f8e087851d3bbdcc4"}, + {file = "breez_sdk_spark-0.15.0-cp314-cp314-manylinux_2_31_x86_64.whl", hash = "sha256:3f341ebe4de2e025fbca25b22183fa90a8af19029f7ddb84b53c4122fc51d2ac"}, + {file = "breez_sdk_spark-0.15.0-cp314-cp314-win32.whl", hash = "sha256:db410e8651fa5666c22d0c6039b4f872f5dec32cc66c7140d95af870c3533302"}, + {file = "breez_sdk_spark-0.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:5211a7e38df5d3bb327cb74b8b79bd9d735268ae8549489df09311b64d863b2c"}, + {file = "breez_sdk_spark-0.15.0-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:70a9b33c74856d9785ce2e63927b41f36980ff7b43321be3bd4db0ddeed05921"}, + {file = "breez_sdk_spark-0.15.0-cp38-cp38-manylinux_2_31_aarch64.whl", hash = "sha256:870a3dcde8549d34cf405ae85c11543165eedc9066a0ab3b5892fb80682d5dad"}, + {file = "breez_sdk_spark-0.15.0-cp38-cp38-manylinux_2_31_x86_64.whl", hash = "sha256:9e96f066e989a953d780ed041c4030fd53a9542bf703b49021f1aa205999544b"}, + {file = "breez_sdk_spark-0.15.0-cp38-cp38-win32.whl", hash = "sha256:076fac96444b2bd753a33d8e2c5e31f9525090bbc92f3e8a88f7ad1804bacc31"}, + {file = "breez_sdk_spark-0.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:125c2ac701cc3843fbe287799bc287bcbd9f935dc8776eca24b1036bd365c0e4"}, + {file = "breez_sdk_spark-0.15.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:584bb29dd2ac9b353277eed852d161e2695a5024299eeaa40a16c47cf5e29d14"}, + {file = "breez_sdk_spark-0.15.0-cp39-cp39-manylinux_2_31_aarch64.whl", hash = "sha256:b1ada181964be0e63c2c9723161317de50d49c580b6e54b3725f852266f99e84"}, + {file = "breez_sdk_spark-0.15.0-cp39-cp39-manylinux_2_31_x86_64.whl", hash = "sha256:e16e401b6426b6cf7372cf1fc47afbb7788d050ac046841198b06c1f900c014f"}, + {file = "breez_sdk_spark-0.15.0-cp39-cp39-win32.whl", hash = "sha256:adec0ddc19d1861725055279fd5bb78fd90a4fbfb582ead2e56d723a8840fc44"}, + {file = "breez_sdk_spark-0.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:85ae9bc6f523ac6e132563225e408788c1b3c576828eec2834a88b24804bcbd9"}, +] + [[package]] name = "brotli" version = "1.1.0" @@ -2883,4 +2928,4 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.1" python-versions = "^3.10" -content-hash = "a1fda6a32a65cf0cb29a81558cc3b573f538a24cfb5a17d1a6f02f1f1f1c2110" +content-hash = "f2e8415f53275aef0423d15c6474037100af3cf216fc46979b3af4b8ab7f1889" diff --git a/pyproject.toml b/pyproject.toml index 615abade9..bd5d3c28a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,7 @@ redis = "^5.1.1" brotli = "^1.1.0" zstandard = "^0.23.0" jinja2 = "^3.1.5" +breez-sdk-spark = "^0.15.0" [tool.poetry.group.dev.dependencies] pytest-asyncio = "^0.24.0" From 33681abbe1267bb3e722cc39a893fdc1aec8b346 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 15:40:51 +0200 Subject: [PATCH 11/24] fix(mint): remove inline imports in Spark L2 backend --- cashu/lightning/sparkl2.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index dd2715caf..e903de8dd 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -98,7 +98,6 @@ async def _ensure_sdk(self): # We run this in a thread because breez SDK connect is blocking in python (currently) # Actually, `connect` is async in Python. Let's await it. # wait, breez_sdk_spark python binding functions are actually async? No they are sync. - import inspect if inspect.iscoroutinefunction(breez_sdk_spark.connect): self.sdk = await breez_sdk_spark.connect( request=breez_sdk_spark.ConnectRequest( @@ -118,7 +117,10 @@ async def _ensure_sdk(self): ) self.listener = _SdkEventListener(self) - self.sdk.add_event_listener(self.listener) + if inspect.iscoroutinefunction(self.sdk.add_event_listener): + await self.sdk.add_event_listener(self.listener) + else: + self.sdk.add_event_listener(self.listener) logger.info("Breez Spark SDK initialized successfully.") @@ -136,7 +138,11 @@ async def status(self) -> StatusResponse: balance=Amount(self.unit, 0), ) - info = self.sdk.get_info() + req = breez_sdk_spark.GetInfoRequest(ensure_synced=False) + if inspect.iscoroutinefunction(self.sdk.get_info): + info = await self.sdk.get_info(req) + else: + info = await asyncio.to_thread(self.sdk.get_info, req) balance_sats = info.balance_sats balance = Amount(Unit.sat, balance_sats) if self.unit == Unit.msat: From 5eaac394f2ca32c62d0159ca9ad9722bc40bd037 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 15:46:05 +0200 Subject: [PATCH 12/24] feat(mint): configure Spark L2 mnemonic securely via MINT_SPARK_MNEMONIC --- .env.example | 1 + cashu/core/settings.py | 1 + cashu/lightning/sparkl2.py | 6 +++--- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index e626f7507..a03fbde3b 100644 --- a/.env.example +++ b/.env.example @@ -112,6 +112,7 @@ MINT_STRIKE_KEY=ABC123 # Use with SparkL2Wallet # MINT_SPARK_NETWORK="TESTNET" # or "MAINNET", "REGTEST" # MINT_SPARK_API_KEY="your_api_key" +# MINT_SPARK_MNEMONIC="abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" # fee to reserve in percent of the amount LIGHTNING_FEE_PERCENT=1.0 diff --git a/cashu/core/settings.py b/cashu/core/settings.py index 8114bfe18..ef448a772 100644 --- a/cashu/core/settings.py +++ b/cashu/core/settings.py @@ -118,6 +118,7 @@ class MintBackends(MintSettings): mint_spark_network: str = Field(default="TESTNET") mint_spark_api_key: Optional[str] = Field(default=None) + mint_spark_mnemonic: Optional[str] = Field(default=None) class MintLimits(MintSettings): diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index e903de8dd..75a110540 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -67,12 +67,12 @@ async def _ensure_sdk(self): if self.sdk is not None: return - if not settings.mint_private_key: - raise Exception("MINT_PRIVATE_KEY is required to initialize SparkL2Wallet") + if not settings.mint_spark_mnemonic: + raise Exception("MINT_SPARK_MNEMONIC is required to initialize SparkL2Wallet. Please set a 12, 15, 18, 21, or 24-word seed phrase in your environment.") # Initialize the Breez SDK seed = breez_sdk_spark.Seed.MNEMONIC( - mnemonic=settings.mint_private_key, + mnemonic=settings.mint_spark_mnemonic, passphrase=None ) From 922db88600a3bcee850b6efb93c5b7b4f261500b Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 16:16:39 +0200 Subject: [PATCH 13/24] fix(mint): pass correct parameters for Breez BOLT11 invoice generation --- cashu/lightning/sparkl2.py | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index 75a110540..e06f1d28b 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -25,7 +25,7 @@ class _SdkEventListener(breez_sdk_spark.EventListener): def __init__(self, wallet: "SparkL2Wallet"): self.wallet = wallet - def on_event(self, event: breez_sdk_spark.SdkEvent): + async def on_event(self, event: breez_sdk_spark.SdkEvent): # We only care about incoming payments if event.is_payment_succeeded(): payment = event.payment_succeeded.payment @@ -37,10 +37,7 @@ def on_event(self, event: breez_sdk_spark.SdkEvent): if details and details.is_lightning(): htlc = details.lightning.htlc_details if htlc and htlc.payment_hash: - asyncio.run_coroutine_threadsafe( - self.wallet.payment_queue.put(htlc.payment_hash), - asyncio.get_event_loop() - ) + await self.wallet.payment_queue.put(htlc.payment_hash) # If it's a spark payment (on-chain/deposit/etc), we might not have a simple payment hash # but for bolt11 invoices created via this backend, it will be lightning. @@ -173,8 +170,9 @@ async def create_invoice( # We want to create a bolt11 invoice req = breez_sdk_spark.ReceivePaymentRequest( payment_method=breez_sdk_spark.ReceivePaymentMethod.BOLT11_INVOICE( - amount_sats=amount_sats, description=memo if not description_hash else "", + amount_sats=amount_sats, + expiry_secs=None, payment_hash=description_hash.hex() if description_hash else None ) ) @@ -184,11 +182,8 @@ async def create_invoice( else: res = await asyncio.to_thread(self.sdk.receive_payment, req) - # The response contains the invoice - if not res.destination.is_bolt11_invoice(): - raise Exception("Failed to get bolt11 invoice destination") - - invoice = res.destination.bolt11_invoice.invoice + # The response contains the invoice string + invoice = res.payment_request # The payment hash is our checking ID invoice_obj = bolt11.decode(invoice) @@ -199,6 +194,7 @@ async def create_invoice( payment_request=invoice, ) except Exception as e: + logger.error(f"Failed to create invoice: {str(e)}") return InvoiceResponse( ok=False, error_message=f"Failed to create invoice: {str(e)}" @@ -262,9 +258,9 @@ async def get_invoice_status(self, checking_id: str) -> PaymentStatus: # Breez SDK provides list_payments but it might be inefficient. # However, for Spark L2 it's local. req = breez_sdk_spark.ListPaymentsRequest( - filters=None, - offset=0, - limit=100 # Fetch recent payments + type_filter=None, + status_filter=None, + asset_filter=None, ) if inspect.iscoroutinefunction(self.sdk.list_payments): From d923aba4b6e7682b9079faf62d3eb27aba4d3940 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 16:19:22 +0200 Subject: [PATCH 14/24] fix(mint): correctly access Breez Spark event properties to avoid AttributeError on incoming payments --- cashu/lightning/sparkl2.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index e06f1d28b..f8ab7bd44 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -28,7 +28,25 @@ def __init__(self, wallet: "SparkL2Wallet"): async def on_event(self, event: breez_sdk_spark.SdkEvent): # We only care about incoming payments if event.is_payment_succeeded(): - payment = event.payment_succeeded.payment + payment = getattr(event, "payment", None) + if payment is None: + # Some rust binding generators use the variant name lowercased, but the error said it didn't exist. + # Let's try to extract it from the event attributes. + try: + payment = event.payment_succeeded.payment + except AttributeError: + pass + + # Uniffi-rs bindings for enums usually have the properties directly on the variant object + if payment is None: + # If we're here, `event` IS the `PAYMENT_SUCCEEDED` instance. + # We can access `event.payment`. + if hasattr(event, "payment"): + payment = event.payment + + if not payment: + return + # Only track incoming payments if payment.payment_type == breez_sdk_spark.PaymentType.RECEIVE: # The payment.details will contain the invoice if it's a lightning payment From 5730d54f993390fa4a5d0882b6c14f332bd23571 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 16:21:17 +0200 Subject: [PATCH 15/24] fix(mint): properly check PAYMENT_SUCCEEDED enum properties in Spark L2 event listener to prevent uniffi crashes --- cashu/lightning/sparkl2.py | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index f8ab7bd44..bec1df66d 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -27,23 +27,8 @@ def __init__(self, wallet: "SparkL2Wallet"): async def on_event(self, event: breez_sdk_spark.SdkEvent): # We only care about incoming payments - if event.is_payment_succeeded(): - payment = getattr(event, "payment", None) - if payment is None: - # Some rust binding generators use the variant name lowercased, but the error said it didn't exist. - # Let's try to extract it from the event attributes. - try: - payment = event.payment_succeeded.payment - except AttributeError: - pass - - # Uniffi-rs bindings for enums usually have the properties directly on the variant object - if payment is None: - # If we're here, `event` IS the `PAYMENT_SUCCEEDED` instance. - # We can access `event.payment`. - if hasattr(event, "payment"): - payment = event.payment - + if isinstance(event, breez_sdk_spark.SdkEvent.PAYMENT_SUCCEEDED): + payment = event.payment if not payment: return From 66a72f2fb1ea2cb3741f3250dded6551befe430a Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 17:07:28 +0200 Subject: [PATCH 16/24] fix(mint): fix Breez SDK parameter and attribute access bugs in Spark L2 backend --- cashu/lightning/sparkl2.py | 42 +++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index bec1df66d..0c6ccf915 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -38,7 +38,7 @@ async def on_event(self, event: breez_sdk_spark.SdkEvent): # We extract the checking_id (payment hash) details = payment.details if details and details.is_lightning(): - htlc = details.lightning.htlc_details + htlc = getattr(details, "htlc_details", None) if htlc and htlc.payment_hash: await self.wallet.payment_queue.put(htlc.payment_hash) # If it's a spark payment (on-chain/deposit/etc), we might not have a simple payment hash @@ -224,11 +224,14 @@ async def pay_invoice( prepare_res = await asyncio.to_thread(self.sdk.prepare_send_payment, prepare_req) # Ensure fee is within limits - fee_sats = prepare_res.fees.original_value - if fee_sats * 1000 > fee_limit_msat: + fee_sats = getattr(prepare_res.payment_method, "lightning_fee_sats", 0) + spark_fee = getattr(prepare_res.payment_method, "spark_transfer_fee_sats", 0) or 0 + total_fee_sats = fee_sats + spark_fee + + if total_fee_sats * 1000 > fee_limit_msat: return PaymentResponse( result=PaymentResult.FAILED, - error_message=f"Fee estimate ({fee_sats} sats) exceeds limit ({fee_limit_msat // 1000} sats)" + error_message=f"Fee estimate ({total_fee_sats} sats) exceeds limit ({fee_limit_msat // 1000} sats)" ) send_req = breez_sdk_spark.SendPaymentRequest( @@ -267,14 +270,14 @@ async def get_invoice_status(self, checking_id: str) -> PaymentStatus: ) if inspect.iscoroutinefunction(self.sdk.list_payments): - payments = await self.sdk.list_payments(req) + res = await self.sdk.list_payments(req) else: - payments = await asyncio.to_thread(self.sdk.list_payments, req) + res = await asyncio.to_thread(self.sdk.list_payments, req) - for p in payments: + for p in res.payments: if p.payment_type == breez_sdk_spark.PaymentType.RECEIVE: if p.details and p.details.is_lightning(): - htlc = p.details.lightning.htlc_details + htlc = getattr(p.details, "htlc_details", None) if htlc and htlc.payment_hash == checking_id: if p.status == breez_sdk_spark.PaymentStatus.COMPLETED: return PaymentStatus(result=PaymentResult.SETTLED) @@ -293,15 +296,17 @@ async def get_payment_status(self, checking_id: str) -> PaymentStatus: raise Exception("SDK not initialized") try: + req = breez_sdk_spark.GetPaymentRequest(payment_id=checking_id) if inspect.iscoroutinefunction(self.sdk.get_payment): - payment = await self.sdk.get_payment(checking_id) + res = await self.sdk.get_payment(req) else: - payment = await asyncio.to_thread(self.sdk.get_payment, checking_id) + res = await asyncio.to_thread(self.sdk.get_payment, req) - if not payment: + if not res or not res.payment: return PaymentStatus(result=PaymentResult.UNKNOWN, error_message="Payment not found") - fee_sats = payment.fee + payment = res.payment + fee_sats = payment.fees fee_amount = None if fee_sats is not None: fee_amount = Amount(Unit.sat, fee_sats) @@ -310,9 +315,9 @@ async def get_payment_status(self, checking_id: str) -> PaymentStatus: preimage = None if payment.details and payment.details.is_lightning(): - htlc = payment.details.lightning.htlc_details + htlc = getattr(payment.details, "htlc_details", None) if htlc: - preimage = htlc.payment_preimage + preimage = htlc.preimage if payment.status == breez_sdk_spark.PaymentStatus.COMPLETED: return PaymentStatus( @@ -347,10 +352,13 @@ async def get_payment_quote( else: prepare_res = await asyncio.to_thread(self.sdk.prepare_send_payment, prepare_req) - fee_sats = prepare_res.fees.original_value - fee_amount = Amount(Unit.sat, fee_sats) + fee_sats = getattr(prepare_res.payment_method, "lightning_fee_sats", 0) + spark_fee = getattr(prepare_res.payment_method, "spark_transfer_fee_sats", 0) or 0 + total_fee_sats = fee_sats + spark_fee + + fee_amount = Amount(Unit.sat, total_fee_sats) if self.unit == Unit.msat: - fee_amount = Amount(Unit.msat, fee_sats * 1000) + fee_amount = Amount(Unit.msat, total_fee_sats * 1000) invoice_obj = bolt11.decode(melt_quote.request) amount_msat = int(invoice_obj.amount_msat) if invoice_obj.amount_msat else 0 From 8c7b396081d21f680c6cad2a630aa151edcf0e13 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Tue, 26 May 2026 19:45:49 +0200 Subject: [PATCH 17/24] fix(mint): pass correct string to Breez description field to prevent NoneType error --- cashu/lightning/sparkl2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index 0c6ccf915..33528ef37 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -173,7 +173,7 @@ async def create_invoice( # We want to create a bolt11 invoice req = breez_sdk_spark.ReceivePaymentRequest( payment_method=breez_sdk_spark.ReceivePaymentMethod.BOLT11_INVOICE( - description=memo if not description_hash else "", + description=(memo or "") if not description_hash else "", amount_sats=amount_sats, expiry_secs=None, payment_hash=description_hash.hex() if description_hash else None From ea5a60cdbbfd54deba120c01cd15bd9b0cab55f9 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Wed, 27 May 2026 09:15:16 +0200 Subject: [PATCH 18/24] fix(mint): refactor out getattr and inspect.iscoroutinefunction workarounds in Breez SDK integration --- cashu/lightning/sparkl2.py | 101 +++++++++++++++---------------------- 1 file changed, 42 insertions(+), 59 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index 33528ef37..50b4bcc2f 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -1,5 +1,4 @@ import asyncio -import inspect import os from typing import AsyncGenerator, Optional @@ -38,7 +37,7 @@ async def on_event(self, event: breez_sdk_spark.SdkEvent): # We extract the checking_id (payment hash) details = payment.details if details and details.is_lightning(): - htlc = getattr(details, "htlc_details", None) + htlc = details.htlc_details if htlc and htlc.payment_hash: await self.wallet.payment_queue.put(htlc.payment_hash) # If it's a spark payment (on-chain/deposit/etc), we might not have a simple payment hash @@ -95,32 +94,16 @@ async def _ensure_sdk(self): os.makedirs(storage_dir, exist_ok=True) try: - # We run this in a thread because breez SDK connect is blocking in python (currently) - # Actually, `connect` is async in Python. Let's await it. - # wait, breez_sdk_spark python binding functions are actually async? No they are sync. - if inspect.iscoroutinefunction(breez_sdk_spark.connect): - self.sdk = await breez_sdk_spark.connect( - request=breez_sdk_spark.ConnectRequest( - config=config, - seed=seed, - storage_dir=storage_dir - ) - ) - else: - self.sdk = await asyncio.to_thread( - breez_sdk_spark.connect, - request=breez_sdk_spark.ConnectRequest( - config=config, - seed=seed, - storage_dir=storage_dir - ) + self.sdk = await breez_sdk_spark.connect( + request=breez_sdk_spark.ConnectRequest( + config=config, + seed=seed, + storage_dir=storage_dir ) + ) self.listener = _SdkEventListener(self) - if inspect.iscoroutinefunction(self.sdk.add_event_listener): - await self.sdk.add_event_listener(self.listener) - else: - self.sdk.add_event_listener(self.listener) + await self.sdk.add_event_listener(self.listener) logger.info("Breez Spark SDK initialized successfully.") @@ -139,10 +122,8 @@ async def status(self) -> StatusResponse: ) req = breez_sdk_spark.GetInfoRequest(ensure_synced=False) - if inspect.iscoroutinefunction(self.sdk.get_info): - info = await self.sdk.get_info(req) - else: - info = await asyncio.to_thread(self.sdk.get_info, req) + info = await self.sdk.get_info(req) + balance_sats = info.balance_sats balance = Amount(Unit.sat, balance_sats) if self.unit == Unit.msat: @@ -180,10 +161,7 @@ async def create_invoice( ) ) - if inspect.iscoroutinefunction(self.sdk.receive_payment): - res = await self.sdk.receive_payment(req) - else: - res = await asyncio.to_thread(self.sdk.receive_payment, req) + res = await self.sdk.receive_payment(req) # The response contains the invoice string invoice = res.payment_request @@ -218,14 +196,21 @@ async def pay_invoice( fee_policy=None # Can pass fee limits here if supported ) - if inspect.iscoroutinefunction(self.sdk.prepare_send_payment): - prepare_res = await self.sdk.prepare_send_payment(prepare_req) - else: - prepare_res = await asyncio.to_thread(self.sdk.prepare_send_payment, prepare_req) + prepare_res = await self.sdk.prepare_send_payment(prepare_req) # Ensure fee is within limits - fee_sats = getattr(prepare_res.payment_method, "lightning_fee_sats", 0) - spark_fee = getattr(prepare_res.payment_method, "spark_transfer_fee_sats", 0) or 0 + if prepare_res.payment_method.is_bolt11_invoice(): + pm = prepare_res.payment_method + fee_sats = pm.lightning_fee_sats or 0 + spark_fee = pm.spark_transfer_fee_sats or 0 + elif prepare_res.payment_method.is_spark_invoice(): + pm = prepare_res.payment_method + fee_sats = pm.lightning_fee_sats or 0 + spark_fee = pm.spark_transfer_fee_sats or 0 + else: + fee_sats = 0 + spark_fee = 0 + total_fee_sats = fee_sats + spark_fee if total_fee_sats * 1000 > fee_limit_msat: @@ -238,10 +223,7 @@ async def pay_invoice( prepare_response=prepare_res ) - if inspect.iscoroutinefunction(self.sdk.send_payment): - send_res = await self.sdk.send_payment(send_req) - else: - send_res = await asyncio.to_thread(self.sdk.send_payment, send_req) + send_res = await self.sdk.send_payment(send_req) return PaymentResponse( result=PaymentResult.PENDING, @@ -269,15 +251,12 @@ async def get_invoice_status(self, checking_id: str) -> PaymentStatus: asset_filter=None, ) - if inspect.iscoroutinefunction(self.sdk.list_payments): - res = await self.sdk.list_payments(req) - else: - res = await asyncio.to_thread(self.sdk.list_payments, req) + res = await self.sdk.list_payments(req) for p in res.payments: if p.payment_type == breez_sdk_spark.PaymentType.RECEIVE: if p.details and p.details.is_lightning(): - htlc = getattr(p.details, "htlc_details", None) + htlc = p.details.htlc_details if htlc and htlc.payment_hash == checking_id: if p.status == breez_sdk_spark.PaymentStatus.COMPLETED: return PaymentStatus(result=PaymentResult.SETTLED) @@ -297,10 +276,7 @@ async def get_payment_status(self, checking_id: str) -> PaymentStatus: try: req = breez_sdk_spark.GetPaymentRequest(payment_id=checking_id) - if inspect.iscoroutinefunction(self.sdk.get_payment): - res = await self.sdk.get_payment(req) - else: - res = await asyncio.to_thread(self.sdk.get_payment, req) + res = await self.sdk.get_payment(req) if not res or not res.payment: return PaymentStatus(result=PaymentResult.UNKNOWN, error_message="Payment not found") @@ -315,7 +291,7 @@ async def get_payment_status(self, checking_id: str) -> PaymentStatus: preimage = None if payment.details and payment.details.is_lightning(): - htlc = getattr(payment.details, "htlc_details", None) + htlc = payment.details.htlc_details if htlc: preimage = htlc.preimage @@ -347,13 +323,20 @@ async def get_payment_quote( fee_policy=None ) - if inspect.iscoroutinefunction(self.sdk.prepare_send_payment): - prepare_res = await self.sdk.prepare_send_payment(prepare_req) - else: - prepare_res = await asyncio.to_thread(self.sdk.prepare_send_payment, prepare_req) + prepare_res = await self.sdk.prepare_send_payment(prepare_req) - fee_sats = getattr(prepare_res.payment_method, "lightning_fee_sats", 0) - spark_fee = getattr(prepare_res.payment_method, "spark_transfer_fee_sats", 0) or 0 + if prepare_res.payment_method.is_bolt11_invoice(): + pm = prepare_res.payment_method + fee_sats = pm.lightning_fee_sats or 0 + spark_fee = pm.spark_transfer_fee_sats or 0 + elif prepare_res.payment_method.is_spark_invoice(): + pm = prepare_res.payment_method + fee_sats = pm.lightning_fee_sats or 0 + spark_fee = pm.spark_transfer_fee_sats or 0 + else: + fee_sats = 0 + spark_fee = 0 + total_fee_sats = fee_sats + spark_fee fee_amount = Amount(Unit.sat, total_fee_sats) From 3f23d954da54b306da0803f5474a316ea20675c3 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Wed, 27 May 2026 10:17:09 +0200 Subject: [PATCH 19/24] fix(mint): map correct Spark L2 status on payment completion and treat all exceptions as PENDING --- cashu/lightning/sparkl2.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index 50b4bcc2f..c8f16dcb3 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -225,14 +225,37 @@ async def pay_invoice( send_res = await self.sdk.send_payment(send_req) + payment = send_res.payment + fee_amount = None + if payment.fees is not None: + if self.unit == Unit.msat: + fee_amount = Amount(Unit.msat, payment.fees * 1000) + else: + fee_amount = Amount(Unit.sat, payment.fees) + + preimage = None + if payment.details and payment.details.is_lightning(): + htlc = payment.details.htlc_details + if htlc: + preimage = htlc.preimage + + if payment.status == breez_sdk_spark.PaymentStatus.COMPLETED: + result = PaymentResult.SETTLED + elif payment.status == breez_sdk_spark.PaymentStatus.FAILED: + result = PaymentResult.FAILED + else: + result = PaymentResult.PENDING + return PaymentResponse( - result=PaymentResult.PENDING, - checking_id=send_res.payment.id, + result=result, + checking_id=payment.id, + fee=fee_amount, + preimage=preimage, ) except Exception as e: return PaymentResponse( - result=PaymentResult.FAILED, - error_message=f"Payment failed: {str(e)}" + result=PaymentResult.PENDING, + error_message=f"Payment failed or unknown: {str(e)}" ) async def get_invoice_status(self, checking_id: str) -> PaymentStatus: From b269a7df35359864021c0c43072aa77a5df3bd2d Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Fri, 29 May 2026 00:44:39 +0200 Subject: [PATCH 20/24] fix(sparkl2): prevent description_hash from being used as payment_hash --- cashu/lightning/sparkl2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index c8f16dcb3..dbd685c1a 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -157,7 +157,7 @@ async def create_invoice( description=(memo or "") if not description_hash else "", amount_sats=amount_sats, expiry_secs=None, - payment_hash=description_hash.hex() if description_hash else None + payment_hash=None ) ) From 9067c249c7b935fe743de4354ce7b4791095b121 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Thu, 4 Jun 2026 21:58:41 +0200 Subject: [PATCH 21/24] fix(sparkl2): robustly cap fees across all payment methods to prevent siphoning attacks --- cashu/lightning/sparkl2.py | 51 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index dbd685c1a..56b718914 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -62,6 +62,29 @@ def __init__(self, unit: Unit, **kwargs): self.payment_queue: asyncio.Queue[str] = asyncio.Queue() self.listener: Optional[_SdkEventListener] = None + def _get_total_fee_sats(self, payment_method: breez_sdk_spark.SendPaymentMethod) -> int: + if payment_method.is_bolt11_invoice(): + pm = payment_method + fee_sats = pm.lightning_fee_sats or 0 + spark_fee = pm.spark_transfer_fee_sats or 0 + return fee_sats + spark_fee + elif payment_method.is_spark_invoice(): + pm = payment_method + return int(pm.fee) + elif payment_method.is_spark_address(): + pm = payment_method + return int(pm.fee) + elif payment_method.is_bitcoin_address(): + pm = payment_method + fq = pm.fee_quote + fees = [] + for speed in [fq.speed_fast, fq.speed_medium, fq.speed_slow]: + if speed: + fees.append(speed.user_fee_sat + speed.l1_broadcast_fee_sat) + return max(fees) if fees else 0 + else: + return 0 + async def _ensure_sdk(self): if self.sdk is not None: return @@ -199,19 +222,7 @@ async def pay_invoice( prepare_res = await self.sdk.prepare_send_payment(prepare_req) # Ensure fee is within limits - if prepare_res.payment_method.is_bolt11_invoice(): - pm = prepare_res.payment_method - fee_sats = pm.lightning_fee_sats or 0 - spark_fee = pm.spark_transfer_fee_sats or 0 - elif prepare_res.payment_method.is_spark_invoice(): - pm = prepare_res.payment_method - fee_sats = pm.lightning_fee_sats or 0 - spark_fee = pm.spark_transfer_fee_sats or 0 - else: - fee_sats = 0 - spark_fee = 0 - - total_fee_sats = fee_sats + spark_fee + total_fee_sats = self._get_total_fee_sats(prepare_res.payment_method) if total_fee_sats * 1000 > fee_limit_msat: return PaymentResponse( @@ -348,19 +359,7 @@ async def get_payment_quote( prepare_res = await self.sdk.prepare_send_payment(prepare_req) - if prepare_res.payment_method.is_bolt11_invoice(): - pm = prepare_res.payment_method - fee_sats = pm.lightning_fee_sats or 0 - spark_fee = pm.spark_transfer_fee_sats or 0 - elif prepare_res.payment_method.is_spark_invoice(): - pm = prepare_res.payment_method - fee_sats = pm.lightning_fee_sats or 0 - spark_fee = pm.spark_transfer_fee_sats or 0 - else: - fee_sats = 0 - spark_fee = 0 - - total_fee_sats = fee_sats + spark_fee + total_fee_sats = self._get_total_fee_sats(prepare_res.payment_method) fee_amount = Amount(Unit.sat, total_fee_sats) if self.unit == Unit.msat: From ed4a07a938c89d562e9eb81154ac5cce478cea57 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Thu, 4 Jun 2026 22:04:24 +0200 Subject: [PATCH 22/24] fix(sparkl2): disable support for on-chain bitcoin payments --- cashu/lightning/sparkl2.py | 9 +++ .../test_lightning_backends_mocked.py | 68 +++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index 56b718914..b73ce87a5 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -221,6 +221,12 @@ async def pay_invoice( prepare_res = await self.sdk.prepare_send_payment(prepare_req) + if prepare_res.payment_method.is_bitcoin_address(): + return PaymentResponse( + result=PaymentResult.FAILED, + error_message="On-chain bitcoin payments are not supported by this mint" + ) + # Ensure fee is within limits total_fee_sats = self._get_total_fee_sats(prepare_res.payment_method) @@ -359,6 +365,9 @@ async def get_payment_quote( prepare_res = await self.sdk.prepare_send_payment(prepare_req) + if prepare_res.payment_method.is_bitcoin_address(): + raise Exception("On-chain bitcoin payments are not supported by this mint") + total_fee_sats = self._get_total_fee_sats(prepare_res.payment_method) fee_amount = Amount(Unit.sat, total_fee_sats) diff --git a/tests/lightning/test_lightning_backends_mocked.py b/tests/lightning/test_lightning_backends_mocked.py index 69e0685e2..ea997f15f 100644 --- a/tests/lightning/test_lightning_backends_mocked.py +++ b/tests/lightning/test_lightning_backends_mocked.py @@ -529,3 +529,71 @@ async def post(self, *args, **kwargs): cast(Any, wallet).client = Client() with pytest.raises(Exception, match="Currency conversion service unavailable"): await wallet._get_sats_per_usd() + + +@pytest.mark.asyncio +async def test_spark_pay_invoice_rejects_on_chain(): + from cashu.lightning.sparkl2 import SparkL2Wallet + wallet = object.__new__(SparkL2Wallet) + wallet.unit = Unit.sat + + async def mock_ensure_sdk(): + pass + wallet._ensure_sdk = mock_ensure_sdk + + class MockMethod: + def is_bitcoin_address(self): + return True + def is_bolt11_invoice(self): + return False + def is_spark_invoice(self): + return False + def is_spark_address(self): + return False + + class MockPrepareResponse: + payment_method = MockMethod() + + class MockSDK: + async def prepare_send_payment(self, req): + return MockPrepareResponse() + + wallet.sdk = MockSDK() + + res = await wallet.pay_invoice(_quote("on-chain-addr"), 1000) + assert res.result == PaymentResult.FAILED + assert "On-chain bitcoin payments are not supported" in res.error_message + + +@pytest.mark.asyncio +async def test_spark_get_payment_quote_rejects_on_chain(): + from cashu.lightning.sparkl2 import SparkL2Wallet + wallet = object.__new__(SparkL2Wallet) + wallet.unit = Unit.sat + + async def mock_ensure_sdk(): + pass + wallet._ensure_sdk = mock_ensure_sdk + + class MockMethod: + def is_bitcoin_address(self): + return True + def is_bolt11_invoice(self): + return False + def is_spark_invoice(self): + return False + def is_spark_address(self): + return False + + class MockPrepareResponse: + payment_method = MockMethod() + + class MockSDK: + async def prepare_send_payment(self, req): + return MockPrepareResponse() + + wallet.sdk = MockSDK() + + melt_quote = PostMeltQuoteRequest(unit="sat", request="on-chain-addr") + with pytest.raises(Exception, match="On-chain bitcoin payments are not supported"): + await wallet.get_payment_quote(melt_quote) From 10743a5a992124bb12a7026c988c99e036580125 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Fri, 5 Jun 2026 09:29:55 +0200 Subject: [PATCH 23/24] fix(sparkl2): enforce only BOLT11 payments in backend to match Cashu melt path --- cashu/lightning/sparkl2.py | 43 ++++++------------- .../test_lightning_backends_mocked.py | 24 +++-------- 2 files changed, 19 insertions(+), 48 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index b73ce87a5..859a853b3 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -62,29 +62,6 @@ def __init__(self, unit: Unit, **kwargs): self.payment_queue: asyncio.Queue[str] = asyncio.Queue() self.listener: Optional[_SdkEventListener] = None - def _get_total_fee_sats(self, payment_method: breez_sdk_spark.SendPaymentMethod) -> int: - if payment_method.is_bolt11_invoice(): - pm = payment_method - fee_sats = pm.lightning_fee_sats or 0 - spark_fee = pm.spark_transfer_fee_sats or 0 - return fee_sats + spark_fee - elif payment_method.is_spark_invoice(): - pm = payment_method - return int(pm.fee) - elif payment_method.is_spark_address(): - pm = payment_method - return int(pm.fee) - elif payment_method.is_bitcoin_address(): - pm = payment_method - fq = pm.fee_quote - fees = [] - for speed in [fq.speed_fast, fq.speed_medium, fq.speed_slow]: - if speed: - fees.append(speed.user_fee_sat + speed.l1_broadcast_fee_sat) - return max(fees) if fees else 0 - else: - return 0 - async def _ensure_sdk(self): if self.sdk is not None: return @@ -221,14 +198,17 @@ async def pay_invoice( prepare_res = await self.sdk.prepare_send_payment(prepare_req) - if prepare_res.payment_method.is_bitcoin_address(): + if not prepare_res.payment_method.is_bolt11_invoice(): return PaymentResponse( result=PaymentResult.FAILED, - error_message="On-chain bitcoin payments are not supported by this mint" + error_message="Only BOLT11 payments are supported" ) # Ensure fee is within limits - total_fee_sats = self._get_total_fee_sats(prepare_res.payment_method) + pm = prepare_res.payment_method + fee_sats = pm.lightning_fee_sats or 0 + spark_fee = pm.spark_transfer_fee_sats or 0 + total_fee_sats = fee_sats + spark_fee if total_fee_sats * 1000 > fee_limit_msat: return PaymentResponse( @@ -365,10 +345,13 @@ async def get_payment_quote( prepare_res = await self.sdk.prepare_send_payment(prepare_req) - if prepare_res.payment_method.is_bitcoin_address(): - raise Exception("On-chain bitcoin payments are not supported by this mint") - - total_fee_sats = self._get_total_fee_sats(prepare_res.payment_method) + if not prepare_res.payment_method.is_bolt11_invoice(): + raise Exception("Only BOLT11 payments are supported") + + pm = prepare_res.payment_method + fee_sats = pm.lightning_fee_sats or 0 + spark_fee = pm.spark_transfer_fee_sats or 0 + total_fee_sats = fee_sats + spark_fee fee_amount = Amount(Unit.sat, total_fee_sats) if self.unit == Unit.msat: diff --git a/tests/lightning/test_lightning_backends_mocked.py b/tests/lightning/test_lightning_backends_mocked.py index ea997f15f..3b53dca72 100644 --- a/tests/lightning/test_lightning_backends_mocked.py +++ b/tests/lightning/test_lightning_backends_mocked.py @@ -532,7 +532,7 @@ async def post(self, *args, **kwargs): @pytest.mark.asyncio -async def test_spark_pay_invoice_rejects_on_chain(): +async def test_spark_pay_invoice_rejects_non_bolt11(): from cashu.lightning.sparkl2 import SparkL2Wallet wallet = object.__new__(SparkL2Wallet) wallet.unit = Unit.sat @@ -542,14 +542,8 @@ async def mock_ensure_sdk(): wallet._ensure_sdk = mock_ensure_sdk class MockMethod: - def is_bitcoin_address(self): - return True def is_bolt11_invoice(self): return False - def is_spark_invoice(self): - return False - def is_spark_address(self): - return False class MockPrepareResponse: payment_method = MockMethod() @@ -560,13 +554,13 @@ async def prepare_send_payment(self, req): wallet.sdk = MockSDK() - res = await wallet.pay_invoice(_quote("on-chain-addr"), 1000) + res = await wallet.pay_invoice(_quote("non-bolt11"), 1000) assert res.result == PaymentResult.FAILED - assert "On-chain bitcoin payments are not supported" in res.error_message + assert "Only BOLT11 payments are supported" in res.error_message @pytest.mark.asyncio -async def test_spark_get_payment_quote_rejects_on_chain(): +async def test_spark_get_payment_quote_rejects_non_bolt11(): from cashu.lightning.sparkl2 import SparkL2Wallet wallet = object.__new__(SparkL2Wallet) wallet.unit = Unit.sat @@ -576,14 +570,8 @@ async def mock_ensure_sdk(): wallet._ensure_sdk = mock_ensure_sdk class MockMethod: - def is_bitcoin_address(self): - return True def is_bolt11_invoice(self): return False - def is_spark_invoice(self): - return False - def is_spark_address(self): - return False class MockPrepareResponse: payment_method = MockMethod() @@ -594,6 +582,6 @@ async def prepare_send_payment(self, req): wallet.sdk = MockSDK() - melt_quote = PostMeltQuoteRequest(unit="sat", request="on-chain-addr") - with pytest.raises(Exception, match="On-chain bitcoin payments are not supported"): + melt_quote = PostMeltQuoteRequest(unit="sat", request="non-bolt11") + with pytest.raises(Exception, match="Only BOLT11 payments are supported"): await wallet.get_payment_quote(melt_quote) From 7115a65324202c919bb27b259ec620e109adda8a Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Sat, 13 Jun 2026 10:22:15 +0200 Subject: [PATCH 24/24] fix(sparkl2): optimize get_invoice_status by filtering list_payments --- cashu/lightning/sparkl2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cashu/lightning/sparkl2.py b/cashu/lightning/sparkl2.py index 859a853b3..2b03893ad 100644 --- a/cashu/lightning/sparkl2.py +++ b/cashu/lightning/sparkl2.py @@ -266,9 +266,9 @@ async def get_invoice_status(self, checking_id: str) -> PaymentStatus: # Breez SDK provides list_payments but it might be inefficient. # However, for Spark L2 it's local. req = breez_sdk_spark.ListPaymentsRequest( - type_filter=None, - status_filter=None, - asset_filter=None, + type_filter=[breez_sdk_spark.PaymentType.RECEIVE], + asset_filter=breez_sdk_spark.AssetFilter.BITCOIN(), + payment_details_filter=[breez_sdk_spark.PaymentDetailsFilter.LIGHTNING(None)], ) res = await self.sdk.list_payments(req)