Compare commits

..
Author SHA1 Message Date
Vlad Stan 4744ef9bba Merge branch 'more_unit_tests' of https://github.com/lnbits/lnbits into more_unit_tests 2026-03-30 16:00:12 +03:00
Vlad Stan fdf061c08d chore: make regtest wait 2026-03-30 15:32:42 +03:00
Vlad Stan d348234cad fix: aaaaa 2026-03-30 15:32:42 +03:00
Vlad Stan fc5261132e fix: regtests 2026-03-30 15:32:42 +03:00
Vlad Stan 4e18c423de chore: check log 2026-03-30 15:32:42 +03:00
Vlad Stan 37e5601207 fix: try clean-up 2026-03-30 15:32:42 +03:00
Vlad Stan 231f6fc01c fix: is boltz wallet 2026-03-30 15:32:42 +03:00
Vlad Stan 811957f5e1 chore: logs 2026-03-30 15:32:42 +03:00
Vlad Stan c63a53cb14 chore: some logs 2026-03-30 15:32:42 +03:00
Vlad Stan 78b8f7f16e fix: hope for regtest to work 2026-03-30 15:32:42 +03:00
Vlad Stan 4642878c05 fix: test 2026-03-30 15:32:42 +03:00
Vlad Stan d7c850ccbb fix: test funding source 2026-03-30 15:32:42 +03:00
Vlad Stan 4fbb4b5eef chore: fix lint 2026-03-30 15:32:42 +03:00
Vlad Stan db2829a5f6 chore: postpone test 2026-03-30 15:31:59 +03:00
Vlad Stan 13ce1ac172 chore: fix lint 2026-03-30 15:08:42 +03:00
Vlad Stan 512697ae53 test: more tests 2026-03-30 14:58:04 +03:00
Vlad Stan dfa89ca063 test: some tests 2026-03-30 13:18:36 +03:00
Vlad Stan 182694d2e5 fix: bad config 2026-03-30 13:12:47 +03:00
Vlad Stan 2f10c57a10 fix: timeout 2026-03-30 13:12:46 +03:00
Vlad Stan d685824596 fix: test funding source 2026-03-30 13:12:46 +03:00
Vlad Stan e816eb2dac fix: date 2026-03-30 13:12:46 +03:00
Vlad Stan d3c099350a chore: fix lint 2026-03-30 13:12:46 +03:00
Vlad Stan 691ac969dc chore: postpone test 2026-03-30 13:12:46 +03:00
Vlad Stan 85e8ac6057 refactor: extract helpers, move private functions to the bottom 2026-03-30 13:12:46 +03:00
Vlad Stan 99da300f6d chore: code lint 2026-03-30 13:12:46 +03:00
Vlad Stan cd413d85ed fix: tests 2026-03-30 13:12:46 +03:00
Vlad Stan 9245e2c268 fix: lint 2026-03-30 13:12:46 +03:00
Vlad Stan 0b5c8cdee2 test: more api tests 2026-03-30 13:12:46 +03:00
Vlad Stan c94cef07c2 chore: fix lint 2026-03-30 13:12:46 +03:00
Vlad Stan 22b4ab779f test: more tests 2026-03-30 13:12:46 +03:00
Vlad Stan 42061d0cc8 test: some tests 2026-03-30 13:12:46 +03:00
Vlad Stan d0ea42fd70 chore: make regtest wait 2026-03-26 12:28:12 +02:00
Vlad Stan cd58a0dc9b fix: aaaaa 2026-03-26 12:12:13 +02:00
Vlad Stan cac4e309f4 fix: regtests 2026-03-26 11:57:25 +02:00
Vlad Stan 632cd257d7 chore: check log 2026-03-26 11:50:30 +02:00
Vlad Stan a11274593c fix: try clean-up 2026-03-26 11:49:57 +02:00
Vlad Stan ae92965b69 fix: is boltz wallet 2026-03-26 11:45:16 +02:00
Vlad Stan 3e1f75c4cc chore: logs 2026-03-26 11:32:02 +02:00
Vlad Stan d668747ca2 chore: some logs 2026-03-26 11:24:18 +02:00
Vlad Stan dedfcd4818 fix: hope for regtest to work 2026-03-25 11:37:21 +02:00
Vlad Stan f66f2fe6c2 fix: test 2026-03-25 11:24:25 +02:00
Vlad Stan f3ca37e846 Merge branch 'more_unit_tests' of https://github.com/lnbits/lnbits into more_unit_tests 2026-03-25 10:54:23 +02:00
Vlad Stan d45709a80f fix: bad config 2026-03-25 10:53:25 +02:00
Vlad Stan e4b6dc84b5 fix: timeout 2026-03-25 10:49:52 +02:00
Vlad Stan 67d1b4be3e fix: test funding source 2026-03-25 10:49:52 +02:00
Vlad Stan bd514f1a46 fix: date 2026-03-25 10:49:52 +02:00
Vlad Stan 03b302da69 chore: fix lint 2026-03-25 10:49:52 +02:00
Vlad Stan b373e35915 chore: postpone test 2026-03-25 10:49:52 +02:00
Vlad Stan 0fd116e7ee refactor: extract helpers, move private functions to the bottom 2026-03-25 10:49:52 +02:00
Vlad Stan 2c84f9781d chore: code lint 2026-03-25 10:49:52 +02:00
Vlad Stan 9fcf3121ac fix: tests 2026-03-25 10:49:52 +02:00
Vlad Stan 1df9fa831d fix: lint 2026-03-25 10:49:52 +02:00
Vlad Stan 42039070b9 test: more api tests 2026-03-25 10:49:52 +02:00
Vlad Stan 2f9146fff3 chore: fix lint 2026-03-25 10:49:52 +02:00
Vlad Stan 5738795c8c test: more tests 2026-03-25 10:49:52 +02:00
Vlad Stan 3c77acf266 test: some tests 2026-03-25 10:49:52 +02:00
Vlad Stan a4f2f55279 fix: timeout 2026-03-23 14:01:55 +02:00
Vlad Stan 2ab7c17ceb fix: test funding source 2026-03-23 12:33:57 +02:00
Vlad Stan 7a2c509cd3 fix: date 2026-03-23 12:32:39 +02:00
Vlad Stan 8a51ea53c8 chore: fix lint 2026-03-23 12:32:39 +02:00
Vlad Stan 19d3e9e64e chore: postpone test 2026-03-23 12:32:39 +02:00
Vlad Stan 9f9f14ead0 refactor: extract helpers, move private functions to the bottom 2026-03-23 12:32:39 +02:00
Vlad Stan 0a093d82ae chore: code lint 2026-03-23 12:32:39 +02:00
Vlad Stan 17fd459fa7 fix: tests 2026-03-23 12:32:39 +02:00
Vlad Stan fe9aa4d8c9 fix: lint 2026-03-23 12:32:39 +02:00
Vlad Stan 1af3b62739 test: more api tests 2026-03-23 12:32:39 +02:00
Vlad Stan e9cbc3492f chore: fix lint 2026-03-23 12:32:39 +02:00
Vlad Stan ca2f78d25b test: more tests 2026-03-23 12:32:39 +02:00
Vlad Stan 9d9ab48345 test: some tests 2026-03-23 12:32:39 +02:00
22 changed files with 56 additions and 178 deletions
-4
View File
@@ -24,10 +24,6 @@ LOG_ROTATION="100 MB"
LOG_RETENTION="3 months"
# for database cleanup commands
# CLEANUP_WALLETS_DAYS=90
# Hard limit for total created users. Set to 0 to disable the limit.
# LNBITS_MAX_USERS=0
# Hard limit for total installed extensions. Set to 0 to disable the limit.
# LNBITS_MAX_EXTENSIONS=0
# === Admin Settings ===
-3
View File
@@ -69,10 +69,7 @@ jobs:
--onefile \
--name lnbits \
--hidden-import=embit \
--hidden-import=bitstring.bitstore_bitarray \
--collect-all embit \
--collect-all bitstring \
--collect-all bitarray \
--collect-all lnbits \
--collect-all sqlalchemy \
--collect-all breez_sdk \
+1 -1
View File
@@ -65,7 +65,7 @@ jobs:
make: openapi
regtest:
needs: [ lint ]
needs: [ lint, test-api, test-wallets, test-unit, migration, openapi ]
uses: ./.github/workflows/regtest.yml
strategy:
matrix:
-1
View File
@@ -6,7 +6,6 @@ __pycache__
*$py.class
.mypy_cache
.vscode
.codex
*-lock.json
.python-version
-4
View File
@@ -12,7 +12,6 @@ from .extensions import (
drop_extension_db,
get_installed_extension,
get_installed_extensions,
get_installed_extensions_count,
get_user_active_extensions_ids,
get_user_extension,
get_user_extensions,
@@ -59,7 +58,6 @@ from .users import (
get_account_by_username,
get_account_by_username_or_email,
get_accounts,
get_accounts_count,
get_user,
get_user_access_control_lists,
get_user_from_account,
@@ -119,13 +117,11 @@ __all__ = [
"get_account_by_username",
"get_account_by_username_or_email",
"get_accounts",
"get_accounts_count",
"get_admin_settings",
"get_db_version",
"get_db_versions",
"get_installed_extension",
"get_installed_extensions",
"get_installed_extensions_count",
"get_latest_payments_by_extension",
"get_payment",
"get_payments",
-7
View File
@@ -90,13 +90,6 @@ async def get_installed_extensions(
return all_extensions
async def get_installed_extensions_count(conn: Connection | None = None) -> int:
row: dict | None = await (conn or db).fetchone(
"SELECT COUNT(*) as count FROM installed_extensions"
)
return int(row["count"]) if row else 0
async def get_user_extension(
user_id: str, extension: str, conn: Connection | None = None
) -> UserExtension | None:
-7
View File
@@ -37,13 +37,6 @@ async def create_account(
return account
async def get_accounts_count(conn: Connection | None = None) -> int:
row: dict | None = await (conn or db).fetchone(
"SELECT COUNT(*) as count FROM accounts"
)
return int(row["count"]) if row else 0
async def update_account(account: Account, conn: Connection | None = None) -> Account:
account.updated_at = datetime.now(timezone.utc)
await (conn or db).update("accounts", account)
-12
View File
@@ -9,7 +9,6 @@ from lnbits.core.crud import (
delete_installed_extension,
get_db_version,
get_installed_extension,
get_installed_extensions_count,
update_installed_extension_state,
)
from lnbits.core.crud.extensions import (
@@ -39,8 +38,6 @@ async def install_extension(
if installed_ext and installed_ext.meta:
ext_info.meta.payments = installed_ext.meta.payments
await check_extensions_limit(installed_ext)
if not skip_download:
await ext_info.download_archive()
@@ -66,15 +63,6 @@ async def install_extension(
return extension
async def check_extensions_limit(installed_ext: InstallableExtension | None = None):
if settings.lnbits_max_extensions == 0 or installed_ext:
return
extensions_count = await get_installed_extensions_count()
if extensions_count >= settings.lnbits_max_extensions:
raise ValueError("Max amount of extensions have been installed")
async def uninstall_extension(ext_id: str):
await stop_extension_background_work(ext_id)
-12
View File
@@ -23,7 +23,6 @@ from ..crud import (
get_account_by_email,
get_account_by_pubkey,
get_account_by_username,
get_accounts_count,
get_super_settings,
get_user_extensions,
get_user_from_account,
@@ -56,8 +55,6 @@ async def create_user_account_no_ckeck(
conn: Connection | None = None,
) -> User:
async with db.reuse_conn(conn) if conn else db.connect() as conn:
await check_users_limit(conn)
if account:
account.validate_fields()
if account.username and await get_account_by_username(
@@ -98,15 +95,6 @@ async def create_user_account_no_ckeck(
return user
async def check_users_limit(conn: Connection | None = None):
if settings.lnbits_max_users == 0:
return
users_count = await get_accounts_count(conn=conn)
if users_count >= settings.lnbits_max_users:
raise ValueError("Max amount of users have been created")
async def update_user_account(account: Account) -> Account:
account.validate_fields()
+2 -6
View File
@@ -98,16 +98,12 @@ async def api_install_extension(data: CreateExtension):
ext_info.clean_extension_files()
detail = (
str(exc)
if isinstance(exc, (AssertionError, ValueError))
if isinstance(exc, AssertionError)
else f"Failed to install extension '{ext_info.id}'."
f"({ext_info.installed_version})."
)
raise HTTPException(
status_code=(
HTTPStatus.BAD_REQUEST
if isinstance(exc, (AssertionError, ValueError))
else HTTPStatus.INTERNAL_SERVER_ERROR
),
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=detail,
) from exc
+2 -5
View File
@@ -1007,9 +1007,8 @@ class EnvSettings(LNbitsSettings):
debug_database: bool = Field(default=False)
bundle_assets: bool = Field(default=True)
# When enabled, auth cookies require HTTPS and SSO will reject insecure HTTP.
# Keep disabled by default so local HTTP installs continue to work unless
# operators explicitly opt into HTTPS-only auth cookies.
auth_https_only: bool = Field(default=False)
# Set to false for local/dev environments that run without TLS.
auth_https_only: bool = Field(default=True)
host: str = Field(default="127.0.0.1")
port: int = Field(default=5000, gt=0)
forwarded_allow_ips: str = Field(default="*")
@@ -1027,8 +1026,6 @@ class EnvSettings(LNbitsSettings):
cleanup_wallets_days: int = Field(default=90, ge=0)
funding_source_max_retries: int = Field(default=4, ge=0)
lnbits_max_users: int = Field(default=0, ge=0)
lnbits_max_extensions: int = Field(default=0, ge=0)
@property
def has_default_extension_path(self) -> bool:
+29 -29
View File
@@ -75,35 +75,7 @@
</p>
</div>
</div>
<div v-if="isSuperUser">
<lnbits-admin-funding-sources
:form-data="formData"
:allowed-funding-sources="settings.lnbits_allowed_funding_sources"
/>
<div class="row q-col-gutter-md q-my-md">
<div class="col-12 col-sm-8">
<q-item tag="div">
<q-item-section>
<q-item-label
v-text="$t('funding_source_retries')"
></q-item-label>
<q-item-label
caption
v-text="$t('funding_source_retries_desc')"
></q-item-label>
</q-item-section>
<q-item-section>
<q-input
filled
v-model="formData.funding_source_max_retries"
type="number"
/>
</q-item-section>
</q-item>
</div>
</div>
</div>
<div class="row q-col-gutter-md q-mt-lg">
<div class="row q-col-gutter-md">
<div class="col-12">
<h6 class="q-my-none">
<span v-text="$t('routing_fee_reserve_calculations')"></span>
@@ -210,6 +182,34 @@
></q-input>
</div>
</div>
<div v-if="isSuperUser">
<lnbits-admin-funding-sources
:form-data="formData"
:allowed-funding-sources="settings.lnbits_allowed_funding_sources"
/>
<div class="row q-col-gutter-md q-my-md">
<div class="col-12 col-sm-8">
<q-item tag="div">
<q-item-section>
<q-item-label
v-text="$t('funding_source_retries')"
></q-item-label>
<q-item-label
caption
v-text="$t('funding_source_retries_desc')"
></q-item-label>
</q-item-section>
<q-item-section>
<q-input
filled
v-model="formData.funding_source_max_retries"
type="number"
/>
</q-item-section>
</q-item>
</div>
</div>
</div>
<q-separator></q-separator>
<h6 class="q-mt-lg q-mb-sm">
<p v-text="$t('watchdog')"></p>
-1
View File
@@ -61,7 +61,6 @@ lnbits-cli = "lnbits.commands:main"
breez = ["breez-sdk~=0.8.0", "breez-sdk-liquid~=0.11.11"]
liquid = ["wallycore~=1.5.1"]
migration = ["psycopg2-binary~=2.9.11"]
wasm = ["wasmtime>=43.0.0"]
[dependency-groups]
dev = [
-42
View File
@@ -135,8 +135,6 @@ async def test_auth_api_first_install_success_and_validation(
)
assert success.status_code == 200
assert success.json()["access_token"]
assert "cookie_access_token=" in success.headers["set-cookie"]
assert "Secure" not in success.headers["set-cookie"]
updated_superuser = await get_account(settings.super_user, active_only=False)
assert updated_superuser is not None
@@ -161,43 +159,3 @@ async def test_auth_api_first_install_success_and_validation(
await update_account(restored_superuser)
settings.first_install = original_first_install
settings.first_install_token = original_first_install_token
@pytest.mark.anyio
async def test_auth_api_first_install_uses_secure_cookie_when_enabled(
http_client: AsyncClient, settings: Settings
):
superuser = await get_account(settings.super_user, active_only=False)
assert superuser is not None
original_username = superuser.username
original_password_hash = superuser.password_hash
original_first_install = settings.first_install
original_auth_https_only = settings.auth_https_only
new_username = f"secure_{uuid4().hex[:8]}"
try:
settings.first_install = True
settings.auth_https_only = True
success = await http_client.put(
"/api/v1/auth/first_install",
json={
"username": new_username,
"password": "secret1234",
"password_repeat": "secret1234",
},
)
assert success.status_code == 200
assert "cookie_access_token=" in success.headers["set-cookie"]
assert "Secure" in success.headers["set-cookie"]
finally:
restored_superuser = await get_account(settings.super_user, active_only=False)
assert restored_superuser is not None
restored_superuser.username = original_username
restored_superuser.password_hash = original_password_hash
await update_account(restored_superuser)
settings.first_install = original_first_install
settings.auth_https_only = original_auth_https_only
+1 -3
View File
@@ -40,9 +40,7 @@ from tests.helpers import (
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
ADMIN_USER_ID = uuid4().hex
# Snapshot the initialized module settings instead of a fresh Settings() instance.
# The module settings include runtime-populated values like `version`.
_PURE_SETTINGS = copy.deepcopy(lnbits_settings)
_PURE_SETTINGS = Settings()
_PURE_SETTINGS_FIELDS = tuple(
sorted(
{
+1 -3
View File
@@ -28,7 +28,7 @@ from lnbits.core.models.extensions_builder import (
PublicPageFields,
SettingsFields,
)
from lnbits.wallets import get_funding_source, set_funding_source
from lnbits.wallets import get_funding_source
class DbTestModel(BaseModel):
@@ -182,8 +182,6 @@ def make_lnurl_pay_response(
)
set_funding_source()
funding_source = get_funding_source()
is_fake: bool = funding_source.__class__.__name__ == "FakeWallet"
is_regtest: bool = not is_fake
+9 -1
View File
@@ -9,7 +9,15 @@ from loguru import logger
from lnbits.wallets import get_funding_source
funding_source = get_funding_source()
is_boltz_wallet = funding_source.__class__.__name__ == "BoltzWallet"
def is_boltz_wallet():
print(
"### funding_source.__class__.__name__ 2",
get_funding_source().__class__.__name__,
)
return get_funding_source().__class__.__name__ == "BoltzWallet"
docker_lightning_cli = [
"docker",
@@ -21,7 +21,8 @@ async def test_create_invoice(from_wallet):
)
# we cannot know the preimage of the swap yet
if not is_boltz_wallet:
funding_source = get_funding_source()
if not is_boltz_wallet():
assert payment.preimage
invoice = decode(payment.bolt11)
@@ -42,7 +43,8 @@ async def test_create_internal_invoice(from_wallet):
)
# we cannot know the preimage of the swap yet
if not is_boltz_wallet:
funding_source = get_funding_source()
if not is_boltz_wallet():
assert payment.preimage
invoice = decode(payment.bolt11)
+1 -1
View File
@@ -20,7 +20,7 @@ async def test_services_pay_invoice(to_wallet, real_invoice):
)
assert payment
assert payment.memo == description
if not is_boltz_wallet:
if not is_boltz_wallet():
assert payment.status == PaymentState.SUCCESS
assert payment.preimage
else:
+1 -6
View File
@@ -252,12 +252,7 @@ async def test_notification_for_internal_payment(
assert _payment.bolt11 == payment.bolt11
assert _payment.amount == 123_000
updated_payment = await get_payment(_payment.checking_id)
assert (
updated_payment.webhook_status is not None
), "Webhook should have been called."
assert (
int(updated_payment.webhook_status) >= 400
), "Webhook should have been called and failed."
assert updated_payment.webhook_status == "404"
@pytest.mark.anyio
+1 -1
View File
@@ -197,7 +197,7 @@ async def test_update_wallet_balance_validates_credit_and_debit(
settings.lnbits_wallet_limit_max_balance = 0
queue_mock = mocker.patch(
"lnbits.tasks.internal_invoice_queue_put",
"lnbits.core.services.payments.internal_invoice_queue_put",
mocker.AsyncMock(),
)
Generated
+4 -27
View File
@@ -1321,9 +1321,6 @@ liquid = [
migration = [
{ name = "psycopg2-binary" },
]
wasm = [
{ name = "wasmtime" },
]
[package.dev-dependencies]
dev = [
@@ -1394,11 +1391,10 @@ requires-dist = [
{ name = "uvicorn", specifier = "~=0.40.0" },
{ name = "uvloop", specifier = "~=0.22.1" },
{ name = "wallycore", marker = "extra == 'liquid'", specifier = "~=1.5.1" },
{ name = "wasmtime", marker = "extra == 'wasm'", specifier = ">=43.0.0" },
{ name = "websocket-client", specifier = "~=1.9.0" },
{ name = "websockets", specifier = "~=15.0.1" },
]
provides-extras = ["breez", "liquid", "migration", "wasm"]
provides-extras = ["breez", "liquid", "migration"]
[package.metadata.requires-dev]
dev = [
@@ -2026,11 +2022,11 @@ email = [
[[package]]
name = "pygments"
version = "2.20.0"
version = "2.19.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
]
[[package]]
@@ -2784,25 +2780,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/f4/15/38c48fb3319725d946b926090cb3e5fc4dc1fdc15b1fa9fe8474628b6c55/wallycore-1.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:36da969b58cd32f95eba901027595ad35f0326c04c9e5227fa73e0c14203bb4c", size = 1728580, upload-time = "2026-02-02T12:27:01.79Z" },
]
[[package]]
name = "wasmtime"
version = "43.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c3/0e/967542865d59d9529bab604b9b88f09a92636e69cc4b1d30c5013e854493/wasmtime-43.0.0.tar.gz", hash = "sha256:eb98b8e2bc35d03dd69c9dd095a388044323622526fc94a9406b8efc48ddc259", size = 117449, upload-time = "2026-03-31T19:26:23.663Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/10/a9/5e598c9ae8791375fa47b0dad377e0030dcd6da1be527a639670c5a3f9d6/wasmtime-43.0.0-py3-none-android_26_arm64_v8a.whl", hash = "sha256:c52d7bd47481958494b6ef9f0ed56d01ba6d7088cc9adbc1414be899b75bc04d", size = 6895231, upload-time = "2026-03-31T19:26:01.774Z" },
{ url = "https://files.pythonhosted.org/packages/3b/aa/ce764724dcede88f9010963ca7d70d0a79655174599ea85074cb2c656d59/wasmtime-43.0.0-py3-none-android_26_x86_64.whl", hash = "sha256:f65b287290f06751b2c87da3cdb2381b045ac93bc3ee0e3b805c2a6dc5327bc6", size = 7775074, upload-time = "2026-03-31T19:26:04.741Z" },
{ url = "https://files.pythonhosted.org/packages/2a/ca/67db17c3f098894be798457ce261816fb67c0c1b80c1a53ed1dfa8ed4ff1/wasmtime-43.0.0-py3-none-any.whl", hash = "sha256:9441349d9346230420ed24d357d6f8330fe7251ac5938bb892147728bbe731d7", size = 6472597, upload-time = "2026-03-31T19:26:06.61Z" },
{ url = "https://files.pythonhosted.org/packages/bf/87/b9727ac8ecf02d2bd9af838fe6004c028034ce3f38215a22f8e94705b83d/wasmtime-43.0.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:0ff3815f63122d2f59e58c626aad3c4592f1cabc0b6bd7dcc1edc3890eb46783", size = 7564987, upload-time = "2026-03-31T19:26:08.492Z" },
{ url = "https://files.pythonhosted.org/packages/08/42/d9588fa6dad9a609e5acaa72d1d5b346b2913f87c2e95d0c7ddadf5e919b/wasmtime-43.0.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5a03c7aa03519df58fed5115ad8093d6deac46386115add715e725448e89ab25", size = 6615055, upload-time = "2026-03-31T19:26:10.506Z" },
{ url = "https://files.pythonhosted.org/packages/48/a9/25b27545ad916a169583dbea41a6a03c58fe04c1d05fa39797dc43bd50b9/wasmtime-43.0.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:341542e87caf1f2ef7ff648a78827fcef5751e3e9be2ee07a1fcf3a04413c213", size = 7819110, upload-time = "2026-03-31T19:26:12.335Z" },
{ url = "https://files.pythonhosted.org/packages/d8/9a/4d8760f827931b5b265b83e52316d40b8e0eb999bb8e2d457c2ae172d5cc/wasmtime-43.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:30b042fd4a05d0f8a320baed53fcb971aff8a3789ed6967f4521f87931ace717", size = 6910375, upload-time = "2026-03-31T19:26:14.207Z" },
{ url = "https://files.pythonhosted.org/packages/ce/19/81c748c089a693b102f9a6239f2558a0ffd55fc721fcdd139361aaede1a1/wasmtime-43.0.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:34ff18384ad62625cb1438fd0266f6c74b4a72ddcb8ba30c60a66be3632db44b", size = 6938286, upload-time = "2026-03-31T19:26:15.898Z" },
{ url = "https://files.pythonhosted.org/packages/0f/fa/c37e77c907567a8802696f9ab839b719ea811cf3d59ffc815cc95d894339/wasmtime-43.0.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:c7025d477d807df30dad07c9318ea747c6cfc99764c7cb2a8e44e75b8c43e3be", size = 7852033, upload-time = "2026-03-31T19:26:17.915Z" },
{ url = "https://files.pythonhosted.org/packages/69/67/57c7e361049554cdedd9253e732a6eace5c643488a0e3886ac3f471a4be7/wasmtime-43.0.0-py3-none-win_amd64.whl", hash = "sha256:7e6b0d0641d78012bdf7d3622ca4bc969462dcf1d0a6c147dc5d7aae2f5093a9", size = 6472603, upload-time = "2026-03-31T19:26:19.724Z" },
{ url = "https://files.pythonhosted.org/packages/ec/27/8ecf7dbbb16dc3ab32fcb205f4d798e77cab264118bc1ac52145a76e38fb/wasmtime-43.0.0-py3-none-win_arm64.whl", hash = "sha256:5ddb2ba4b354fc4f055c8ce9285e7bc4cb259c339e5834bb4d0739d644042b8e", size = 5455362, upload-time = "2026-03-31T19:26:21.746Z" },
]
[[package]]
name = "websocket-client"
version = "1.9.0"