@@ -909,55 +897,6 @@
-
-
-
- Accept Bitcoin onchain payments. Requires the
- SatsPay and Watchonly
- extensions to be installed and enabled.
-
-
val && loadOnchainWallets()"
- >
-
-
-
-
-
-
-
-
dict[str, Any]:
- try:
- config = await fetch_watchonly_config(wallet.inkey)
- network = config.get("network")
- if not network:
- raise HTTPException(
- status_code=HTTPStatus.BAD_REQUEST,
- detail="Watchonly extension returned an invalid network.",
- )
- wallets = await fetch_watchonly_wallets(wallet.inkey, network)
- except HTTPException:
- raise
- except Exception as exc:
- return {
- "available": False,
- "message": f"Watchonly extension is not reachable: {exc!s}",
- "network": None,
- "wallets": [],
- "mempool_endpoint": None,
- }
- return {
- "available": True,
- "message": None,
- "network": network,
- "wallets": wallets,
- "mempool_endpoint": config.get("mempool_endpoint"),
- }
-
-
def _is_fiat_currency(currency: str | None) -> bool:
return str(currency or "").lower() not in {"sat", "sats"}
@@ -294,13 +259,6 @@ async def api_get_settings_public(
return {"auto_approve": settings.auto_approve}
-@events_api_router.get("/onchain/status")
-async def api_onchain_status(
- wallet: WalletTypeInfo = Depends(require_admin_key),
-) -> dict[str, Any]:
- return await _get_watchonly_status(wallet.wallet)
-
-
@events_api_router.get("/{event_id}", response_model=PublicEvent)
async def api_get_event(event_id: str) -> Event:
"""Public event detail used by display.vue.
@@ -821,7 +779,7 @@ async def api_ticket_create(
refund_address = data.refund_address
nostr_identifier = data.nostr_identifier.strip() if data.nostr_identifier else None
payment_method = (data.payment_method or "lightning").lower()
- if payment_method not in {"lightning", "fiat", "onchain"}:
+ if payment_method not in {"lightning", "fiat"}:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="Unsupported payment method.",
@@ -931,7 +889,6 @@ async def api_ticket_create(
invoice_unit = selected_wave.currency
fiat_amount = price
fiat_provider = None
- onchain_amount_sat = None
if payment_method == "fiat":
if _is_fiat_currency(selected_wave.currency):
@@ -956,80 +913,6 @@ async def api_ticket_create(
status_code=HTTPStatus.BAD_REQUEST,
detail="No fiat payment provider configured for this event.",
)
- elif payment_method == "onchain":
- onchain_amount_sat = int(price)
- wallet_record = await get_wallet(event.wallet)
- if not wallet_record:
- raise HTTPException(
- status_code=HTTPStatus.NOT_FOUND,
- detail="Event wallet does not exist.",
- )
- if not event.extra.onchain_enabled:
- raise HTTPException(
- status_code=HTTPStatus.BAD_REQUEST,
- detail="Onchain payments are not enabled for this event.",
- )
- if not event.extra.onchain_wallet_id:
- raise HTTPException(
- status_code=HTTPStatus.BAD_REQUEST,
- detail="No onchain wallet configured for this event.",
- )
-
- ticket_id = urlsafe_short_hash()
- base_url = str(request.base_url).rstrip("/")
- # Use internal address for webhook — SatsPay calls it server-side and
- # cannot reach the public domain from within the container.
- internal_base = f"http://{settings.host}:{settings.port}"
- webhook_url = (
- f"{internal_base}/events/api/v1/tickets/{ticket_id}/satspay-webhook"
- )
- complete_url = f"{base_url}/events/ticket/{ticket_id}"
- try:
- charge = await create_satspay_charge(
- api_key=wallet_record.inkey,
- data={
- "amount": onchain_amount_sat,
- "description": f"Ticket for {event.name}",
- "name": name,
- "onchainwallet": event.extra.onchain_wallet_id,
- "zeroconf": event.extra.onchain_zeroconf,
- "fasttrack": event.extra.onchain_fasttrack,
- "webhook": webhook_url,
- "completelink": complete_url,
- "completelinktext": "View your ticket",
- "time": 1440,
- },
- )
- except Exception as exc:
- raise HTTPException(
- status_code=HTTPStatus.BAD_REQUEST,
- detail=f"Failed to create SatsPay charge: {exc}",
- ) from exc
-
- await create_ticket(
- payment_hash=ticket_id,
- wallet=event.wallet,
- event=event.id,
- name=name,
- email=email,
- extra={
- "applied_promo_code": promo_code,
- "ticket_wave_id": selected_wave.id,
- "ticket_wave_title": selected_wave.title,
- "refund_address": refund_address,
- "nostr_identifier": nostr_identifier,
- "ticket_base_url": base_url,
- "sats_paid": onchain_amount_sat,
- "onchain": True,
- "satspay_charge_id": charge["id"],
- },
- )
-
- return TicketPaymentRequest(
- payment_hash=ticket_id,
- onchain_amount_sat=onchain_amount_sat,
- satspay_charge_url=f"/satspay/{charge['id']}",
- )
else:
invoice_unit = "sat"
@@ -1194,73 +1077,6 @@ async def api_ticket_delete(
await delete_ticket(ticket_id)
-@tickets_api_router.post("/{ticket_id}/satspay-webhook")
-async def api_ticket_satspay_webhook(ticket_id: str) -> None:
- ticket = await get_ticket(ticket_id)
- if not ticket:
- logger.warning(f"SatsPay webhook: ticket {ticket_id} does not exist.")
- raise HTTPException(
- status_code=HTTPStatus.NOT_FOUND, detail="Ticket does not exist."
- )
- if ticket.paid:
- logger.warning(f"SatsPay webhook: ticket {ticket_id} already paid.")
- return
- if not ticket.extra.satspay_charge_id:
- raise HTTPException(
- status_code=HTTPStatus.BAD_REQUEST, detail="Not a SatsPay ticket."
- )
- wallet = await get_wallet(ticket.wallet)
- if not wallet:
- raise HTTPException(
- status_code=HTTPStatus.NOT_FOUND, detail="Ticket wallet does not exist."
- )
- try:
- charge = await get_satspay_charge(wallet.inkey, ticket.extra.satspay_charge_id)
- except Exception as exc:
- raise HTTPException(
- status_code=HTTPStatus.BAD_REQUEST, detail=f"Could not verify charge: {exc}"
- ) from exc
- if not charge.get("paid"):
- logger.warning(
- f"SatsPay webhook for ticket {ticket_id}: charge"
- f" {ticket.extra.satspay_charge_id} not paid."
- )
- return
-
- ticket = await set_ticket_paid(ticket)
- send_ticket_notification_in_background(ticket)
- for queue in payment_listeners.get(ticket_id, []):
- queue.put_nowait(ticket)
-
-
-@tickets_api_router.put("/{payment_hash}/onchain-confirm")
-async def api_ticket_onchain_confirm(
- payment_hash: str,
- wallet: WalletTypeInfo = Depends(require_admin_key),
-) -> Ticket:
- ticket = await get_ticket(payment_hash)
- if not ticket:
- raise HTTPException(
- status_code=HTTPStatus.NOT_FOUND, detail="Ticket does not exist."
- )
- if ticket.wallet != wallet.wallet.id:
- raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail="Not your ticket.")
- if ticket.paid:
- raise HTTPException(
- status_code=HTTPStatus.BAD_REQUEST, detail="Ticket already paid."
- )
- if not ticket.extra.onchain:
- raise HTTPException(
- status_code=HTTPStatus.BAD_REQUEST,
- detail="Ticket is not an onchain payment.",
- )
- ticket = await set_ticket_paid(ticket)
- send_ticket_notification_in_background(ticket)
- for queue in payment_listeners.get(payment_hash, []):
- queue.put_nowait(ticket)
- return ticket
-
-
@tickets_api_router.post("/{ticket_id}/resend-email", response_model=TicketResendResult)
async def api_ticket_resend_email(
ticket_id: str,