1
0
This repository has been archived on 2026-03-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Timmy-time-dashboard/src/timmy_serve/payment_handler.py
Alexander Payne d8d976aa60 feat: complete Event Log, Ledger, Memory, Cascade Router, Upgrade Queue, Activity Feed
This commit implements six major features:

1. Event Log System (src/swarm/event_log.py)
   - SQLite-based audit trail for all swarm events
   - Task lifecycle tracking (created, assigned, completed, failed)
   - Agent lifecycle tracking (joined, left, status changes)
   - Integrated with coordinator for automatic logging
   - Dashboard page at /swarm/events

2. Lightning Ledger (src/lightning/ledger.py)
   - Transaction tracking for Lightning Network payments
   - Balance calculations (incoming, outgoing, net, available)
   - Integrated with payment_handler for automatic logging
   - Dashboard page at /lightning/ledger

3. Semantic Memory / Vector Store (src/memory/vector_store.py)
   - Embedding-based similarity search for Echo agent
   - Fallback to keyword matching if sentence-transformers unavailable
   - Personal facts storage and retrieval
   - Dashboard page at /memory

4. Cascade Router Integration (src/timmy/cascade_adapter.py)
   - Automatic LLM failover between providers (Ollama → AirLLM → API)
   - Circuit breaker pattern for failing providers
   - Metrics tracking per provider (latency, error rates)
   - Dashboard status page at /router/status

5. Self-Upgrade Approval Queue (src/upgrades/)
   - State machine for self-modifications: proposed → approved/rejected → applied/failed
   - Human approval required before applying changes
   - Git integration for branch management
   - Dashboard queue at /self-modify/queue

6. Real-Time Activity Feed (src/events/broadcaster.py)
   - WebSocket-based live activity streaming
   - Bridges event_log to dashboard clients
   - Activity panel on /swarm/live

Tests:
- 101 unit tests passing
- 4 new E2E test files for Selenium testing
- Run with: SELENIUM_UI=1 pytest tests/functional/ -v --headed

Documentation:
- 6 ADRs (017-022) documenting architecture decisions
- Implementation summary in docs/IMPLEMENTATION_SUMMARY.md
- Architecture diagram in docs/architecture-v2.md
2026-02-26 08:01:01 -05:00

154 lines
4.7 KiB
Python

"""Lightning invoice creation and payment verification.
This module is now a thin wrapper around the lightning backend interface.
The actual backend (mock or LND) is selected via LIGHTNING_BACKEND env var.
For backward compatibility, the PaymentHandler class and payment_handler
singleton are preserved, but they delegate to the lightning backend.
All transactions are logged to the ledger for audit and accounting.
"""
import logging
from typing import Optional
# Import from the new lightning module
from lightning import get_backend, Invoice
from lightning.base import LightningBackend
from lightning.ledger import (
create_invoice_entry,
mark_settled,
get_balance,
list_transactions,
)
logger = logging.getLogger(__name__)
class PaymentHandler:
"""Creates and verifies Lightning invoices.
This class is a wrapper around the LightningBackend interface.
It exists for backward compatibility — new code should use
the lightning module directly.
Usage:
from timmy_serve.payment_handler import payment_handler
invoice = payment_handler.create_invoice(100, "API access")
if payment_handler.check_payment(invoice.payment_hash):
print("Paid!")
"""
def __init__(self, backend: Optional[LightningBackend] = None) -> None:
"""Initialize the payment handler.
Args:
backend: Lightning backend to use. If None, uses get_backend()
which reads LIGHTNING_BACKEND env var.
"""
self._backend = backend or get_backend()
logger.info("PaymentHandler initialized — backend: %s", self._backend.name)
def create_invoice(
self,
amount_sats: int,
memo: str = "",
source: str = "payment_handler",
task_id: Optional[str] = None,
agent_id: Optional[str] = None,
) -> Invoice:
"""Create a new Lightning invoice.
Args:
amount_sats: Invoice amount in satoshis
memo: Payment description
source: Component creating the invoice
task_id: Associated task ID
agent_id: Associated agent ID
"""
invoice = self._backend.create_invoice(amount_sats, memo)
logger.info(
"Invoice created: %d sats — %s (hash: %s…)",
amount_sats, memo, invoice.payment_hash[:12],
)
# Log to ledger
create_invoice_entry(
payment_hash=invoice.payment_hash,
amount_sats=amount_sats,
memo=memo,
invoice=invoice.bolt11 if hasattr(invoice, 'bolt11') else None,
source=source,
task_id=task_id,
agent_id=agent_id,
)
return invoice
def check_payment(self, payment_hash: str) -> bool:
"""Check whether an invoice has been paid.
If paid, updates the ledger entry.
"""
is_paid = self._backend.check_payment(payment_hash)
if is_paid:
# Update ledger entry
mark_settled(payment_hash)
return is_paid
def settle_invoice(self, payment_hash: str, preimage: str) -> bool:
"""Manually settle an invoice with a preimage (for testing).
Also updates the ledger entry.
"""
result = self._backend.settle_invoice(payment_hash, preimage)
if result:
mark_settled(payment_hash, preimage=preimage)
return result
def get_invoice(self, payment_hash: str) -> Optional[Invoice]:
"""Get invoice details by payment hash."""
return self._backend.get_invoice(payment_hash)
def list_invoices(self, settled_only: bool = False) -> list[Invoice]:
"""List recent invoices."""
return self._backend.list_invoices(settled_only=settled_only)
def health_check(self) -> dict:
"""Check backend health."""
return self._backend.health_check()
@property
def backend_name(self) -> str:
"""Get the name of the current backend."""
return self._backend.name
def get_balance(self) -> dict:
"""Get current balance summary from ledger.
Returns:
Dict with incoming, outgoing, pending, and available balances
"""
return get_balance()
def list_transactions(self, limit: int = 100, **filters) -> list:
"""List transactions from ledger.
Args:
limit: Maximum number of transactions
**filters: Optional filters (tx_type, status, task_id, agent_id)
Returns:
List of LedgerEntry objects
"""
return list_transactions(limit=limit, **filters)
# Module-level singleton
payment_handler = PaymentHandler()