feat: merge a link's extra into the payout payment (v1.2.2-aio.2) #3
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/extra-passthrough"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Adds an optional
extra(JSON) field to a withdraw link. When the link is claimed, thatextrais merged onto the payout payment'sextra, so a caller can tag the resulting payment with metadata an external listener keys on.Before this, an LNURL-withdraw payout carried only
{tag: "withdraw", withdrawal_link_id}— there was no way to attach caller metadata, because the customer (not the operator) triggers the payout via the public callback.Why
bitSpire cash-in settlements. The operator's
spirekeeperlistener creates acash_insettlement (and pays the platform its fee) only on an outbound payment stampedsource=bitspire. With no way to stamp an LNURL-withdraw payout, cash-ins never settled, never charged a fee, and never paid the platform. bitSpire now creates the cash-in link for the NET amount withextra={source, type:cash_in, principal_sats, fee_sats, nostr attribution}, and the settlement fires on claim.Changes
extra: dict | NoneonCreateWithdrawData+WithdrawLink. LNbits' db layer (de)serializes dict columns to/from JSON natively (same asPayment.extra) — no per-field validator needed.withdraw_link.extra TEXTtracked underwithdraw_fork, keeping the upstream-trackedmigrations.pybyte-identical for clean rebases (aiolabs/lnbits#8pattern — withdraw's first fork migration).extra={**(link.extra or {}), "tag": "withdraw", "withdrawal_link_id": link.id}— the extension's own keys are written last so a caller cannot clobber them.1.2.2→1.2.2-aio.2.Verification (dev stack)
A stamped link's payout carries the merged
extra(source=bitspire, type=cash_in, principal=82386, fee=6591) and drives a full spirekeepercash_insettlement — net to customer 75,795, super fee 2,472 paid, settlementprocessed.black+ruffclean on all changed files.Post-merge
Tag
v1.2.2-aio.2at the merged HEAD and add a new catalog entry toaiolabs/lnbits-extensions(alongside-aio.1, not overwriting it).🤖 Generated with Claude Code
extrainto 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.create_withdrawnostr-transport RPC (#31) #32