diff --git a/lnbits/extensions/subdomains/README.md b/lnbits/extensions/subdomains/README.md
deleted file mode 100644
index 3797c761..00000000
--- a/lnbits/extensions/subdomains/README.md
+++ /dev/null
@@ -1,54 +0,0 @@
-
Subdomains Extension
-
-So the goal of the extension is to allow the owner of a domain to sell subdomains to anyone who is willing to pay some money for it.
-
-[](https://youtu.be/O1X0fy3uNpw 'video tutorial subdomains')
-
-## Requirements
-
-- Free Cloudflare account
-- Cloudflare as a DNS server provider
-- Cloudflare TOKEN and Cloudflare zone-ID where the domain is parked
-
-## Usage
-
-1. Register at Cloudflare and setup your domain with them. (Just follow instructions they provide...)
-2. Change DNS server at your domain registrar to point to Cloudflare's
-3. Get Cloudflare zone-ID for your domain
-
-4. Get Cloudflare API TOKEN
-
-
-5. Open the LNbits subdomains extension and register your domain
-6. Click on the button in the table to open the public form that was generated for your domain
-
- - Extension also supports webhooks so you can get notified when someone buys a new subdomain\
-
-
-## API Endpoints
-
-- **Domains**
- - GET /api/v1/domains
- - POST /api/v1/domains
- - PUT /api/v1/domains/
- - DELETE /api/v1/domains/
-- **Subdomains**
- - GET /api/v1/subdomains
- - POST /api/v1/subdomains/
- - GET /api/v1/subdomains/
- - DELETE /api/v1/subdomains/
-
-### Cloudflare
-
-- Cloudflare offers programmatic subdomain registration... (create new A record)
-- you can keep your existing domain's registrar, you just have to transfer dns records to the cloudflare (free service)
-- more information:
- - https://api.cloudflare.com/#getting-started-requests
- - API endpoints needed for our project:
- - https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records
- - https://api.cloudflare.com/#dns-records-for-a-zone-create-dns-record
- - https://api.cloudflare.com/#dns-records-for-a-zone-delete-dns-record
- - https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record
-- api can be used by providing authorization token OR authorization key
- - check API Tokens and API Keys : https://api.cloudflare.com/#getting-started-requests
-- Cloudflare API postman collection: https://support.cloudflare.com/hc/en-us/articles/115002323852-Using-Cloudflare-API-with-Postman-Collections
diff --git a/lnbits/extensions/subdomains/__init__.py b/lnbits/extensions/subdomains/__init__.py
deleted file mode 100644
index 7434555d..00000000
--- a/lnbits/extensions/subdomains/__init__.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import asyncio
-
-from fastapi import APIRouter
-from fastapi.staticfiles import StaticFiles
-
-from lnbits.db import Database
-from lnbits.helpers import template_renderer
-from lnbits.tasks import catch_everything_and_restart
-
-db = Database("ext_subdomains")
-
-subdomains_ext: APIRouter = APIRouter(prefix="/subdomains", tags=["subdomains"])
-
-subdomains_static_files = [
- {
- "path": "/subdomains/static",
- "app": StaticFiles(directory="lnbits/extensions/subdomains/static"),
- "name": "subdomains_static",
- }
-]
-
-
-def subdomains_renderer():
- return template_renderer(["lnbits/extensions/subdomains/templates"])
-
-
-from .tasks import wait_for_paid_invoices
-from .views import * # noqa: F401,F403
-from .views_api import * # noqa: F401,F403
-
-
-def subdomains_start():
- loop = asyncio.get_event_loop()
- loop.create_task(catch_everything_and_restart(wait_for_paid_invoices))
diff --git a/lnbits/extensions/subdomains/cloudflare.py b/lnbits/extensions/subdomains/cloudflare.py
deleted file mode 100644
index 3d3b9bde..00000000
--- a/lnbits/extensions/subdomains/cloudflare.py
+++ /dev/null
@@ -1,49 +0,0 @@
-import httpx
-
-from .models import Domains
-
-
-async def cloudflare_create_subdomain(
- domain: Domains, subdomain: str, record_type: str, ip: str
-):
- # Call to cloudflare sort of a dry-run - if success delete the domain and wait for payment
- ### SEND REQUEST TO CLOUDFLARE
- url = (
- "https://api.cloudflare.com/client/v4/zones/"
- + domain.cf_zone_id
- + "/dns_records"
- )
- header = {
- "Authorization": "Bearer " + domain.cf_token,
- "Content-Type": "application/json",
- }
- aRecord = subdomain + "." + domain.domain
- async with httpx.AsyncClient() as client:
- r = await client.post(
- url,
- headers=header,
- json={
- "type": record_type,
- "name": aRecord,
- "content": ip,
- "ttl": 0,
- "proxied": False,
- },
- timeout=40,
- )
- r.raise_for_status()
- return r.json()
-
-
-async def cloudflare_deletesubdomain(domain: Domains, domain_id: str):
- url = (
- "https://api.cloudflare.com/client/v4/zones/"
- + domain.cf_zone_id
- + "/dns_records"
- )
- header = {
- "Authorization": "Bearer " + domain.cf_token,
- "Content-Type": "application/json",
- }
- async with httpx.AsyncClient() as client:
- await client.delete(url + "/" + domain_id, headers=header, timeout=40)
diff --git a/lnbits/extensions/subdomains/config.json b/lnbits/extensions/subdomains/config.json
deleted file mode 100644
index cec2ec64..00000000
--- a/lnbits/extensions/subdomains/config.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "Subdomains",
- "short_description": "Sell subdomains of your domain",
- "tile": "/subdomains/static/image/subdomains.png",
- "contributors": ["grmkris"]
-}
diff --git a/lnbits/extensions/subdomains/crud.py b/lnbits/extensions/subdomains/crud.py
deleted file mode 100644
index b3476ed9..00000000
--- a/lnbits/extensions/subdomains/crud.py
+++ /dev/null
@@ -1,161 +0,0 @@
-from typing import List, Optional, Union
-
-from lnbits.helpers import urlsafe_short_hash
-
-from . import db
-from .models import CreateDomain, CreateSubdomain, Domains, Subdomains
-
-
-async def create_subdomain(payment_hash, wallet, data: CreateSubdomain) -> Subdomains:
- await db.execute(
- """
- INSERT INTO subdomains.subdomain (id, domain, email, subdomain, ip, wallet, sats, duration, paid, record_type)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (
- payment_hash,
- data.domain,
- data.email,
- data.subdomain,
- data.ip,
- wallet,
- data.sats,
- data.duration,
- False,
- data.record_type,
- ),
- )
-
- new_subdomain = await get_subdomain(payment_hash)
- assert new_subdomain, "Newly created subdomain couldn't be retrieved"
- return new_subdomain
-
-
-async def set_subdomain_paid(payment_hash: str) -> Subdomains:
- row = await db.fetchone(
- "SELECT s.*, d.domain as domain_name FROM subdomains.subdomain s INNER JOIN subdomains.domain d ON (s.domain = d.id) WHERE s.id = ?",
- (payment_hash,),
- )
- if row[8] is False:
- await db.execute(
- """
- UPDATE subdomains.subdomain
- SET paid = true
- WHERE id = ?
- """,
- (payment_hash,),
- )
-
- domaindata = await get_domain(row[1])
- assert domaindata, "Couldn't get domain from paid subdomain"
-
- amount = domaindata.amountmade + row[8]
- await db.execute(
- """
- UPDATE subdomains.domain
- SET amountmade = ?
- WHERE id = ?
- """,
- (amount, row[1]),
- )
-
- new_subdomain = await get_subdomain(payment_hash)
- assert new_subdomain, "Newly paid subdomain couldn't be retrieved"
- return new_subdomain
-
-
-async def get_subdomain(subdomain_id: str) -> Optional[Subdomains]:
- row = await db.fetchone(
- "SELECT s.*, d.domain as domain_name FROM subdomains.subdomain s INNER JOIN subdomains.domain d ON (s.domain = d.id) WHERE s.id = ?",
- (subdomain_id,),
- )
- return Subdomains(**row) if row else None
-
-
-async def get_subdomainBySubdomain(subdomain: str) -> Optional[Subdomains]:
- row = await db.fetchone(
- "SELECT s.*, d.domain as domain_name FROM subdomains.subdomain s INNER JOIN subdomains.domain d ON (s.domain = d.id) WHERE s.subdomain = ?",
- (subdomain,),
- )
- return Subdomains(**row) if row else None
-
-
-async def get_subdomains(wallet_ids: Union[str, List[str]]) -> List[Subdomains]:
- if isinstance(wallet_ids, str):
- wallet_ids = [wallet_ids]
-
- q = ",".join(["?"] * len(wallet_ids))
- rows = await db.fetchall(
- f"SELECT s.*, d.domain as domain_name FROM subdomains.subdomain s INNER JOIN subdomains.domain d ON (s.domain = d.id) WHERE s.wallet IN ({q})",
- (*wallet_ids,),
- )
-
- return [Subdomains(**row) for row in rows]
-
-
-async def delete_subdomain(subdomain_id: str) -> None:
- await db.execute("DELETE FROM subdomains.subdomain WHERE id = ?", (subdomain_id,))
-
-
-# Domains
-
-
-async def create_domain(data: CreateDomain) -> Domains:
- domain_id = urlsafe_short_hash()
- await db.execute(
- """
- INSERT INTO subdomains.domain (id, wallet, domain, webhook, cf_token, cf_zone_id, description, cost, amountmade, allowed_record_types)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (
- domain_id,
- data.wallet,
- data.domain,
- data.webhook,
- data.cf_token,
- data.cf_zone_id,
- data.description,
- data.cost,
- 0,
- data.allowed_record_types,
- ),
- )
-
- new_domain = await get_domain(domain_id)
- assert new_domain, "Newly created domain couldn't be retrieved"
- return new_domain
-
-
-async def update_domain(domain_id: str, **kwargs) -> Domains:
- q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
- await db.execute(
- f"UPDATE subdomains.domain SET {q} WHERE id = ?", (*kwargs.values(), domain_id)
- )
- row = await db.fetchone(
- "SELECT * FROM subdomains.domain WHERE id = ?", (domain_id,)
- )
- assert row, "Newly updated domain couldn't be retrieved"
- return Domains(**row)
-
-
-async def get_domain(domain_id: str) -> Optional[Domains]:
- row = await db.fetchone(
- "SELECT * FROM subdomains.domain WHERE id = ?", (domain_id,)
- )
- return Domains(**row) if row else None
-
-
-async def get_domains(wallet_ids: Union[str, List[str]]) -> List[Domains]:
- if isinstance(wallet_ids, str):
- wallet_ids = [wallet_ids]
-
- q = ",".join(["?"] * len(wallet_ids))
- rows = await db.fetchall(
- f"SELECT * FROM subdomains.domain WHERE wallet IN ({q})", (*wallet_ids,)
- )
-
- return [Domains(**row) for row in rows]
-
-
-async def delete_domain(domain_id: str) -> None:
- await db.execute("DELETE FROM subdomains.domain WHERE id = ?", (domain_id,))
diff --git a/lnbits/extensions/subdomains/migrations.py b/lnbits/extensions/subdomains/migrations.py
deleted file mode 100644
index 292d1f18..00000000
--- a/lnbits/extensions/subdomains/migrations.py
+++ /dev/null
@@ -1,41 +0,0 @@
-async def m001_initial(db):
-
- await db.execute(
- """
- CREATE TABLE subdomains.domain (
- id TEXT PRIMARY KEY,
- wallet TEXT NOT NULL,
- domain TEXT NOT NULL,
- webhook TEXT,
- cf_token TEXT NOT NULL,
- cf_zone_id TEXT NOT NULL,
- description TEXT NOT NULL,
- cost INTEGER NOT NULL,
- amountmade INTEGER NOT NULL,
- allowed_record_types TEXT NOT NULL,
- time TIMESTAMP NOT NULL DEFAULT """
- + db.timestamp_now
- + """
- );
- """
- )
-
- await db.execute(
- """
- CREATE TABLE subdomains.subdomain (
- id TEXT PRIMARY KEY,
- domain TEXT NOT NULL,
- email TEXT NOT NULL,
- subdomain TEXT NOT NULL,
- ip TEXT NOT NULL,
- wallet TEXT NOT NULL,
- sats INTEGER NOT NULL,
- duration INTEGER NOT NULL,
- paid BOOLEAN NOT NULL,
- record_type TEXT NOT NULL,
- time TIMESTAMP NOT NULL DEFAULT """
- + db.timestamp_now
- + """
- );
- """
- )
diff --git a/lnbits/extensions/subdomains/models.py b/lnbits/extensions/subdomains/models.py
deleted file mode 100644
index 552c37c7..00000000
--- a/lnbits/extensions/subdomains/models.py
+++ /dev/null
@@ -1,52 +0,0 @@
-from fastapi import Query
-from pydantic import BaseModel
-
-
-class CreateDomain(BaseModel):
- wallet: str = Query(...)
- domain: str = Query(...)
- cf_token: str = Query(...)
- cf_zone_id: str = Query(...)
- webhook: str = Query("")
- description: str = Query(..., min_length=0)
- cost: int = Query(..., ge=0)
- allowed_record_types: str = Query(...)
-
-
-class CreateSubdomain(BaseModel):
- domain: str = Query(...)
- subdomain: str = Query(...)
- email: str = Query(...)
- ip: str = Query(...)
- sats: int = Query(..., ge=0)
- duration: int = Query(...)
- record_type: str = Query(...)
-
-
-class Domains(BaseModel):
- id: str
- wallet: str
- domain: str
- cf_token: str
- cf_zone_id: str
- webhook: str
- description: str
- cost: int
- amountmade: int
- time: int
- allowed_record_types: str
-
-
-class Subdomains(BaseModel):
- id: str
- wallet: str
- domain: str
- domain_name: str
- subdomain: str
- email: str
- ip: str
- sats: int
- duration: int
- paid: bool
- time: int
- record_type: str
diff --git a/lnbits/extensions/subdomains/static/image/subdomains.png b/lnbits/extensions/subdomains/static/image/subdomains.png
deleted file mode 100644
index c552cb7b..00000000
Binary files a/lnbits/extensions/subdomains/static/image/subdomains.png and /dev/null differ
diff --git a/lnbits/extensions/subdomains/tasks.py b/lnbits/extensions/subdomains/tasks.py
deleted file mode 100644
index 42b7885a..00000000
--- a/lnbits/extensions/subdomains/tasks.py
+++ /dev/null
@@ -1,65 +0,0 @@
-import asyncio
-
-import httpx
-from loguru import logger
-
-from lnbits.core.models import Payment
-from lnbits.helpers import get_current_extension_name
-from lnbits.tasks import register_invoice_listener
-
-from .cloudflare import cloudflare_create_subdomain
-from .crud import get_domain, set_subdomain_paid
-
-
-async def wait_for_paid_invoices():
- invoice_queue = asyncio.Queue()
- register_invoice_listener(invoice_queue, get_current_extension_name())
-
- while True:
- payment = await invoice_queue.get()
- await on_invoice_paid(payment)
-
-
-async def on_invoice_paid(payment: Payment) -> None:
- if payment.extra.get("tag") != "lnsubdomain":
- # not an lnsubdomain invoice
- return
-
- await payment.set_pending(False)
- subdomain = await set_subdomain_paid(payment_hash=payment.payment_hash)
- domain = await get_domain(subdomain.domain)
-
- ### Create subdomain
- try:
- cf_response = await cloudflare_create_subdomain(
- domain=domain, # type: ignore
- subdomain=subdomain.subdomain,
- record_type=subdomain.record_type,
- ip=subdomain.ip,
- )
- except Exception as exc:
- logger.error(exc)
- logger.error("could not create subdomain on cloudflare")
- return
-
- ### Use webhook to notify about cloudflare registration
- if domain and domain.webhook:
- async with httpx.AsyncClient() as client:
- try:
- r = await client.post(
- domain.webhook,
- json={
- "domain": subdomain.domain_name,
- "subdomain": subdomain.subdomain,
- "record_type": subdomain.record_type,
- "email": subdomain.email,
- "ip": subdomain.ip,
- "cost:": str(subdomain.sats) + " sats",
- "duration": str(subdomain.duration) + " days",
- "cf_response": cf_response,
- },
- timeout=40,
- )
- assert r
- except AssertionError:
- pass
diff --git a/lnbits/extensions/subdomains/templates/subdomains/_api_docs.html b/lnbits/extensions/subdomains/templates/subdomains/_api_docs.html
deleted file mode 100644
index 035d67a6..00000000
--- a/lnbits/extensions/subdomains/templates/subdomains/_api_docs.html
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
- lnSubdomains: Get paid sats to sell your subdomains
-
-
- Charge people for using your subdomain name...
-
- More details
-
-
- Created by,
- Kris
-
-
-
-
-
diff --git a/lnbits/extensions/subdomains/templates/subdomains/display.html b/lnbits/extensions/subdomains/templates/subdomains/display.html
deleted file mode 100644
index f11c9ddc..00000000
--- a/lnbits/extensions/subdomains/templates/subdomains/display.html
+++ /dev/null
@@ -1,221 +0,0 @@
-{% extends "public.html" %} {% block page %}
-
-
-
-
- {{ domain_domain }}
-
- {{ domain_desc }}
-
-
-
-
-
-
-
-
-
-
-
- Cost per day: {{ domain_cost }} sats
- {% raw %} Total cost: {{amountSats}} sats {% endraw %}
-
-
- Submit
- Cancel
-
-
-
-
-
-
-
-
-
-
-
-
- Copy invoice
- Close
-
-
-
-
-
-{% endblock %} {% block scripts %}
-
-{% endblock %}
diff --git a/lnbits/extensions/subdomains/templates/subdomains/index.html b/lnbits/extensions/subdomains/templates/subdomains/index.html
deleted file mode 100644
index a39773e7..00000000
--- a/lnbits/extensions/subdomains/templates/subdomains/index.html
+++ /dev/null
@@ -1,549 +0,0 @@
-{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
-%} {% block page %}
-
-
-
-
-
- New Domain
-
-
-
-
-
-
-
-
Domains
-
-
- Export to CSV
-
-
-
- {% raw %}
-
-
-
-
- {{ col.label }}
-
-
-
-
-
-
-
-
-
-
- {{ col.value }}
-
-
-
-
-
-
-
-
-
-
- {% endraw %}
-
-
-
-
-
-
-
-
-
Subdomains
-
-
- Export to CSV
-
-
-
- {% raw %}
-
-
-
-
- {{ col.label }}
-
-
-
-
-
-
-
-
-
-
- {{ col.value }}
-
-
-
-
-
-
-
- {% endraw %}
-
-
-
-
-
-
-
-
- {{SITE_TITLE}} Subdomain extension
-
-
-
-
- {% include "subdomains/_api_docs.html" %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Update Form
- Create Domain
- Cancel
-
-
-
-
-
-
-{% endblock %} {% block scripts %} {{ window_vars(user) }}
-
-{% endblock %}
diff --git a/lnbits/extensions/subdomains/util.py b/lnbits/extensions/subdomains/util.py
deleted file mode 100644
index 9265e870..00000000
--- a/lnbits/extensions/subdomains/util.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import re
-import socket
-
-
-# Function to validate domain name.
-def isValidDomain(str):
- # Regex to check valid
- # domain name.
- regex = "^((?!-)[A-Za-z0-9-]{1,63}(?