subscriptions
A multi-provider subscription hub on gno.land: providers publish plans priced per billing period; subscribers pay per period; renewal, grace, expiration and cancellation follow deterministic block-height rules; and any realm or service can gate access with one call.
The rules, in full
| Event | Rule |
|---|---|
| Subscribe | pay exactly price; paidThrough = height + periodBlocks |
| Entitlement | height < paidThrough — status does not enter into it |
| Renew | pay exactly price; accepted iff paidThrough − height ≤ periodBlocks (early bound: at most one unstarted period prepaid — the duplicate-payment guard) and height < paidThrough + periodBlocks (grace bound, exclusive — a renewal always buys at least one block); extends from paidThrough, so period boundaries never drift and a grace renewal back-pays the lapsed span. A lapsed subscriber who prefers a fresh full period may Cancel + Subscribe at the same total price |
| Cancel | subscriber only; terminal; no refund — entitlement already paid for runs to paidThrough; the subscription can never be renewed again |
| Expire | permissionless once height ≥ paidThrough + periodBlocks; no funds move; frees the plan/subscriber slot (Subscribe also collapses an expired incumbent itself). From paidThrough − periodBlocks onward, every height is exactly one of renewable or expirable; below that window a renewal is refused as too early |
| RetirePlan | provider only; no new subscriptions, no renewals; existing entitlements run out untouched |
The on-chain obligation is explicit at every moment: the realm owes the subscriber exactly paidThrough − height blocks of entitlement (queryable by anyone via PaidThrough / Entitled / EntitledFor / RenewableFrom), and the subscriber owes nothing — there is no pull payment and no debt; a lapse simply ends entitlement.
Payments and custody
Payments settle immediately: price − fee to the provider's claimable balance, fee to the protocol pot, both in the composed feeledger. There is no escrow; the monetary invariant is H == U + F (holdings = provider balances + fee pot), with out-of-band surplus recoverable above the Liabilities() reserve. The protocol fee follows the portfolio pattern: compile-time cap MaxFeeBps = 1000, snapshotted into the plan at creation under the provider's own consent ceiling, immutable afterwards.
Unauthorized / duplicate / out-of-window payments
- Unauthorized: only the subscriber may renew or cancel their subscription; only the provider may retire a plan; only the fee recipient touches the pot; admin handover is two-step.
- Duplicate: one live subscription per (plan, subscriber); the renewal path is
Renew, never a secondSubscribe; the early bound refuses a second renewal until a period's worth of blocks has passed. - Out-of-window: both window bounds are checked on chain and precomputed for integrators by
RenewableFrom.
Integration
Gate anything on EntitledFor(planID, subscriber) — it follows the subscriber's most recent subscription to the plan and honors paid entitlement across cancellation. Subscribers are EOAs (coinio's receipt guard); providers may be realms but must expose their own crossing path to Claim — see the header caveat.
Composition
feeledger (balances, fees, conservation) + coinio (receive / payout / sweep) + avl (ordered state) + sanitize/v0 (Render). Discovery record: DISCOVERY.md.