feat(v2): satmachineclient maintenance pass — v2 admin schema (P7)
Updates the LP-facing client extension to work against the v2 admin schema
(per-machine dca_clients, leg_type-discriminated dca_payments, settlement
audit trail) and strips the dead v1 code paths.
Maintenance-mode framing: the richer LP UI is migrating to ~/dev/webapp.
This extension now provides a minimal stable read-mostly surface so
existing LP installs don't break against the v2 admin schema.
models.py — rewrite:
+ PerMachinePosition: LP's position at a single machine
~ ClientDashboardSummary: now aggregates across all the LP's machines
and exposes per-machine breakdown in `positions` field
~ ClientTransaction: gains machine_id + machine_npub + settlement_id;
drops transaction_type / lamassu_transaction_id (v1 fields)
~ leg_type discriminator on ClientTransaction so the LP can tell DCA,
operator-initiated balance-settle, and auto-forward legs apart
+ UpdateClientAutoforward: LPs control their own autoforward setting
- ClientDashboardSummaryAPI, ClientTransactionAPI: deleted (GTQ-only
parallel "API" models that duplicated the internal ones)
- ClientPreferences, ClientRegistrationData, UpdateClientSettings:
deleted (registration + settings are operator-controlled in v2)
crud.py — rewrite:
+ _fetch_user_clients: all dca_clients rows for the LP, joined with
dca_machines for display metadata
+ _position_for_client: per-machine aggregation helper
+ get_client_dashboard_summary: aggregates positions + sums sats/fiat
+ computes cost basis on fiat-spent (not gross deposits)
+ get_client_transactions: filters to LP-visible leg_types
(dca / settlement / autoforward); optional machine_id filter
+ update_lp_autoforward: LP self-manages autoforward across all their
machine positions
- get_client_analytics (300+ lines of date-parsing pretzels): deleted;
webapp will own analytics
- register_dca_client: deleted (admin owns registration in v2)
- update_client_dca_settings: deleted (admin owns DCA mode/limits)
- Lamassu-era status='confirmed' (now 'completed'), transaction_type
column refs, lamassu_transaction_id column refs: all gone
views_api.py — rewrite to 3 endpoints:
GET /api/v1/dca-client/positions (aggregated dashboard)
GET /api/v1/dca-client/transactions (filterable history)
PUT /api/v1/dca-client/autoforward (LP self-manages forwarding)
All require_admin_key on the LP's wallet. Old registration / settings
/ analytics endpoints removed.
Files deleted:
tasks.py — empty stub ("No background tasks needed")
transaction_processor.py — empty stub ("No transaction processing")
README.md gains a status banner pointing LP audience at webapp.
.gitignore gains `data/` + sqlite db files + __pycache__ to prevent
LNbits runtime artifacts (auth keys, dev DBs) from being committed.
4 routes registered. Zero ruff errors across the extension.
Refs: aiolabs/satmachineadmin#9 — completes P7
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
98f82beb28
commit
ade4e67541
8 changed files with 289 additions and 738 deletions
119
models.py
119
models.py
|
|
@ -1,4 +1,12 @@
|
|||
# Description: Pydantic data models for client extension API responses
|
||||
# Satoshi Machine Client v2 — Pydantic models.
|
||||
#
|
||||
# LP-facing read view over the admin extension's v2 schema. An LP can hold
|
||||
# DCA positions across multiple machines (and across multiple operators on
|
||||
# the same LNbits instance); summary endpoints aggregate, with an optional
|
||||
# per-machine breakdown for filtering.
|
||||
#
|
||||
# NOTE: this extension is in maintenance mode. The richer LP UI is moving
|
||||
# to ~/dev/webapp; this surface stays minimal and read-mostly.
|
||||
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
|
|
@ -6,95 +14,60 @@ from typing import List, Optional
|
|||
from pydantic import BaseModel
|
||||
|
||||
|
||||
# API Models for Client Dashboard (Frontend communication in GTQ)
|
||||
class ClientDashboardSummaryAPI(BaseModel):
|
||||
"""API model - client dashboard summary in GTQ"""
|
||||
user_id: str
|
||||
total_sats_accumulated: int
|
||||
total_fiat_invested_gtq: float # Confirmed deposits in GTQ
|
||||
pending_fiat_deposits_gtq: float # Pending deposits in GTQ
|
||||
current_sats_fiat_value_gtq: float # Current fiat value of total sats in GTQ
|
||||
average_cost_basis: float # Average sats per GTQ
|
||||
current_fiat_balance_gtq: float # Available balance for DCA in GTQ
|
||||
total_transactions: int
|
||||
dca_mode: str # 'flow' or 'fixed'
|
||||
dca_status: str # 'active' or 'inactive'
|
||||
last_transaction_date: Optional[datetime]
|
||||
currency: str = "GTQ"
|
||||
class PerMachinePosition(BaseModel):
|
||||
"""LP's position at a single machine."""
|
||||
|
||||
|
||||
class ClientTransactionAPI(BaseModel):
|
||||
"""API model - client transaction in GTQ"""
|
||||
id: str
|
||||
amount_sats: int
|
||||
amount_fiat_gtq: float # Amount in GTQ
|
||||
exchange_rate: float
|
||||
transaction_type: str # 'flow', 'fixed', 'manual'
|
||||
machine_id: str
|
||||
machine_npub: str
|
||||
machine_name: Optional[str]
|
||||
machine_location: Optional[str]
|
||||
currency: str
|
||||
dca_mode: str
|
||||
status: str
|
||||
created_at: datetime
|
||||
transaction_time: Optional[datetime] = None # Original ATM transaction time
|
||||
lamassu_transaction_id: Optional[str] = None
|
||||
total_sats_accumulated: int
|
||||
total_fiat_invested: float
|
||||
current_fiat_balance: float
|
||||
total_transactions: int
|
||||
last_transaction_date: Optional[datetime]
|
||||
|
||||
|
||||
# Internal Models for Client Dashboard (Database storage in GTQ)
|
||||
class ClientDashboardSummary(BaseModel):
|
||||
"""Internal model - client dashboard summary stored in GTQ"""
|
||||
"""LP's aggregated dashboard across all machines they're registered at."""
|
||||
|
||||
user_id: str
|
||||
total_sats_accumulated: int
|
||||
total_fiat_invested: float # Confirmed deposits in GTQ
|
||||
pending_fiat_deposits: float # Pending deposits awaiting confirmation in GTQ
|
||||
current_sats_fiat_value: float # Current fiat value of total sats in GTQ
|
||||
average_cost_basis: float # Average sats per GTQ
|
||||
current_fiat_balance: float # Available balance for DCA in GTQ
|
||||
total_fiat_invested: float # confirmed deposits across all machines
|
||||
current_fiat_balance: float # confirmed deposits - DCA - settlement legs
|
||||
pending_fiat_deposits: float # deposits in 'pending' status
|
||||
average_cost_basis: float # total_sats / total_fiat_invested-spent
|
||||
current_sats_fiat_value: float # current rate × total_sats (best-effort)
|
||||
total_transactions: int
|
||||
dca_mode: str # 'flow' or 'fixed'
|
||||
dca_status: str # 'active' or 'inactive'
|
||||
total_machines: int # how many machines this LP is on
|
||||
last_transaction_date: Optional[datetime]
|
||||
currency: str = "GTQ"
|
||||
currency: str # display currency; if multi-currency, "MIX"
|
||||
positions: List[PerMachinePosition] = []
|
||||
|
||||
|
||||
class ClientTransaction(BaseModel):
|
||||
"""Internal model - client transaction stored in GTQ"""
|
||||
"""A single distribution leg landing in the LP's wallet."""
|
||||
|
||||
id: str
|
||||
machine_id: str
|
||||
machine_npub: str
|
||||
settlement_id: Optional[str]
|
||||
leg_type: str # 'dca' | 'settlement' | 'autoforward' (LP-visible)
|
||||
amount_sats: int
|
||||
amount_fiat: float # Amount in GTQ (e.g., 150.75)
|
||||
exchange_rate: float
|
||||
transaction_type: str # 'flow', 'fixed', 'manual'
|
||||
amount_fiat: Optional[float]
|
||||
exchange_rate: Optional[float]
|
||||
status: str
|
||||
created_at: datetime
|
||||
transaction_time: Optional[datetime] = None # Original ATM transaction time
|
||||
lamassu_transaction_id: Optional[str] = None
|
||||
transaction_time: datetime
|
||||
|
||||
|
||||
class ClientAnalytics(BaseModel):
|
||||
"""Performance analytics for client dashboard"""
|
||||
user_id: str
|
||||
cost_basis_history: List[dict] # Historical cost basis data points
|
||||
accumulation_timeline: List[dict] # Sats accumulated over time
|
||||
transaction_frequency: dict # Transaction frequency metrics
|
||||
performance_vs_market: Optional[dict] = None # Market comparison data
|
||||
|
||||
|
||||
class ClientPreferences(BaseModel):
|
||||
"""Client dashboard preferences and settings"""
|
||||
user_id: str
|
||||
preferred_currency: str = "GTQ"
|
||||
dashboard_theme: str = "light"
|
||||
chart_time_range: str = "30d" # Default chart time range
|
||||
notification_preferences: dict = {}
|
||||
|
||||
|
||||
class UpdateClientSettings(BaseModel):
|
||||
"""Settings that client can modify"""
|
||||
dca_mode: Optional[str] = None # 'flow' or 'fixed'
|
||||
fixed_mode_daily_limit: Optional[int] = None
|
||||
status: Optional[str] = None # 'active' or 'inactive'
|
||||
|
||||
|
||||
class ClientRegistrationData(BaseModel):
|
||||
"""Data for client self-registration"""
|
||||
dca_mode: str = "flow" # Default to flow mode
|
||||
fixed_mode_daily_limit: Optional[int] = None
|
||||
username: Optional[str] = None
|
||||
class UpdateClientAutoforward(BaseModel):
|
||||
"""LPs can manage their own auto-forward setting per #8. Applies to all
|
||||
of the LP's dca_clients rows (across every machine they're on)."""
|
||||
|
||||
autoforward_enabled: Optional[bool] = None
|
||||
autoforward_ln_address: Optional[str] = None
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue