Description
Following up on mppx discussion #905: could Tempo subscriptions support fixed splits enforced on-chain?
Use case
The author needs creator/platform fee splits for one-time payments and subscriptions. They reported a partial browser-flow patch in the MPP Telegram group and want official support, without the marketplace collecting creator funds before distributing them.
A simple example: a $10 membership pays $8 to the creator and $2 to the platform each period.
tempo.charge supports splits; tempo.subscription authorizes one recipient. Initial scope: one payer, one TIP-20 token, fixed amounts, and existing subscription cadence and expiry rules.
Expected behavior
- Enforce every approved recipient and amount; the platform cannot alter or omit a share.
- Credit all shares atomically or revert the entire payment, including any held funds. Transaction fees may still apply.
- Charge each period at most once, including retries and concurrent attempts.
- Respect cancellation, revocation, and expiry. One subscriber's failure must not block others.
Tradeoff: one recipient's receive restriction blocks that membership's renewal until resolved.
Why this needs more than a recipient list
The current authorization checks bind one recipient and a total period limit. An expanded allowlist alone could permit all $10 to go to one address.
Tempo receive policies can hold funds while the transfer call succeeds. Receipt checks afterward cannot undo partial distribution; recipient-credit checks must trigger rollback during execution.
Suggested starting point
For discussion:
- Authorization: Bind approval to the network, settlement mechanism, token, recipients, amounts, schedule, and expiry. Require fresh approval for changed terms and provide on-chain revocation.
- Enforcement: Explore a minimal contract checking actual credits, with its own period limits and revocation. Allowance alone is insufficient. Keep a native mechanism open as an alternative.
- Compatibility: Require explicit support; unsupported clients reject instead of silently falling back to single-recipient settlement.
- Lifecycle: Track subscription and period. Reverted attempts remain retryable; settled periods cannot be charged again. On-chain revocation blocks later collections without reversing settled payments.
Does this model fit Tempo subscriptions, and how should it integrate with existing authorization?
Feasibility check
A Tempo v1.15.0 local dev-chain prototype demonstrated exact allocation, rollback of a held second share, retry, duplicate-period rejection, cancellation, and expiry. Removing the credit check reproduced partial distribution despite transaction success.
The prototype uses payer-deployed immutable terms and allowance. It establishes settlement feasibility; access-key integration, wallet approval, and live-network compatibility remain unverified.
Activity
horn111 commentedon Sep 30, 2026
Hi @EfeDurmaz16, I'm exploring a testnet demo for the marketplace use case in #905. You proved the local settlement behavior; I'd want to use that work as a starting point.
Have you started testing wallet approval and unattended renewals on testnet?
EfeDurmaz16 commentedon Sep 30, 2026
Wallet approval and unattended renewals on testnet are still unverified. Which wallet and renewal flow are you planning to use for the demo?
horn111 commentedon Oct 1, 2026
I haven't chosen a wallet yet; I'm checking @nofluffdev's current setup.
The target flow is one approval for fixed creator/platform shares, then backend triggered renewals and onchain cancellation.
Could you share the prototype code and any wallet/access key constraints you've identified?
EfeDurmaz16 commentedon Oct 1, 2026
Here’s the TypeScript prototype.
Local access-key tests passed for activation, backend renewal and onchain revocation. The key still permits 10/0 or an omitted share, and a receive-policy block can hold the platform share while consuming the period budget.
Wallet approval, live-network compatibility and unattended testnet renewals remain untested. This is a verifier experiment with a custom renewal callback, not complete SDK support.
horn111 commentedon Oct 1, 2026
Thanks for the code. I'm considering the earlier contract and allowance path for a first testnet demo.
Do you see a way to connect it to mppx's subscription lifecycle, or would it need a separate authorization flow?
EfeDurmaz16 commentedon Oct 1, 2026
The contract prototype already demonstrated exact 8/2 settlement, rollback, period checks and cancellation locally. Separately, we tested a custom renewal callback through
SubscriptionStore.renew.The
activate/renewhooks look like possible adapter points, but we haven't connected the contract path end to end. It would still need its own contract/allowance authorization; the current Tempo flow verifies access-key credentials before custom activation.I'm contributing experiments here. Whether this should become a supported subscription path is a question for the maintainers.
nofluffdev commentedon Oct 2, 2026
@EfeDurmaz16
As the README notes, the main integration gap is that the default subscription payment handler still sends the full amount to the primary recipient. Before exposing this as SDK split support, I’d expect:
The counterexamples also clarify the limits of this approach: recipient scopes and an aggregate spending cap do not enforce a fixed allocation or require every recipient to be paid together. The challenge and witness bind the approved terms for SDK verification, but native-key execution still relies on the backend constructing the intended transfers.
The receive-policy case deserves explicit recovery coverage. A successful transaction with an uncredited leg cannot safely be treated as an unpaid attempt and retried in full. Receipt checks can detect that outcome, but cannot reverse funds already transferred.
This seems like a sound starting point for SDK-managed splits, with those guarantees documented explicitly. Integrating the split handling into the default activation and renewal paths would be the next useful step.
EfeDurmaz16 commentedon Oct 2, 2026
@nofluffdev
I’ve now wired splits into the default activation and renewal paths, including sponsorship, stored terms, binding checks and verification of every payment leg. Local lifecycle and concurrent-renewal tests pass.
The 8/2 allocation is still SDK-managed. Receive-policy holds keep their normal behavior; receipt checks cannot undo transferred funds. Recovery after a successful payment followed by a persistence failure remains an open gap.
EfeDurmaz16 commentedon Oct 2, 2026
@nofluffdev Here’s the SDK lifecycle diff. It includes stored split terms and binding checks, the shared activation/renewal batch, and per-leg verification with tests.
nofluffdev commentedon Oct 2, 2026
@EfeDurmaz16 nice work, lgtm!