diff options
| author | Adam Soltys <[email protected]> | 2026-10-04 13:05:53 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-04 13:05:53 -0700 |
| commit | 1ff2623dbb43148267eac5cbe68c76d2c0639805 (patch) | |
| tree | 469260cac95741bbd319ee1e699ed56834e1abcc /lib/payments.ts | |
| parent | 41a5819f5d7c662a5a2884952e49a14464e83c41 (diff) | |
| download | coinos-server-1ff2623dbb43148267eac5cbe68c76d2c0639805.tar.gz coinos-server-1ff2623dbb43148267eac5cbe68c76d2c0639805.zip | |
v3 bridge: a migrated name's legacy receives are paid on to its v3 wallet
A user who moved their name to coinos v3 keeps their legacy account, and
old BOLT12 offers, bolt11 invoices and bitcoin/liquid deposit addresses
keep paying into it. Each confirmed receive of those kinds is now
forwarded as it lands to the name's v3 lightning address (registrar
invoice on the ASP node; the v3 forwarder delivers to the Ark mailbox
even with the wallet closed). Only new receives move; existing balances
stay. Routing cost only: the platform fee is waived (debit exempt), and
the direct channels to the ASP node quote 0. Proof required: the
registrar holds the name for the legacy account's own key, or for the
wallet its session named in a migration grant (/name granted flag).
Autowithdraw stands down for forwarded receives; failures retry with
backoff (v3fwd:retry, one process at a time) and otherwise stay put.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_011bvzKaZosXGHkigcGcSzAR
Diffstat (limited to 'lib/payments.ts')
| -rw-r--r-- | lib/payments.ts | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/lib/payments.ts b/lib/payments.ts index 84d2f25a..58dabc0d 100644 --- a/lib/payments.ts +++ b/lib/payments.ts @@ -40,6 +40,7 @@ import { t, } from "$lib/utils"; import { callWebhook } from "$lib/webhooks"; +import { maybeForwardToV3, retryV3Forwards } from "$lib/v3forward"; import changeid from "$lib/changeid"; import rpc from "@coinos/rpc"; import { bech32 } from "bech32"; @@ -111,6 +112,8 @@ export const debit = async ({ user, type = PaymentType.internal, rate = undefined, + // a v3 bridge forward (lib/v3forward.ts) costs routing only + exempt = false, maxTotal = undefined, }) => { amount = Number.parseInt(amount); @@ -245,7 +248,7 @@ export const debit = async ({ ? Math.round((amount + fee + tip) * feeRate) : 0; - if (aid !== uid) ourfee = 0; + if (aid !== uid || exempt) ourfee = 0; // NWC and other delegated spenders can provide the exact allowance remaining // for this call. Enforce it only after debit has reloaded the invoice and @@ -533,10 +536,17 @@ export const credit = async ({ return p; }; +const forwardSend = (o) => sendLightning({ ...o, exempt: true }); +// failed forwards retry with backoff; one process works the queue at a time +setInterval(() => retryV3Forwards(forwardSend).catch(() => {}), 60_000).unref(); + export const completePayment = async (inv, p, user) => { const { id, autowithdraw, threshold, reserve, destination, username } = user; let withdrawal; - if (p.confirmed) { + // A name that moved to coinos v3: the receive is paid on to the v3 wallet + // (lib/v3forward.ts), and legacy autowithdraw stands down for it. + const forwarded = await maybeForwardToV3(p, user, forwardSend); + if (p.confirmed && !forwarded) { if (autowithdraw) { try { const to = destination.trim(); @@ -945,6 +955,7 @@ export const sendLightning = async ({ memo = undefined, payerNote = undefined, maxTotal = undefined, + exempt = false, }) => { let p; @@ -1049,6 +1060,7 @@ export const sendLightning = async ({ user, type: PaymentType.lightning, maxTotal, + exempt, }); await db.sAdd("pending", pr); |
