feat: merge a link's extra into the payout payment (v1.2.2-aio.2)
Adds an optional `extra` (JSON) field to a withdraw link. When the link
is claimed, that `extra` is merged onto the payout payment's `extra`, so
a caller can tag the resulting payment with metadata an external listener
keys on — the link is the only place to attach it (the customer-facing
LNURL-withdraw payout otherwise carries just `{tag, withdrawal_link_id}`).
Motivating use: bitSpire cash-in settlements. The operator's spirekeeper
listener fires a `cash_in` settlement (fee split to the platform) only on
an outbound payment stamped `source=bitspire`; before this there was no
way to stamp an LNURL-withdraw payout, so cash-ins never settled. bitSpire
now creates the cash-in link for the NET amount with
`extra={source, type:cash_in, principal_sats, fee_sats, ...}` and the
settlement fires on claim.
- models: `extra: dict | None` on CreateWithdrawData + WithdrawLink.
LNbits' db layer (de)serializes dict columns to/from JSON natively
(same as Payment.extra) — no per-field validator needed.
- migrations_fork.py: `withdraw_link.extra TEXT` under `withdraw_fork`,
keeping the upstream-tracked migrations.py byte-identical for clean
rebases (aiolabs/lnbits#8 pattern).
- views_lnurl: `extra={**(link.extra or {}), "tag": ..., "withdrawal_link_id": ...}`
— the withdraw extension's own keys are written last so a caller cannot
clobber them.
Verified end-to-end on the dev stack: a stamped link's payout carries the
merged extra and drives a spirekeeper cash_in settlement + super-fee payout.
This commit is contained in:
parent
2877cf6b20
commit
9c0e58a87c
5 changed files with 66 additions and 2 deletions
44
migrations_fork.py
Normal file
44
migrations_fork.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
"""
|
||||
Fork-specific database migrations for the aiolabs withdraw extension.
|
||||
|
||||
These migrations are tracked separately under `withdraw_fork` in the
|
||||
`dbversions` table (loaded by `lnbits/core/helpers.py:migrate_extension_database`),
|
||||
so they do not collide with upstream's `m{NNN}_*` numbering in
|
||||
`migrations.py`. Keeping the upstream-tracked file untouched means
|
||||
`git pull upstream` stays rebase-clean for schema changes.
|
||||
|
||||
Conventions:
|
||||
- Sequential numbering starting from m001.
|
||||
- Each migration is `async def m{NNN}_<description>(db)`.
|
||||
- DDL must be idempotent: a fresh install runs every migration; an
|
||||
install that already carries the column must not crash. Use
|
||||
`_alter_add_column_safe` so re-runs are no-ops.
|
||||
"""
|
||||
|
||||
|
||||
async def _alter_add_column_safe(db, sql: str) -> None:
|
||||
"""ALTER TABLE ADD COLUMN that swallows duplicate-column errors, so a
|
||||
re-run on a DB that already has the column is a silent no-op."""
|
||||
try:
|
||||
await db.execute(sql)
|
||||
except Exception as exc:
|
||||
msg = str(exc).lower()
|
||||
if "duplicate column" in msg or "already exists" in msg:
|
||||
return
|
||||
raise
|
||||
|
||||
|
||||
async def m001_aio_withdraw_schema(db):
|
||||
"""
|
||||
Apply every aiolabs schema delta on top of upstream withdraw.
|
||||
|
||||
`withdraw_link.extra` — arbitrary JSON merged into the payout payment's
|
||||
`extra` when the link is claimed (see views_lnurl). Lets a caller tag the
|
||||
resulting payment with settlement/attribution metadata an external listener
|
||||
can key on — e.g. bitSpire stamps {source, type, principal_sats, fee_sats,
|
||||
...} so the spirekeeper cash-in settlement fires off an LNURL-withdraw
|
||||
payout. Stored as TEXT; (de)serialized to a dict by the WithdrawLink model.
|
||||
"""
|
||||
await _alter_add_column_safe(
|
||||
db, "ALTER TABLE withdraw.withdraw_link ADD COLUMN extra TEXT"
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue