Skip to content

feat: subscriptions delegation payment lifecycle - #10305

Open
lwin-kyaw wants to merge 7 commits into
mainfrom
feat/subs-payment-life-cycle
Open

lwin-kyaw wants to merge 7 commits into
mainfrom
feat/subs-payment-life-cycle

Conversation

@lwin-kyaw

@lwin-kyaw lwin-kyaw commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds subscription-controller support for Money Account delegation payment states, delegation rotation, and access-token refreshes.

Changes

  • Added typed Subscription API payment-execution errors and lastInvoice response data.
  • Added selectors for:
    • Payment failure state and reason.
    • Renewal/recovery-needed state.
    • Delegation allowance exhaustion.
  • Preserved the distinction between:
    • Payment-method errors from paymentMethod.crypto.error.
    • CHOMP/payment-execution errors from lastInvoice.errorCode.
  • Added a delegation-specific updatePaymentMethod request variant for SUB-920 rotation.
  • Added optional force-new delegation preparation:
    • Creates a replacement delegation instead of reusing an existing one.
    • Signs and verifies the delegation.
    • Persists it and registers the corresponding intent.
  • Ensured subscription state changes trigger triggerAccessTokenRefresh() so the Authentication service can refresh the moneyAccountPlan claim.
  • Preserved existing Shield ERC-20 payment and entitlement behavior.
  • Added and updated changelog entries and generated messenger action types.

Error handling

The controller interprets Subscription API payment errors as follows:

Error code Controller behavior
insufficient_balance Payment failed; renewal/recovery can be offered
delegation_not_found Payment failed; renewal/recovery can be offered
exceeds_delegation_allowance Delegation is exhausted
delegation_revoked Terminal delegation failure
recipient_not_allowlisted Terminal payment failure
internal_server_error Terminal payment failure
insufficient_allowance Preserved as a payment-method/payment error

Delegation rotation flow

Consumers can rotate an active subscription by:

  1. Calling SubscriptionDelegationService:prepareDelegation(request, true).
  2. Passing the returned delegationHash to SubscriptionController:updatePaymentMethod.
  3. Updating the existing subscription using the SUB-920 delegation payload.

The subscription is updated in place and is not recreated.

References

https://consensyssoftware.atlassian.net/browse/SUB-885?atlOrigin=eyJpIjoiZTk1OWY4YjQ5YWJlNGRkYzkwMWEzYzdlZGU4Y2Y0ZGQiLCJwIjoiaiJ9

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Breaking Subscription typing and expanded payment/delegation flows affect consumers and access-token refresh timing around billing failures.

Overview
Adds Money Account Plus support for crypto payment-execution failures from the Subscription API, including typed CRYPTO_PAYMENT_ERRORS, optional Subscription.lastInvoice, and product-scoped selectors (selectIsPaymentFailed, selectPaymentFailureReason, selectIsRenewalNeeded, selectIsDelegationExhausted) that read lastInvoice.errorCode, not paymentMethod.crypto.error.

Breaking: Subscription.currentPeriodStart, currentPeriodEnd, cancelType, and isEligibleForSupport are now optional so paused/failed crypto subscriptions validate. Response parsing and structs accept the new invoice shape and reject unknown execution error codes.

Consumers can rotate delegation payment methods via a delegation-specific UpdatePaymentMethodCryptoRequest (cryptoAuthMethod + delegationHash). SubscriptionDelegationService:prepareDelegation accepts optional forceNew and, when reusing stored delegations, picks the match with the latest period startDate so newer replacements win over older equivalents.

Subscription snapshot changes (including payment-failure updates while status stays active) still drive triggerAccessTokenRefresh so moneyAccountPlan claims stay in sync; Shield behavior is covered by tests.

Reviewed by Cursor Bugbot for commit 0e39b86. Bugbot is set up for automated code reviews on this repo. Configure here.

@lwin-kyaw
lwin-kyaw requested review from a team as code owners September 20, 2026 16:49
@lwin-kyaw
lwin-kyaw deployed to default-branch September 20, 2026 16:49 — with GitHub Actions Active

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 080c233. Configure here.

}

/**
* Returns whether the delegation has exhausted its cumulative allowance.

@tanguyenvn tanguyenvn Sep 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the point "exhausted cumulative allowance" in ticket description is not valid anymore.

This branch was successfully deployed

1 active (outdated) deployment
default-branch 080c2331 Deployed Sep 20, 2026 by lwin-kyaw via Determine whether this PR is a release PR #4285
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants