2.3 KiB
2.3 KiB
pub struct Billing
Billing is a service which polls the database, creates invoices, and attempts to collect payment for invoices.
Members:
nwc_url: String- a nostr wallet connect URL used to create invoicesrepo: Reporobot: Robot
pub fn new(repo: Repo, robot: Robot) -> Self
- Reads environment and populates members
pub async fn start(self)
Calls self.tick in a loop every hour.
pub async fn tick(self)
Iterates over repo.list_activity since last run and does the following:
- For any
create_relay|update_relay|activate_relayactivity if this is the first non-free relay for the tenant, update tenant's billing anchor to the time the relay was created.
Also iterates over repo.list_tenants() and for each tenant calls self.generate_invoice_if_due(tenant) and self.collect_outstanding(tenant).
async fn generate_invoice_if_due(&self, tenant: &Tenant)
- Skip tenants that have a
pendinginvoice or have no active non-free relays. - Compute current billing period from
tenant.billing_anchoras rolling monthly windows:[period_start, period_end). - Only generate an invoice once the period has closed (
now >= period_end). - Load activity needed to compute usage for the tenant using
repo.list_activity. - Calculate how many hours (rounded up) each relay was active during the window per paid plan.
- If total invoice amount is 0, return.
- Generate a
bolt11invoice. If this fails, log the error and return. - Generate an invoice for the tenant and an invoice item for each relay.
- Persist invoice + items atomically using
repo.create_invoice.
async fn collect_outstanding(&self, tenant: &Tenant)
- Load
pendingtenant invoices and attempt to collect each one. - If
attempted_atis less than 24 hours ago, skip it. - If the
bolt11invoice has been paid out of band, callrepo.mark_invoice_paidand return. - If the tenant has a
nwc_url, attempt to pay the invoice with nwc. - If collection succeeds, call
repo.mark_invoice_paid. - If collection fails, populate
repo.mark_invoice_attempted. - If nwc isn't set up or fails and
sent_atis not set:- Send a NIP 17 DM to the user with the invoice included.
- Call
repo.mark_invoice_sent.
- If the invoice is 7 days past
created_at, callrepo.mark_invoice_closed.