Pairs with the satmachineadmin Phase 1 refactor that hoisted LP state
into `satoshimachine.dca_lp` (one row per user). This extension is now
the WRITER for that table; satmachineadmin only reads it during
distribution.
API surface:
- `GET /api/v1/dca-client/preferences` — returns the LP's
`dca_lp` row, AUTO-CREATING it with the authenticated wallet
as the default DCA destination on first call. Hitting this
endpoint is the act that marks the LP as onboarded on the
operator side (gating their deposit creation).
- `PUT /api/v1/dca-client/preferences` — LP-side update of
wallet / mode / fixed-mode limit / autoforward fields. Ensures
the row exists before applying. Replaces the old
`PUT /autoforward` endpoint (which is gone).
- `GET /api/v1/dca-client/positions` — same shape as before
but also auto-inits dca_lp on entry (so opening the dashboard
onboards the LP). Now INNER JOINs dca_lp so only onboarded
LPs see positions (matches the operator-side "must onboard
before deposits" gate).
- `GET /api/v1/dca-client/transactions` — unchanged.
Models:
- New `LpPreferences` / `UpdateLpPreferences` exposing the
dca_lp fields.
- `UpdateClientAutoforward` removed (replaced by the broader
`UpdateLpPreferences`).
- `PerMachinePosition.dca_mode` now sourced from `dca_lp` (it's
LP-wide, echoed on each position row for legacy display
compatibility).
CRUD:
- `_fetch_user_clients` rewritten: INNER JOIN dca_lp, drop
references to removed `dca_clients.wallet_id` / `.dca_mode`
columns (they don't exist anymore post-Phase-1).
- New: `get_lp_preferences`, `ensure_lp_preferences`,
`update_lp_preferences`. The first writes nothing; the second
is the get-or-create that defends the auto-onboard invariant.
- `update_lp_autoforward` removed — write path is now
`update_lp_preferences` against `dca_lp`, not the multi-row
UPDATE on `dca_clients` that used to be needed because the
state was denormalised across enrolments.
Note: the legacy static/js/index.js in this extension references
endpoints that no longer exist (`/registration-status`, `/register`,
`/dashboard/summary`, ...) — that's pre-existing tech debt from when
the LP UX was moved to ~/dev/webapp. Not regressed by this commit;
the deprecated frontend is out of scope. For now LP onboarding works
via direct API call (curl `GET /preferences` once with the LP's wallet
admin key); the webapp will own the proper UI.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
104 lines
3.6 KiB
Python
104 lines
3.6 KiB
Python
# 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
|
||
|
||
from pydantic import BaseModel
|
||
|
||
|
||
class PerMachinePosition(BaseModel):
|
||
"""LP's position at a single machine.
|
||
|
||
`dca_mode` was previously per-(machine, LP) and is now LP-wide (lives
|
||
on `dca_lp.default_dca_mode`). Echoed here for legacy UI display only
|
||
— every position for a given LP shares the same value.
|
||
"""
|
||
|
||
machine_id: str
|
||
machine_npub: str
|
||
machine_name: Optional[str]
|
||
machine_location: Optional[str]
|
||
currency: str
|
||
dca_mode: str
|
||
status: str
|
||
total_sats_accumulated: int
|
||
total_fiat_invested: float
|
||
current_fiat_balance: float
|
||
total_transactions: int
|
||
last_transaction_date: Optional[datetime]
|
||
|
||
|
||
class ClientDashboardSummary(BaseModel):
|
||
"""LP's aggregated dashboard across all machines they're registered at."""
|
||
|
||
user_id: str
|
||
total_sats_accumulated: int
|
||
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
|
||
total_machines: int # how many machines this LP is on
|
||
last_transaction_date: Optional[datetime]
|
||
currency: str # display currency; if multi-currency, "MIX"
|
||
positions: List[PerMachinePosition] = []
|
||
|
||
|
||
class LpPreferences(BaseModel):
|
||
"""LP-controlled DCA preferences (one row per user in `dca_lp`).
|
||
|
||
Auto-created on first satmachineclient dashboard access with the LP's
|
||
authenticated wallet as the default `dca_wallet_id`; they can change
|
||
any field via `PUT /api/v1/dca-client/preferences`. Distribution
|
||
reads from here at payout time — operator cannot override.
|
||
"""
|
||
|
||
user_id: str
|
||
dca_wallet_id: str
|
||
default_dca_mode: str # 'flow' | 'fixed'
|
||
fixed_mode_daily_limit: Optional[float]
|
||
autoforward_ln_address: Optional[str]
|
||
autoforward_enabled: bool
|
||
created_at: datetime
|
||
updated_at: datetime
|
||
|
||
|
||
class UpdateLpPreferences(BaseModel):
|
||
"""LP-side preference updates. All fields optional; only ones provided
|
||
are touched. Use to switch DCA wallet, change mode, toggle autoforward."""
|
||
|
||
dca_wallet_id: Optional[str] = None
|
||
default_dca_mode: Optional[str] = None
|
||
fixed_mode_daily_limit: Optional[float] = None
|
||
autoforward_ln_address: Optional[str] = None
|
||
autoforward_enabled: Optional[bool] = None
|
||
|
||
|
||
class ClientTransaction(BaseModel):
|
||
"""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: Optional[float]
|
||
exchange_rate: Optional[float]
|
||
status: str
|
||
created_at: datetime
|
||
transaction_time: datetime
|
||
|
||
|
||
# `UpdateClientAutoforward` removed in the dca_lp refactor; preferences
|
||
# (autoforward, wallet, mode) now flow through `UpdateLpPreferences`
|
||
# against `PUT /api/v1/dca-client/preferences`.
|