@metamask/subscription-controller 12.0.1 → 14.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +45 -1
  2. package/dist/SubscriptionController-method-action-types.d.ts +14 -4
  3. package/dist/SubscriptionController-method-action-types.d.ts.map +1 -1
  4. package/dist/SubscriptionController-method-action-types.js.map +1 -1
  5. package/dist/SubscriptionController.d.ts +16 -5
  6. package/dist/SubscriptionController.d.ts.map +1 -1
  7. package/dist/SubscriptionController.js +61 -16
  8. package/dist/SubscriptionController.js.map +1 -1
  9. package/dist/SubscriptionService-structs.d.ts +36 -36
  10. package/dist/SubscriptionService-structs.js +4 -4
  11. package/dist/SubscriptionService-structs.js.map +1 -1
  12. package/dist/constants.d.ts +6 -2
  13. package/dist/constants.d.ts.map +1 -1
  14. package/dist/constants.js +39 -2
  15. package/dist/constants.js.map +1 -1
  16. package/dist/index.d.ts +2 -2
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +1 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/subscription-delegation/SubscriptionDelegationService-method-action-types.d.ts +9 -14
  21. package/dist/subscription-delegation/SubscriptionDelegationService-method-action-types.d.ts.map +1 -1
  22. package/dist/subscription-delegation/SubscriptionDelegationService-method-action-types.js.map +1 -1
  23. package/dist/subscription-delegation/SubscriptionDelegationService.d.ts +11 -17
  24. package/dist/subscription-delegation/SubscriptionDelegationService.d.ts.map +1 -1
  25. package/dist/subscription-delegation/SubscriptionDelegationService.js +35 -107
  26. package/dist/subscription-delegation/SubscriptionDelegationService.js.map +1 -1
  27. package/dist/subscription-delegation/types.d.ts +0 -21
  28. package/dist/subscription-delegation/types.d.ts.map +1 -1
  29. package/dist/subscription-delegation/types.js +0 -1
  30. package/dist/subscription-delegation/types.js.map +1 -1
  31. package/dist/types.d.ts +18 -4
  32. package/dist/types.d.ts.map +1 -1
  33. package/dist/types.js.map +1 -1
  34. package/package.json +7 -7
@@ -1,15 +1,14 @@
1
- import { ORIGIN_METAMASK } from '@metamask/controller-utils';
2
1
  import { hashDelegation } from '@metamask/delegation-core';
3
2
  import { DELEGATOR_CONTRACTS } from '@metamask/delegation-deployments';
4
- import { getMoneyAccountDepositAssetAddress, getMoneyAccountVaultConfig, MUSD_DECIMALS, } from '@metamask/money-account-utils';
5
- import { add0x, hexToNumber, isStrictHexString } from '@metamask/utils';
3
+ import { getMoneyAccountVaultConfig, MUSD_DECIMALS, } from '@metamask/money-account-utils';
4
+ import { add0x, hexToNumber } from '@metamask/utils';
6
5
  import { ACTIVE_SUBSCRIPTION_STATUSES, SubscriptionControllerErrorMessage, SubscriptionDelegationServiceErrorMessage, } from '../constants.js';
7
6
  import { CRYPTO_AUTH_METHODS, PAYMENT_TYPES, PRODUCT_TYPES } from '../types.js';
8
7
  import { assertPositiveInteger, calculatePeriodAmount, getDelegationStartDate, getPeriodDuration, } from './amount.js';
9
8
  import { buildUnsignedSubscriptionDelegation } from './caveats.js';
10
9
  import { equalsIgnoreCase, makeMatchesSubscriptionDelegation, pickLatestMatchingSubscriptionDelegation, } from './fingerprint.js';
11
10
  import { buildDelegationTypedData, decodeSubscriptionAuthority, } from './typed-data.js';
12
- import { CASH_SUBSCRIPTION_DELEGATION_TYPE, SUBSCRIPTION_DELEGATION_APPROVAL_TYPE, SUBSCRIPTION_DELEGATION_POLICY_VERSION, } from './types.js';
11
+ import { CASH_SUBSCRIPTION_DELEGATION_TYPE } from './types.js';
13
12
  /**
14
13
  * The name of the {@link SubscriptionDelegationService}, used to namespace the
15
14
  * service's actions and events.
@@ -90,22 +89,17 @@ export class SubscriptionDelegationService {
90
89
  * Runs the complete Money Account subscription checkout authorization flow.
91
90
  *
92
91
  * Subscriptions are refreshed first. An active subscription for the product
93
- * is rejected before Money Account upgrade, approval, delegation signing,
94
- * persistence, or CHOMP registration.
92
+ * is rejected before Money Account upgrade, delegation signing, persistence,
93
+ * or CHOMP registration.
95
94
  *
96
- * Before the approval, `MoneyAccountUpgradeController` is asked to ensure
97
- * the Money Account vault delegations and CHOMP intents exist; the
98
- * Subscription API validates them server-side. The custom approval is the
99
- * sole consent and funding boundary for the payment permission. No payment
100
- * delegation signing, persistence, or intent mutation occurs before it
101
- * returns a funding transaction hash.
95
+ * The caller must obtain user consent and initiate funding before calling.
96
+ * `MoneyAccountUpgradeController` ensures the Money Account vault
97
+ * delegations and CHOMP intents exist. The Subscription API validates those
98
+ * delegations and the Money Account balance server-side. No payment
99
+ * delegation signing, persistence, or intent mutation occurs before the
100
+ * account is upgraded.
102
101
  *
103
- * When `request.skipApproval` is `true`, the approval request and its
104
- * result validation are skipped and the flow proceeds directly to signing.
105
- * The caller is then responsible for consent and funding.
106
- *
107
- * @param request - Product selection, Money Account identity, and optional
108
- * `skipApproval` flag.
102
+ * @param request - Product selection and Money Account identity.
109
103
  * @returns The result from `SubscriptionController:startSubscriptionWithCrypto`.
110
104
  */
111
105
  async startSubscriptionWithDelegation(request) {
@@ -118,58 +112,32 @@ export class SubscriptionDelegationService {
118
112
  }
119
113
  const subscriptions = await this.#messenger.call('SubscriptionController:getSubscriptions');
120
114
  this.#assertUserNotSubscribed(subscriptions, request.product);
121
- const { trialedProducts } = this.#messenger.call('SubscriptionController:getState');
122
- const isTrialRequested = config.price.trialPeriodDays > 0 &&
123
- !trialedProducts.includes(request.product);
115
+ const isEligibleForTrial = await this.#messenger.call('SubscriptionController:isUserEligibleForTrial', request.product);
116
+ const isTrialRequested = config.price.trialPeriodDays > 0 && isEligibleForTrial;
124
117
  await this.#messenger.call('MoneyAccountUpgradeController:forceUpgradeAccount', request.payerAddress);
125
118
  const paymentPermission = await this.#preparePaymentPermission(request, config, isTrialRequested);
126
- const bundle = {
127
- policyVersion: SUBSCRIPTION_DELEGATION_POLICY_VERSION,
128
- account: request.payerAddress,
119
+ const paymentDelegation = await this.#signPaymentPermissionIfRequired(paymentPermission, config);
120
+ const paymentDelegationHash = await this.#commitPaymentPermission({
121
+ request,
122
+ paymentPermission,
123
+ paymentDelegation,
124
+ config,
125
+ });
126
+ return await this.#messenger.call('SubscriptionController:startSubscriptionWithCrypto', {
127
+ products: [request.product],
128
+ isTrialRequested,
129
+ recurringInterval: request.recurringInterval,
130
+ billingCycles: config.price.minBillingCycles,
129
131
  chainId: request.chainId,
130
- permissions: [paymentPermission],
131
- };
132
- const approval = request.skipApproval
133
- ? undefined
134
- : await this.#requestApproval({
135
- request,
136
- price: config.price,
137
- musdAddress: config.musdAddress,
138
- bundle,
139
- });
140
- try {
141
- if (approval) {
142
- this.#validateApprovalResult(approval);
143
- }
144
- const paymentDelegation = await this.#signPaymentPermissionIfRequired(paymentPermission, config);
145
- const paymentDelegationHash = await this.#commitPaymentPermission({
146
- request,
147
- paymentPermission,
148
- paymentDelegation,
149
- config,
150
- });
151
- const result = await this.#messenger.call('SubscriptionController:startSubscriptionWithCrypto', {
152
- products: [request.product],
153
- isTrialRequested,
154
- recurringInterval: request.recurringInterval,
155
- billingCycles: config.price.minBillingCycles,
156
- chainId: request.chainId,
157
- payerAddress: request.payerAddress,
158
- tokenSymbol: config.token.symbol,
159
- cryptoAuthMethod: CRYPTO_AUTH_METHODS.DELEGATION,
160
- delegationHash: paymentDelegationHash,
161
- // Reject if eligibility changed during approval, because the signed
162
- // delegation start date was derived from the original trial state.
163
- // This local guard is removed before the backend request.
164
- assertTrialEligibility: true,
165
- });
166
- approval?.resultCallbacks?.success();
167
- return result;
168
- }
169
- catch (error) {
170
- approval?.resultCallbacks?.error(error);
171
- throw error;
172
- }
132
+ payerAddress: request.payerAddress,
133
+ tokenSymbol: config.token.symbol,
134
+ cryptoAuthMethod: CRYPTO_AUTH_METHODS.DELEGATION,
135
+ delegationHash: paymentDelegationHash,
136
+ // Reject if eligibility changed during checkout, because the signed
137
+ // delegation start date was derived from the original trial state.
138
+ // This local guard is removed before the backend request.
139
+ assertTrialEligibility: true,
140
+ });
173
141
  }
174
142
  /**
175
143
  * Rejects when the refreshed list already contains an active subscription
@@ -185,31 +153,6 @@ export class SubscriptionDelegationService {
185
153
  throw new Error(SubscriptionControllerErrorMessage.UserAlreadySubscribed);
186
154
  }
187
155
  }
188
- async #requestApproval({ request, price, musdAddress, bundle, }) {
189
- const targetAmount = calculatePeriodAmount({
190
- unitAmount: price.unitAmount,
191
- unitDecimals: price.unitDecimals,
192
- tokenDecimals: MUSD_DECIMALS,
193
- }) * BigInt(price.minBillingCyclesForBalance);
194
- return (await this.#messenger.call('ApprovalController:addRequest', {
195
- origin: ORIGIN_METAMASK,
196
- type: SUBSCRIPTION_DELEGATION_APPROVAL_TYPE,
197
- expectsResult: true,
198
- requestData: {
199
- bundle,
200
- funding: {
201
- useCase: 'subscription',
202
- destinationAccount: request.payerAddress,
203
- chainId: request.chainId,
204
- targetToken: {
205
- symbol: 'mUSD',
206
- address: musdAddress,
207
- },
208
- targetAmount: targetAmount.toString(),
209
- },
210
- },
211
- }, true));
212
- }
213
156
  async #preparePaymentPermission(request, config, isTrialRequested) {
214
157
  const periodAmount = calculatePeriodAmount({
215
158
  unitAmount: config.price.unitAmount,
@@ -266,20 +209,6 @@ export class SubscriptionDelegationService {
266
209
  : {}),
267
210
  };
268
211
  }
269
- #validateApprovalResult(approval) {
270
- if (!approval?.value || typeof approval.value !== 'object') {
271
- throw new Error(SubscriptionDelegationServiceErrorMessage.ApprovalResultMissing);
272
- }
273
- const value = approval.value;
274
- if (typeof value.fundingTransactionHash !== 'string' ||
275
- !isStrictHexString(value.fundingTransactionHash) ||
276
- value.fundingTransactionHash.length !== 66) {
277
- throw new Error(SubscriptionDelegationServiceErrorMessage.InvalidFundingTransactionHash);
278
- }
279
- return {
280
- fundingTransactionHash: value.fundingTransactionHash,
281
- };
282
- }
283
212
  async #signPaymentPermissionIfRequired(permission, config) {
284
213
  if (permission.disposition === 'reused') {
285
214
  return undefined;
@@ -544,7 +473,6 @@ export class SubscriptionDelegationService {
544
473
  .DelegationManager,
545
474
  paymentAddress: chain.paymentAddress,
546
475
  enforcers,
547
- musdAddress: getMoneyAccountDepositAssetAddress(chainId),
548
476
  price,
549
477
  token,
550
478
  };
@@ -1 +1 @@
1
- {"version":3,"file":"SubscriptionDelegationService.js","sourceRoot":"","sources":["../../src/subscription-delegation/SubscriptionDelegationService.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AddResult,\n ApprovalControllerAddRequestAction,\n} from '@metamask/approval-controller';\nimport type {\n DelegationResponse,\n AuthenticatedUserStorageServiceCreateDelegationAction,\n AuthenticatedUserStorageServiceListDelegationsAction,\n} from '@metamask/authenticated-user-storage';\nimport type {\n ChompApiServiceCreateIntentsAction,\n ChompApiServiceGetIntentsByAddressAction,\n ChompApiServiceVerifyDelegationAction,\n} from '@metamask/chomp-api-service';\nimport { ORIGIN_METAMASK } from '@metamask/controller-utils';\nimport type { DelegationControllerSignDelegationAction } from '@metamask/delegation-controller';\nimport { hashDelegation } from '@metamask/delegation-core';\nimport { DELEGATOR_CONTRACTS } from '@metamask/delegation-deployments';\nimport type { Messenger } from '@metamask/messenger';\nimport type { MoneyAccountBalanceServiceFetchBalanceWithFallbackAction } from '@metamask/money-account-balance-service';\nimport type { MoneyAccountUpgradeControllerForceUpgradeAccountAction } from '@metamask/money-account-upgrade-controller';\nimport {\n getMoneyAccountDepositAssetAddress,\n getMoneyAccountVaultConfig,\n MUSD_DECIMALS,\n} from '@metamask/money-account-utils';\nimport type { RemoteFeatureFlagControllerGetStateAction } from '@metamask/remote-feature-flag-controller';\nimport { add0x, hexToNumber, isStrictHexString } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n ACTIVE_SUBSCRIPTION_STATUSES,\n SubscriptionControllerErrorMessage,\n SubscriptionDelegationServiceErrorMessage,\n} from '../constants.js';\nimport type {\n SubscriptionControllerGetPricingAction,\n SubscriptionControllerGetSubscriptionsAction,\n SubscriptionControllerStartSubscriptionWithCryptoAction,\n} from '../SubscriptionController-method-action-types.js';\nimport type { SubscriptionControllerGetStateAction } from '../SubscriptionController.js';\nimport { CRYPTO_AUTH_METHODS, PAYMENT_TYPES, PRODUCT_TYPES } from '../types.js';\nimport type {\n ProductPrice,\n ProductType,\n PricingCryptoPaymentMethod,\n RecurringInterval,\n Subscription,\n TokenPaymentInfo,\n} from '../types.js';\nimport {\n assertPositiveInteger,\n calculatePeriodAmount,\n getDelegationStartDate,\n getPeriodDuration,\n} from './amount.js';\nimport { buildUnsignedSubscriptionDelegation } from './caveats.js';\nimport {\n equalsIgnoreCase,\n makeMatchesSubscriptionDelegation,\n pickLatestMatchingSubscriptionDelegation,\n} from './fingerprint.js';\nimport type { SubscriptionDelegationServiceMethodActions } from './SubscriptionDelegationService-method-action-types.js';\nimport {\n buildDelegationTypedData,\n decodeSubscriptionAuthority,\n} from './typed-data.js';\nimport type {\n MoneyAccountBalanceCheckRequest,\n MoneyAccountBalanceCheckResult,\n PrepareSubscriptionDelegationRequest,\n PreparedSubscriptionDelegationBundle,\n PreparedSubscriptionPermission,\n PreparedSubscriptionDelegation,\n SignedSubscriptionDelegation,\n StartSubscriptionWithDelegationRequest,\n StartSubscriptionWithDelegationResult,\n SubscriptionDelegationApprovalResult,\n SubscriptionDelegationEnforcers,\n UnsignedSubscriptionDelegation,\n} from './types.js';\nimport {\n CASH_SUBSCRIPTION_DELEGATION_TYPE,\n SUBSCRIPTION_DELEGATION_APPROVAL_TYPE,\n SUBSCRIPTION_DELEGATION_POLICY_VERSION,\n} from './types.js';\n\n/**\n * The name of the {@link SubscriptionDelegationService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'SubscriptionDelegationService';\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'prepareDelegation',\n 'checkMoneyAccountBalance',\n 'startSubscriptionWithDelegation',\n] as const;\n\nconst DELEGATION_FRAMEWORK_VERSION = '1.3.0';\n\nfunction resolveEnforcers(chainId: Hex): SubscriptionDelegationEnforcers {\n const contracts =\n DELEGATOR_CONTRACTS[DELEGATION_FRAMEWORK_VERSION]?.[hexToNumber(chainId)];\n\n if (\n !contracts?.ERC20PeriodTransferEnforcer ||\n !contracts.AllowedCalldataEnforcer\n ) {\n throw new Error(\n `${SubscriptionDelegationServiceErrorMessage.DelegationContractsNotFound}: ${chainId}`,\n );\n }\n\n return {\n erc20TokenPeriodTransfer: contracts.ERC20PeriodTransferEnforcer,\n allowedCalldata: contracts.AllowedCalldataEnforcer,\n };\n}\n\nfunction removeDelegationSignature(\n delegation: SignedSubscriptionDelegation,\n): UnsignedSubscriptionDelegation {\n const { signature: _signature, ...unsignedDelegation } = delegation;\n return unsignedDelegation;\n}\n\n/**\n * Actions that {@link SubscriptionDelegationService} exposes to other consumers.\n */\nexport type SubscriptionDelegationServiceActions =\n SubscriptionDelegationServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link SubscriptionDelegationServiceMessenger} calls.\n */\ntype AllowedActions =\n | AuthenticatedUserStorageServiceListDelegationsAction\n | AuthenticatedUserStorageServiceCreateDelegationAction\n | ChompApiServiceVerifyDelegationAction\n | ChompApiServiceCreateIntentsAction\n | ChompApiServiceGetIntentsByAddressAction\n | DelegationControllerSignDelegationAction\n | ApprovalControllerAddRequestAction\n | MoneyAccountUpgradeControllerForceUpgradeAccountAction\n | MoneyAccountBalanceServiceFetchBalanceWithFallbackAction\n | RemoteFeatureFlagControllerGetStateAction\n | SubscriptionControllerGetStateAction\n | SubscriptionControllerGetPricingAction\n | SubscriptionControllerGetSubscriptionsAction\n | SubscriptionControllerStartSubscriptionWithCryptoAction;\n\n/**\n * Events that {@link SubscriptionDelegationService} exposes to other consumers.\n */\nexport type SubscriptionDelegationServiceEvents = never;\n\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link SubscriptionDelegationService}.\n */\nexport type SubscriptionDelegationServiceMessenger = Messenger<\n typeof serviceName,\n SubscriptionDelegationServiceActions | AllowedActions,\n SubscriptionDelegationServiceEvents | AllowedEvents\n>;\n\n/**\n * Options for constructing {@link SubscriptionDelegationService}.\n */\nexport type SubscriptionDelegationServiceOptions = {\n messenger: SubscriptionDelegationServiceMessenger;\n};\n\ntype SubscriptionIntentParams = {\n account: Hex;\n chainId: Hex;\n delegationHash: Hex;\n allowance: Hex;\n tokenSymbol: string;\n tokenAddress: Hex;\n};\n\ntype ResolvedSubscriptionDelegationConfig = {\n chainId: Hex;\n delegateAddress: Hex;\n delegationManager: Hex;\n paymentAddress: Hex;\n enforcers: SubscriptionDelegationEnforcers;\n musdAddress: Hex;\n price: ProductPrice;\n token: TokenPaymentInfo;\n};\n\n/**\n * Stateless orchestrator for cash-subscription delegation setup.\n *\n * Owns the workflow: size periodic caveats → sign → CHOMP verify → persist to\n * Authenticated User Storage → register CHOMP intent. Returns a verified\n * `delegationHash` for `SubscriptionController.startSubscriptionWithCrypto`.\n *\n * Pass `skipChompInteractions: true` to skip CHOMP verify and intent\n * registration and return a locally computed delegation hash.\n *\n * Each call resolves the Money Account chain from remote feature flags, then\n * resolves its price, payment token, and delegate from `SubscriptionController`\n * pricing. The pricing `delegateAddress` is used as the delegation `delegate`.\n *\n * Does not own subscription state; `SubscriptionController` does not depend on\n * this service. Only Money Account Plus is supported.\n */\nexport class SubscriptionDelegationService {\n readonly name: typeof serviceName = serviceName;\n\n readonly #messenger: SubscriptionDelegationServiceMessenger;\n\n constructor(options: SubscriptionDelegationServiceOptions) {\n this.#messenger = options.messenger;\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Checks whether the Money Account holds enough convertible mUSD value to\n * cover pricing `unitAmount × minBillingCyclesForBalance`.\n *\n * @param request - Payer address and pricing amount fields.\n * @returns Balance comparison in mUSD base units (6 decimals).\n */\n async checkMoneyAccountBalance(\n request: MoneyAccountBalanceCheckRequest,\n ): Promise<MoneyAccountBalanceCheckResult> {\n const { price } = await this.#resolveConfiguration(\n request.product,\n request.recurringInterval,\n );\n return this.#compareMoneyAccountBalance(request.payerAddress, price);\n }\n\n async #compareMoneyAccountBalance(\n payerAddress: Hex,\n price: ProductPrice,\n ): Promise<MoneyAccountBalanceCheckResult> {\n assertPositiveInteger(\n price.minBillingCyclesForBalance,\n SubscriptionDelegationServiceErrorMessage.InvalidMinimumFundingCycles,\n );\n\n const periodAmount = calculatePeriodAmount({\n unitAmount: price.unitAmount,\n unitDecimals: price.unitDecimals,\n tokenDecimals: MUSD_DECIMALS,\n });\n const requiredBalance =\n periodAmount * BigInt(price.minBillingCyclesForBalance);\n\n const { totalBalance } = await this.#messenger.call(\n 'MoneyAccountBalanceService:fetchBalanceWithFallback',\n payerAddress,\n );\n\n return {\n hasSufficientBalance: BigInt(totalBalance) >= requiredBalance,\n balance: totalBalance,\n requiredBalance: requiredBalance.toString(),\n };\n }\n\n /**\n * Runs the complete Money Account subscription checkout authorization flow.\n *\n * Subscriptions are refreshed first. An active subscription for the product\n * is rejected before Money Account upgrade, approval, delegation signing,\n * persistence, or CHOMP registration.\n *\n * Before the approval, `MoneyAccountUpgradeController` is asked to ensure\n * the Money Account vault delegations and CHOMP intents exist; the\n * Subscription API validates them server-side. The custom approval is the\n * sole consent and funding boundary for the payment permission. No payment\n * delegation signing, persistence, or intent mutation occurs before it\n * returns a funding transaction hash.\n *\n * When `request.skipApproval` is `true`, the approval request and its\n * result validation are skipped and the flow proceeds directly to signing.\n * The caller is then responsible for consent and funding.\n *\n * @param request - Product selection, Money Account identity, and optional\n * `skipApproval` flag.\n * @returns The result from `SubscriptionController:startSubscriptionWithCrypto`.\n */\n async startSubscriptionWithDelegation(\n request: StartSubscriptionWithDelegationRequest,\n ): Promise<StartSubscriptionWithDelegationResult> {\n if (request.product !== PRODUCT_TYPES.MONEY_ACCOUNT_PLUS) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.UnsupportedProduct,\n );\n }\n\n const config = await this.#resolveConfiguration(\n request.product,\n request.recurringInterval,\n );\n if (!equalsIgnoreCase(request.chainId, config.chainId)) {\n throw new Error(SubscriptionDelegationServiceErrorMessage.ChainMismatch);\n }\n const subscriptions = await this.#messenger.call(\n 'SubscriptionController:getSubscriptions',\n );\n this.#assertUserNotSubscribed(subscriptions, request.product);\n const { trialedProducts } = this.#messenger.call(\n 'SubscriptionController:getState',\n );\n const isTrialRequested =\n config.price.trialPeriodDays > 0 &&\n !trialedProducts.includes(request.product);\n\n await this.#messenger.call(\n 'MoneyAccountUpgradeController:forceUpgradeAccount',\n request.payerAddress,\n );\n\n const paymentPermission = await this.#preparePaymentPermission(\n request,\n config,\n isTrialRequested,\n );\n const bundle: PreparedSubscriptionDelegationBundle = {\n policyVersion: SUBSCRIPTION_DELEGATION_POLICY_VERSION,\n account: request.payerAddress,\n chainId: request.chainId,\n permissions: [paymentPermission],\n };\n const approval = request.skipApproval\n ? undefined\n : await this.#requestApproval({\n request,\n price: config.price,\n musdAddress: config.musdAddress,\n bundle,\n });\n\n try {\n if (approval) {\n this.#validateApprovalResult(approval);\n }\n\n const paymentDelegation = await this.#signPaymentPermissionIfRequired(\n paymentPermission,\n config,\n );\n const paymentDelegationHash = await this.#commitPaymentPermission({\n request,\n paymentPermission,\n paymentDelegation,\n config,\n });\n const result = await this.#messenger.call(\n 'SubscriptionController:startSubscriptionWithCrypto',\n {\n products: [request.product],\n isTrialRequested,\n recurringInterval: request.recurringInterval,\n billingCycles: config.price.minBillingCycles,\n chainId: request.chainId,\n payerAddress: request.payerAddress,\n tokenSymbol: config.token.symbol,\n cryptoAuthMethod: CRYPTO_AUTH_METHODS.DELEGATION,\n delegationHash: paymentDelegationHash,\n // Reject if eligibility changed during approval, because the signed\n // delegation start date was derived from the original trial state.\n // This local guard is removed before the backend request.\n assertTrialEligibility: true,\n },\n );\n approval?.resultCallbacks?.success();\n return result;\n } catch (error) {\n approval?.resultCallbacks?.error(error as Error);\n throw error;\n }\n }\n\n /**\n * Rejects when the refreshed list already contains an active subscription\n * for the product. Active includes `active`, `trialing`, and `provisional`.\n *\n * @param subscriptions - Subscriptions returned by the latest refresh.\n * @param product - Product the caller is trying to start.\n */\n #assertUserNotSubscribed(\n subscriptions: Subscription[],\n product: ProductType,\n ): void {\n const alreadySubscribed = subscriptions.some(\n (subscription) =>\n ACTIVE_SUBSCRIPTION_STATUSES.includes(subscription.status) &&\n subscription.products.some((entry) => entry.name === product),\n );\n if (alreadySubscribed) {\n throw new Error(SubscriptionControllerErrorMessage.UserAlreadySubscribed);\n }\n }\n\n async #requestApproval({\n request,\n price,\n musdAddress,\n bundle,\n }: {\n request: StartSubscriptionWithDelegationRequest;\n price: ProductPrice;\n musdAddress: Hex;\n bundle: PreparedSubscriptionDelegationBundle;\n }): Promise<AddResult> {\n const targetAmount =\n calculatePeriodAmount({\n unitAmount: price.unitAmount,\n unitDecimals: price.unitDecimals,\n tokenDecimals: MUSD_DECIMALS,\n }) * BigInt(price.minBillingCyclesForBalance);\n\n return (await this.#messenger.call(\n 'ApprovalController:addRequest',\n {\n origin: ORIGIN_METAMASK,\n type: SUBSCRIPTION_DELEGATION_APPROVAL_TYPE,\n expectsResult: true,\n requestData: {\n bundle,\n funding: {\n useCase: 'subscription',\n destinationAccount: request.payerAddress,\n chainId: request.chainId,\n targetToken: {\n symbol: 'mUSD',\n address: musdAddress,\n },\n targetAmount: targetAmount.toString(),\n },\n },\n },\n true,\n )) as AddResult;\n }\n\n async #preparePaymentPermission(\n request: StartSubscriptionWithDelegationRequest,\n config: ResolvedSubscriptionDelegationConfig,\n isTrialRequested: boolean,\n ): Promise<PreparedSubscriptionPermission> {\n const periodAmount = calculatePeriodAmount({\n unitAmount: config.price.unitAmount,\n unitDecimals: config.price.unitDecimals,\n tokenDecimals: config.token.decimals,\n });\n const periodDuration = getPeriodDuration(request.recurringInterval);\n const nowSeconds = Math.floor(Date.now() / 1000);\n const startDate = getDelegationStartDate({\n nowSeconds,\n trialPeriodDays: isTrialRequested\n ? config.price.trialPeriodDays\n : undefined,\n });\n const matches = makeMatchesSubscriptionDelegation({\n delegatorAddress: request.payerAddress,\n delegateAddress: config.delegateAddress,\n chainId: request.chainId,\n recipientAddress: config.paymentAddress,\n tokenAddress: config.token.address,\n periodAmount,\n periodDuration,\n nowSeconds,\n isTrialDeferred: startDate > nowSeconds,\n enforcers: config.enforcers,\n });\n const reusable = pickLatestMatchingSubscriptionDelegation(\n (\n await this.#messenger.call(\n 'AuthenticatedUserStorageService:listDelegations',\n )\n ).filter(matches),\n config.enforcers,\n );\n const delegation = reusable\n ? removeDelegationSignature(reusable.signedDelegation)\n : buildUnsignedSubscriptionDelegation({\n delegateAddress: config.delegateAddress,\n delegatorAddress: request.payerAddress,\n enforcers: config.enforcers,\n recipientAddress: config.paymentAddress,\n tokenAddress: config.token.address,\n periodAmount,\n periodDuration,\n startDate,\n });\n const typedData = buildDelegationTypedData({\n delegation,\n chainId: request.chainId,\n delegationManager: config.delegationManager,\n });\n\n return {\n id: CASH_SUBSCRIPTION_DELEGATION_TYPE,\n owner: 'subscription',\n disposition: reusable ? 'reused' : 'new',\n delegation,\n typedData,\n decodedAuthority: decodeSubscriptionAuthority(\n delegation,\n config.enforcers,\n ),\n ...(reusable\n ? { existingDelegationHash: reusable.metadata.delegationHash }\n : {}),\n };\n }\n\n #validateApprovalResult(\n approval: AddResult,\n ): SubscriptionDelegationApprovalResult {\n if (!approval?.value || typeof approval.value !== 'object') {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ApprovalResultMissing,\n );\n }\n const value = approval.value as Record<string, unknown>;\n if (\n typeof value.fundingTransactionHash !== 'string' ||\n !isStrictHexString(value.fundingTransactionHash) ||\n value.fundingTransactionHash.length !== 66\n ) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.InvalidFundingTransactionHash,\n );\n }\n return {\n fundingTransactionHash: value.fundingTransactionHash,\n };\n }\n\n async #signPaymentPermissionIfRequired(\n permission: PreparedSubscriptionPermission,\n config: ResolvedSubscriptionDelegationConfig,\n ): Promise<SignedSubscriptionDelegation | undefined> {\n if (permission.disposition === 'reused') {\n return undefined;\n }\n const signature = (await this.#messenger.call(\n 'DelegationController:signDelegation',\n {\n delegation: permission.delegation,\n chainId: config.chainId,\n },\n )) as Hex;\n return { ...permission.delegation, signature };\n }\n\n async #commitPaymentPermission({\n request,\n paymentPermission,\n paymentDelegation,\n config,\n }: {\n request: StartSubscriptionWithDelegationRequest;\n paymentPermission: PreparedSubscriptionPermission;\n paymentDelegation?: SignedSubscriptionDelegation;\n config: ResolvedSubscriptionDelegationConfig;\n }): Promise<Hex> {\n if (paymentPermission.disposition === 'reused') {\n const delegationHash = paymentPermission.existingDelegationHash as Hex;\n const storedDelegation = (\n await this.#messenger.call(\n 'AuthenticatedUserStorageService:listDelegations',\n )\n ).find(({ metadata }) =>\n equalsIgnoreCase(metadata.delegationHash, delegationHash),\n );\n if (!storedDelegation) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ReusableDelegationInvalid,\n );\n }\n await this.#verifySignedPaymentDelegation(\n storedDelegation.signedDelegation,\n delegationHash,\n request.chainId,\n );\n await this.#ensureIntent({\n account: request.payerAddress,\n chainId: request.chainId,\n delegationHash,\n allowance: add0x(\n BigInt(paymentPermission.decodedAuthority.periodAmount).toString(16),\n ),\n tokenSymbol: config.token.symbol,\n tokenAddress: config.token.address,\n });\n await this.#assertIntentActive(request.payerAddress, delegationHash);\n return delegationHash;\n }\n\n const signedDelegation = paymentDelegation as SignedSubscriptionDelegation;\n const delegationHash = hashDelegation({\n ...signedDelegation,\n salt: BigInt(signedDelegation.salt),\n });\n await this.#verifySignedPaymentDelegation(\n signedDelegation,\n delegationHash,\n request.chainId,\n );\n\n const allowance = add0x(\n BigInt(paymentPermission.decodedAuthority.periodAmount).toString(16),\n );\n await this.#messenger.call(\n 'AuthenticatedUserStorageService:createDelegation',\n {\n signedDelegation,\n metadata: {\n delegationHash,\n chainIdHex: request.chainId,\n allowance,\n tokenSymbol: config.token.symbol,\n tokenAddress: config.token.address,\n type: CASH_SUBSCRIPTION_DELEGATION_TYPE,\n },\n },\n );\n await this.#createIntent({\n account: request.payerAddress,\n chainId: request.chainId,\n delegationHash,\n allowance,\n tokenSymbol: config.token.symbol,\n tokenAddress: config.token.address,\n });\n await this.#assertIntentActive(request.payerAddress, delegationHash);\n return delegationHash;\n }\n\n async #assertIntentActive(account: Hex, delegationHash: Hex): Promise<void> {\n const intents = await this.#messenger.call(\n 'ChompApiService:getIntentsByAddress',\n account,\n );\n const intent = intents.find((candidate) =>\n equalsIgnoreCase(candidate.delegationHash, delegationHash),\n );\n if (intent?.status !== 'active') {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ChompIntentNotActive,\n );\n }\n }\n\n async #verifySignedPaymentDelegation(\n signedDelegation: SignedSubscriptionDelegation,\n expectedDelegationHash: Hex,\n chainId: Hex,\n ): Promise<void> {\n const localHash = hashDelegation({\n ...signedDelegation,\n salt: BigInt(signedDelegation.salt),\n });\n if (!equalsIgnoreCase(localHash, expectedDelegationHash)) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ReusableDelegationInvalid,\n );\n }\n\n const verifyResult = await this.#messenger.call(\n 'ChompApiService:verifyDelegation',\n { signedDelegation, chainId },\n );\n if (!verifyResult.valid) {\n throw new Error(\n `${SubscriptionDelegationServiceErrorMessage.ChompRejectedDelegation}: ${\n verifyResult.errors?.join(', ') ?? 'unknown error'\n }`,\n );\n }\n if (!verifyResult.delegationHash) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ChompMissingDelegationHash,\n );\n }\n if (\n !equalsIgnoreCase(verifyResult.delegationHash, expectedDelegationHash)\n ) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ChompDelegationHashMismatch,\n );\n }\n }\n\n /**\n * Prepares a cash-subscription delegation and returns its hash.\n *\n * Reuses a stored AUS delegation that matches the semantic fingerprint when\n * one exists (ensuring a CHOMP intent is active for its hash, unless\n * `skipChompInteractions` is true). Reuse classifies period `startDate` as\n * trial-deferred (`> now`) vs immediately redeemable, matching creation.\n * When several records match, the latest period `startDate` is reused\n * so a `forceNew` replacement is preferred over an older equivalent\n * permission.\n * If there is no match, builds, signs, optionally verifies with CHOMP,\n * persists, and optionally registers a new delegation.\n *\n * When `skipChompInteractions` is true, CHOMP verify and intent calls are\n * skipped; the returned hash is computed locally.\n *\n * @param request - Authoritative pricing and payer details for the delegation.\n * @param forceNew - Whether to create a replacement instead of reusing a\n * matching stored delegation.\n * @returns The delegation hash (CHOMP-verified unless skipped) and whether it\n * was created or reused.\n */\n async prepareDelegation(\n request: PrepareSubscriptionDelegationRequest,\n forceNew = false,\n ): Promise<PreparedSubscriptionDelegation> {\n if (request.product !== PRODUCT_TYPES.MONEY_ACCOUNT_PLUS) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.UnsupportedProduct,\n );\n }\n\n const skipChomp = Boolean(request.skipChompInteractions);\n\n const {\n chainId,\n delegateAddress,\n paymentAddress,\n enforcers,\n price,\n token,\n } = await this.#resolveConfiguration(\n request.product,\n request.recurringInterval,\n );\n\n if (request.checkBalance) {\n const { hasSufficientBalance } = await this.#compareMoneyAccountBalance(\n request.payerAddress,\n price,\n );\n if (!hasSufficientBalance) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.InsufficientBalance,\n );\n }\n }\n\n const periodAmount = calculatePeriodAmount({\n unitAmount: price.unitAmount,\n unitDecimals: price.unitDecimals,\n tokenDecimals: token.decimals,\n });\n const periodDuration = getPeriodDuration(request.recurringInterval);\n const nowSeconds = Math.floor(Date.now() / 1000);\n const startDate = getDelegationStartDate({\n nowSeconds,\n trialPeriodDays: request.isTrialRequested\n ? price.trialPeriodDays\n : undefined,\n });\n const isTrialDeferred = startDate > nowSeconds;\n\n const reusable = forceNew\n ? undefined\n : await this.#findReusableDelegation({\n request,\n chainId,\n delegateAddress,\n paymentAddress,\n tokenAddress: token.address,\n periodAmount,\n periodDuration,\n nowSeconds,\n isTrialDeferred,\n enforcers,\n });\n if (reusable) {\n if (!skipChomp) {\n await this.#ensureIntent({\n account: request.payerAddress,\n chainId,\n delegationHash: reusable.metadata.delegationHash,\n allowance: reusable.metadata.allowance,\n tokenSymbol: reusable.metadata.tokenSymbol,\n tokenAddress: reusable.metadata.tokenAddress,\n });\n }\n return {\n delegationHash: reusable.metadata.delegationHash,\n disposition: 'reused',\n };\n }\n\n const unsigned = buildUnsignedSubscriptionDelegation({\n delegateAddress,\n delegatorAddress: request.payerAddress,\n recipientAddress: paymentAddress,\n enforcers,\n tokenAddress: token.address,\n periodAmount,\n periodDuration,\n startDate,\n });\n\n const signature = (await this.#messenger.call(\n 'DelegationController:signDelegation',\n { delegation: unsigned, chainId },\n )) as Hex;\n\n const signedDelegation = { ...unsigned, signature };\n\n const delegationHash = hashDelegation({\n ...unsigned,\n salt: BigInt(unsigned.salt),\n signature,\n });\n\n if (!skipChomp) {\n const verifyResult = await this.#messenger.call(\n 'ChompApiService:verifyDelegation',\n {\n signedDelegation,\n chainId,\n },\n );\n\n if (!verifyResult.valid) {\n throw new Error(\n `${SubscriptionDelegationServiceErrorMessage.ChompRejectedDelegation}: ${\n verifyResult.errors?.join(', ') ?? 'unknown error'\n }`,\n );\n }\n\n if (!verifyResult.delegationHash) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ChompMissingDelegationHash,\n );\n }\n if (!equalsIgnoreCase(verifyResult.delegationHash, delegationHash)) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ChompDelegationHashMismatch,\n );\n }\n }\n\n const allowance: Hex = add0x(periodAmount.toString(16));\n\n await this.#messenger.call(\n 'AuthenticatedUserStorageService:createDelegation',\n {\n signedDelegation,\n metadata: {\n delegationHash,\n chainIdHex: chainId,\n allowance,\n tokenSymbol: token.symbol,\n tokenAddress: token.address,\n type: CASH_SUBSCRIPTION_DELEGATION_TYPE,\n },\n },\n );\n\n if (!skipChomp) {\n await this.#createIntent({\n account: request.payerAddress,\n chainId,\n delegationHash,\n allowance,\n tokenSymbol: token.symbol,\n tokenAddress: token.address,\n });\n }\n\n return {\n delegationHash,\n disposition: 'created',\n };\n }\n\n async #findReusableDelegation({\n request,\n chainId,\n delegateAddress,\n paymentAddress,\n tokenAddress,\n periodAmount,\n periodDuration,\n nowSeconds,\n isTrialDeferred,\n enforcers,\n }: {\n request: PrepareSubscriptionDelegationRequest;\n chainId: Hex;\n delegateAddress: Hex;\n paymentAddress: Hex;\n tokenAddress: Hex;\n periodAmount: bigint;\n periodDuration: number;\n nowSeconds: number;\n isTrialDeferred: boolean;\n enforcers: SubscriptionDelegationEnforcers;\n }): Promise<DelegationResponse | undefined> {\n const matches = makeMatchesSubscriptionDelegation({\n delegatorAddress: request.payerAddress,\n delegateAddress,\n recipientAddress: paymentAddress,\n chainId,\n tokenAddress,\n periodAmount,\n periodDuration,\n nowSeconds,\n isTrialDeferred,\n enforcers,\n });\n\n const existingDelegations = await this.#messenger.call(\n 'AuthenticatedUserStorageService:listDelegations',\n );\n\n return pickLatestMatchingSubscriptionDelegation(\n existingDelegations.filter(matches),\n enforcers,\n );\n }\n\n async #resolveConfiguration(\n product: ProductType,\n recurringInterval: RecurringInterval,\n ): Promise<ResolvedSubscriptionDelegationConfig> {\n const { remoteFeatureFlags } = this.#messenger.call(\n 'RemoteFeatureFlagController:getState',\n );\n const vaultConfig = getMoneyAccountVaultConfig(remoteFeatureFlags);\n if (!vaultConfig) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.MissingMoneyAccountVaultConfig,\n );\n }\n\n const { chainId } = vaultConfig;\n const enforcers = resolveEnforcers(chainId);\n const pricing = await this.#messenger.call(\n 'SubscriptionController:getPricing',\n );\n const price = pricing.products\n .find((entry) => entry.name === product)\n ?.prices?.find((entry) => entry.interval === recurringInterval);\n const paymentMethod = pricing.paymentMethods.find(\n (entry): entry is PricingCryptoPaymentMethod =>\n entry.type === PAYMENT_TYPES.byCrypto &&\n entry.cryptoAuthMethod === CRYPTO_AUTH_METHODS.DELEGATION &&\n entry.products?.includes(product) === true,\n );\n const chain = paymentMethod?.chains?.find(\n (entry) => entry.chainId === chainId,\n );\n const token = chain?.tokens[0];\n if (!price || !chain?.delegateAddress || !token) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.PricingConfigurationNotFound,\n );\n }\n\n return {\n chainId,\n delegateAddress: chain.delegateAddress,\n delegationManager:\n DELEGATOR_CONTRACTS[DELEGATION_FRAMEWORK_VERSION][hexToNumber(chainId)]\n .DelegationManager,\n paymentAddress: chain.paymentAddress,\n enforcers,\n musdAddress: getMoneyAccountDepositAssetAddress(chainId),\n price,\n token,\n };\n }\n\n /**\n * Ensures an active CHOMP intent exists for the given delegation hash,\n * registering one when missing or revoked.\n *\n * @param params - Intent identity and metadata.\n * @param params.account - Delegator / payer address.\n * @param params.chainId - Chain ID of the delegation.\n * @param params.delegationHash - Hash of the stored delegation.\n * @param params.allowance - Period allowance stored with the delegation.\n * @param params.tokenSymbol - Payment token symbol.\n * @param params.tokenAddress - Payment token address.\n */\n async #ensureIntent(params: SubscriptionIntentParams): Promise<void> {\n const existingIntents = await this.#messenger.call(\n 'ChompApiService:getIntentsByAddress',\n params.account,\n );\n\n const hasActiveIntent = existingIntents.some(\n (intent) =>\n equalsIgnoreCase(intent.delegationHash, params.delegationHash) &&\n intent.status === 'active',\n );\n\n if (hasActiveIntent) {\n return;\n }\n\n await this.#createIntent(params);\n }\n\n async #createIntent(params: SubscriptionIntentParams): Promise<void> {\n await this.#messenger.call('ChompApiService:createIntents', [\n {\n account: params.account,\n delegationHash: params.delegationHash,\n chainId: params.chainId,\n metadata: {\n allowance: params.allowance,\n tokenSymbol: params.tokenSymbol,\n tokenAddress: params.tokenAddress,\n type: CASH_SUBSCRIPTION_DELEGATION_TYPE,\n },\n },\n ]);\n }\n}\n"]}
1
+ {"version":3,"file":"SubscriptionDelegationService.js","sourceRoot":"","sources":["../../src/subscription-delegation/SubscriptionDelegationService.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n DelegationResponse,\n AuthenticatedUserStorageServiceCreateDelegationAction,\n AuthenticatedUserStorageServiceListDelegationsAction,\n} from '@metamask/authenticated-user-storage';\nimport type {\n ChompApiServiceCreateIntentsAction,\n ChompApiServiceGetIntentsByAddressAction,\n ChompApiServiceVerifyDelegationAction,\n} from '@metamask/chomp-api-service';\nimport type { DelegationControllerSignDelegationAction } from '@metamask/delegation-controller';\nimport { hashDelegation } from '@metamask/delegation-core';\nimport { DELEGATOR_CONTRACTS } from '@metamask/delegation-deployments';\nimport type { Messenger } from '@metamask/messenger';\nimport type { MoneyAccountBalanceServiceFetchBalanceWithFallbackAction } from '@metamask/money-account-balance-service';\nimport type { MoneyAccountUpgradeControllerForceUpgradeAccountAction } from '@metamask/money-account-upgrade-controller';\nimport {\n getMoneyAccountVaultConfig,\n MUSD_DECIMALS,\n} from '@metamask/money-account-utils';\nimport type { RemoteFeatureFlagControllerGetStateAction } from '@metamask/remote-feature-flag-controller';\nimport { add0x, hexToNumber } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n ACTIVE_SUBSCRIPTION_STATUSES,\n SubscriptionControllerErrorMessage,\n SubscriptionDelegationServiceErrorMessage,\n} from '../constants.js';\nimport type {\n SubscriptionControllerGetPricingAction,\n SubscriptionControllerGetSubscriptionsAction,\n SubscriptionControllerIsUserEligibleForTrialAction,\n SubscriptionControllerStartSubscriptionWithCryptoAction,\n} from '../SubscriptionController-method-action-types.js';\nimport type { SubscriptionControllerGetStateAction } from '../SubscriptionController.js';\nimport { CRYPTO_AUTH_METHODS, PAYMENT_TYPES, PRODUCT_TYPES } from '../types.js';\nimport type {\n ProductPrice,\n ProductType,\n PricingCryptoPaymentMethod,\n RecurringInterval,\n Subscription,\n TokenPaymentInfo,\n} from '../types.js';\nimport {\n assertPositiveInteger,\n calculatePeriodAmount,\n getDelegationStartDate,\n getPeriodDuration,\n} from './amount.js';\nimport { buildUnsignedSubscriptionDelegation } from './caveats.js';\nimport {\n equalsIgnoreCase,\n makeMatchesSubscriptionDelegation,\n pickLatestMatchingSubscriptionDelegation,\n} from './fingerprint.js';\nimport type { SubscriptionDelegationServiceMethodActions } from './SubscriptionDelegationService-method-action-types.js';\nimport {\n buildDelegationTypedData,\n decodeSubscriptionAuthority,\n} from './typed-data.js';\nimport type {\n MoneyAccountBalanceCheckRequest,\n MoneyAccountBalanceCheckResult,\n PrepareSubscriptionDelegationRequest,\n PreparedSubscriptionPermission,\n PreparedSubscriptionDelegation,\n SignedSubscriptionDelegation,\n StartSubscriptionWithDelegationRequest,\n StartSubscriptionWithDelegationResult,\n SubscriptionDelegationEnforcers,\n UnsignedSubscriptionDelegation,\n} from './types.js';\nimport { CASH_SUBSCRIPTION_DELEGATION_TYPE } from './types.js';\n\n/**\n * The name of the {@link SubscriptionDelegationService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'SubscriptionDelegationService';\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'prepareDelegation',\n 'checkMoneyAccountBalance',\n 'startSubscriptionWithDelegation',\n] as const;\n\nconst DELEGATION_FRAMEWORK_VERSION = '1.3.0';\n\nfunction resolveEnforcers(chainId: Hex): SubscriptionDelegationEnforcers {\n const contracts =\n DELEGATOR_CONTRACTS[DELEGATION_FRAMEWORK_VERSION]?.[hexToNumber(chainId)];\n\n if (\n !contracts?.ERC20PeriodTransferEnforcer ||\n !contracts.AllowedCalldataEnforcer\n ) {\n throw new Error(\n `${SubscriptionDelegationServiceErrorMessage.DelegationContractsNotFound}: ${chainId}`,\n );\n }\n\n return {\n erc20TokenPeriodTransfer: contracts.ERC20PeriodTransferEnforcer,\n allowedCalldata: contracts.AllowedCalldataEnforcer,\n };\n}\n\nfunction removeDelegationSignature(\n delegation: SignedSubscriptionDelegation,\n): UnsignedSubscriptionDelegation {\n const { signature: _signature, ...unsignedDelegation } = delegation;\n return unsignedDelegation;\n}\n\n/**\n * Actions that {@link SubscriptionDelegationService} exposes to other consumers.\n */\nexport type SubscriptionDelegationServiceActions =\n SubscriptionDelegationServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link SubscriptionDelegationServiceMessenger} calls.\n */\ntype AllowedActions =\n | AuthenticatedUserStorageServiceListDelegationsAction\n | AuthenticatedUserStorageServiceCreateDelegationAction\n | ChompApiServiceVerifyDelegationAction\n | ChompApiServiceCreateIntentsAction\n | ChompApiServiceGetIntentsByAddressAction\n | DelegationControllerSignDelegationAction\n | MoneyAccountUpgradeControllerForceUpgradeAccountAction\n | MoneyAccountBalanceServiceFetchBalanceWithFallbackAction\n | RemoteFeatureFlagControllerGetStateAction\n | SubscriptionControllerGetStateAction\n | SubscriptionControllerGetPricingAction\n | SubscriptionControllerGetSubscriptionsAction\n | SubscriptionControllerIsUserEligibleForTrialAction\n | SubscriptionControllerStartSubscriptionWithCryptoAction;\n\n/**\n * Events that {@link SubscriptionDelegationService} exposes to other consumers.\n */\nexport type SubscriptionDelegationServiceEvents = never;\n\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link SubscriptionDelegationService}.\n */\nexport type SubscriptionDelegationServiceMessenger = Messenger<\n typeof serviceName,\n SubscriptionDelegationServiceActions | AllowedActions,\n SubscriptionDelegationServiceEvents | AllowedEvents\n>;\n\n/**\n * Options for constructing {@link SubscriptionDelegationService}.\n */\nexport type SubscriptionDelegationServiceOptions = {\n messenger: SubscriptionDelegationServiceMessenger;\n};\n\ntype SubscriptionIntentParams = {\n account: Hex;\n chainId: Hex;\n delegationHash: Hex;\n allowance: Hex;\n tokenSymbol: string;\n tokenAddress: Hex;\n};\n\ntype ResolvedSubscriptionDelegationConfig = {\n chainId: Hex;\n delegateAddress: Hex;\n delegationManager: Hex;\n paymentAddress: Hex;\n enforcers: SubscriptionDelegationEnforcers;\n price: ProductPrice;\n token: TokenPaymentInfo;\n};\n\n/**\n * Stateless orchestrator for cash-subscription delegation setup.\n *\n * Owns the workflow: size periodic caveats → sign → CHOMP verify → persist to\n * Authenticated User Storage → register CHOMP intent. Returns a verified\n * `delegationHash` for `SubscriptionController.startSubscriptionWithCrypto`.\n *\n * Pass `skipChompInteractions: true` to skip CHOMP verify and intent\n * registration and return a locally computed delegation hash.\n *\n * Each call resolves the Money Account chain from remote feature flags, then\n * resolves its price, payment token, and delegate from `SubscriptionController`\n * pricing. The pricing `delegateAddress` is used as the delegation `delegate`.\n *\n * Does not own subscription state; `SubscriptionController` does not depend on\n * this service. Only Money Account Plus is supported.\n */\nexport class SubscriptionDelegationService {\n readonly name: typeof serviceName = serviceName;\n\n readonly #messenger: SubscriptionDelegationServiceMessenger;\n\n constructor(options: SubscriptionDelegationServiceOptions) {\n this.#messenger = options.messenger;\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Checks whether the Money Account holds enough convertible mUSD value to\n * cover pricing `unitAmount × minBillingCyclesForBalance`.\n *\n * @param request - Payer address and pricing amount fields.\n * @returns Balance comparison in mUSD base units (6 decimals).\n */\n async checkMoneyAccountBalance(\n request: MoneyAccountBalanceCheckRequest,\n ): Promise<MoneyAccountBalanceCheckResult> {\n const { price } = await this.#resolveConfiguration(\n request.product,\n request.recurringInterval,\n );\n return this.#compareMoneyAccountBalance(request.payerAddress, price);\n }\n\n async #compareMoneyAccountBalance(\n payerAddress: Hex,\n price: ProductPrice,\n ): Promise<MoneyAccountBalanceCheckResult> {\n assertPositiveInteger(\n price.minBillingCyclesForBalance,\n SubscriptionDelegationServiceErrorMessage.InvalidMinimumFundingCycles,\n );\n\n const periodAmount = calculatePeriodAmount({\n unitAmount: price.unitAmount,\n unitDecimals: price.unitDecimals,\n tokenDecimals: MUSD_DECIMALS,\n });\n const requiredBalance =\n periodAmount * BigInt(price.minBillingCyclesForBalance);\n\n const { totalBalance } = await this.#messenger.call(\n 'MoneyAccountBalanceService:fetchBalanceWithFallback',\n payerAddress,\n );\n\n return {\n hasSufficientBalance: BigInt(totalBalance) >= requiredBalance,\n balance: totalBalance,\n requiredBalance: requiredBalance.toString(),\n };\n }\n\n /**\n * Runs the complete Money Account subscription checkout authorization flow.\n *\n * Subscriptions are refreshed first. An active subscription for the product\n * is rejected before Money Account upgrade, delegation signing, persistence,\n * or CHOMP registration.\n *\n * The caller must obtain user consent and initiate funding before calling.\n * `MoneyAccountUpgradeController` ensures the Money Account vault\n * delegations and CHOMP intents exist. The Subscription API validates those\n * delegations and the Money Account balance server-side. No payment\n * delegation signing, persistence, or intent mutation occurs before the\n * account is upgraded.\n *\n * @param request - Product selection and Money Account identity.\n * @returns The result from `SubscriptionController:startSubscriptionWithCrypto`.\n */\n async startSubscriptionWithDelegation(\n request: StartSubscriptionWithDelegationRequest,\n ): Promise<StartSubscriptionWithDelegationResult> {\n if (request.product !== PRODUCT_TYPES.MONEY_ACCOUNT_PLUS) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.UnsupportedProduct,\n );\n }\n\n const config = await this.#resolveConfiguration(\n request.product,\n request.recurringInterval,\n );\n if (!equalsIgnoreCase(request.chainId, config.chainId)) {\n throw new Error(SubscriptionDelegationServiceErrorMessage.ChainMismatch);\n }\n const subscriptions = await this.#messenger.call(\n 'SubscriptionController:getSubscriptions',\n );\n this.#assertUserNotSubscribed(subscriptions, request.product);\n const isEligibleForTrial = await this.#messenger.call(\n 'SubscriptionController:isUserEligibleForTrial',\n request.product,\n );\n const isTrialRequested =\n config.price.trialPeriodDays > 0 && isEligibleForTrial;\n\n await this.#messenger.call(\n 'MoneyAccountUpgradeController:forceUpgradeAccount',\n request.payerAddress,\n );\n\n const paymentPermission = await this.#preparePaymentPermission(\n request,\n config,\n isTrialRequested,\n );\n const paymentDelegation = await this.#signPaymentPermissionIfRequired(\n paymentPermission,\n config,\n );\n const paymentDelegationHash = await this.#commitPaymentPermission({\n request,\n paymentPermission,\n paymentDelegation,\n config,\n });\n return await this.#messenger.call(\n 'SubscriptionController:startSubscriptionWithCrypto',\n {\n products: [request.product],\n isTrialRequested,\n recurringInterval: request.recurringInterval,\n billingCycles: config.price.minBillingCycles,\n chainId: request.chainId,\n payerAddress: request.payerAddress,\n tokenSymbol: config.token.symbol,\n cryptoAuthMethod: CRYPTO_AUTH_METHODS.DELEGATION,\n delegationHash: paymentDelegationHash,\n // Reject if eligibility changed during checkout, because the signed\n // delegation start date was derived from the original trial state.\n // This local guard is removed before the backend request.\n assertTrialEligibility: true,\n },\n );\n }\n\n /**\n * Rejects when the refreshed list already contains an active subscription\n * for the product. Active includes `active`, `trialing`, and `provisional`.\n *\n * @param subscriptions - Subscriptions returned by the latest refresh.\n * @param product - Product the caller is trying to start.\n */\n #assertUserNotSubscribed(\n subscriptions: Subscription[],\n product: ProductType,\n ): void {\n const alreadySubscribed = subscriptions.some(\n (subscription) =>\n ACTIVE_SUBSCRIPTION_STATUSES.includes(subscription.status) &&\n subscription.products.some((entry) => entry.name === product),\n );\n if (alreadySubscribed) {\n throw new Error(SubscriptionControllerErrorMessage.UserAlreadySubscribed);\n }\n }\n\n async #preparePaymentPermission(\n request: StartSubscriptionWithDelegationRequest,\n config: ResolvedSubscriptionDelegationConfig,\n isTrialRequested: boolean,\n ): Promise<PreparedSubscriptionPermission> {\n const periodAmount = calculatePeriodAmount({\n unitAmount: config.price.unitAmount,\n unitDecimals: config.price.unitDecimals,\n tokenDecimals: config.token.decimals,\n });\n const periodDuration = getPeriodDuration(request.recurringInterval);\n const nowSeconds = Math.floor(Date.now() / 1000);\n const startDate = getDelegationStartDate({\n nowSeconds,\n trialPeriodDays: isTrialRequested\n ? config.price.trialPeriodDays\n : undefined,\n });\n const matches = makeMatchesSubscriptionDelegation({\n delegatorAddress: request.payerAddress,\n delegateAddress: config.delegateAddress,\n chainId: request.chainId,\n recipientAddress: config.paymentAddress,\n tokenAddress: config.token.address,\n periodAmount,\n periodDuration,\n nowSeconds,\n isTrialDeferred: startDate > nowSeconds,\n enforcers: config.enforcers,\n });\n const reusable = pickLatestMatchingSubscriptionDelegation(\n (\n await this.#messenger.call(\n 'AuthenticatedUserStorageService:listDelegations',\n )\n ).filter(matches),\n config.enforcers,\n );\n const delegation = reusable\n ? removeDelegationSignature(reusable.signedDelegation)\n : buildUnsignedSubscriptionDelegation({\n delegateAddress: config.delegateAddress,\n delegatorAddress: request.payerAddress,\n enforcers: config.enforcers,\n recipientAddress: config.paymentAddress,\n tokenAddress: config.token.address,\n periodAmount,\n periodDuration,\n startDate,\n });\n const typedData = buildDelegationTypedData({\n delegation,\n chainId: request.chainId,\n delegationManager: config.delegationManager,\n });\n\n return {\n id: CASH_SUBSCRIPTION_DELEGATION_TYPE,\n owner: 'subscription',\n disposition: reusable ? 'reused' : 'new',\n delegation,\n typedData,\n decodedAuthority: decodeSubscriptionAuthority(\n delegation,\n config.enforcers,\n ),\n ...(reusable\n ? { existingDelegationHash: reusable.metadata.delegationHash }\n : {}),\n };\n }\n\n async #signPaymentPermissionIfRequired(\n permission: PreparedSubscriptionPermission,\n config: ResolvedSubscriptionDelegationConfig,\n ): Promise<SignedSubscriptionDelegation | undefined> {\n if (permission.disposition === 'reused') {\n return undefined;\n }\n const signature = (await this.#messenger.call(\n 'DelegationController:signDelegation',\n {\n delegation: permission.delegation,\n chainId: config.chainId,\n },\n )) as Hex;\n return { ...permission.delegation, signature };\n }\n\n async #commitPaymentPermission({\n request,\n paymentPermission,\n paymentDelegation,\n config,\n }: {\n request: StartSubscriptionWithDelegationRequest;\n paymentPermission: PreparedSubscriptionPermission;\n paymentDelegation?: SignedSubscriptionDelegation;\n config: ResolvedSubscriptionDelegationConfig;\n }): Promise<Hex> {\n if (paymentPermission.disposition === 'reused') {\n const delegationHash = paymentPermission.existingDelegationHash as Hex;\n const storedDelegation = (\n await this.#messenger.call(\n 'AuthenticatedUserStorageService:listDelegations',\n )\n ).find(({ metadata }) =>\n equalsIgnoreCase(metadata.delegationHash, delegationHash),\n );\n if (!storedDelegation) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ReusableDelegationInvalid,\n );\n }\n await this.#verifySignedPaymentDelegation(\n storedDelegation.signedDelegation,\n delegationHash,\n request.chainId,\n );\n await this.#ensureIntent({\n account: request.payerAddress,\n chainId: request.chainId,\n delegationHash,\n allowance: add0x(\n BigInt(paymentPermission.decodedAuthority.periodAmount).toString(16),\n ),\n tokenSymbol: config.token.symbol,\n tokenAddress: config.token.address,\n });\n await this.#assertIntentActive(request.payerAddress, delegationHash);\n return delegationHash;\n }\n\n const signedDelegation = paymentDelegation as SignedSubscriptionDelegation;\n const delegationHash = hashDelegation({\n ...signedDelegation,\n salt: BigInt(signedDelegation.salt),\n });\n await this.#verifySignedPaymentDelegation(\n signedDelegation,\n delegationHash,\n request.chainId,\n );\n\n const allowance = add0x(\n BigInt(paymentPermission.decodedAuthority.periodAmount).toString(16),\n );\n await this.#messenger.call(\n 'AuthenticatedUserStorageService:createDelegation',\n {\n signedDelegation,\n metadata: {\n delegationHash,\n chainIdHex: request.chainId,\n allowance,\n tokenSymbol: config.token.symbol,\n tokenAddress: config.token.address,\n type: CASH_SUBSCRIPTION_DELEGATION_TYPE,\n },\n },\n );\n await this.#createIntent({\n account: request.payerAddress,\n chainId: request.chainId,\n delegationHash,\n allowance,\n tokenSymbol: config.token.symbol,\n tokenAddress: config.token.address,\n });\n await this.#assertIntentActive(request.payerAddress, delegationHash);\n return delegationHash;\n }\n\n async #assertIntentActive(account: Hex, delegationHash: Hex): Promise<void> {\n const intents = await this.#messenger.call(\n 'ChompApiService:getIntentsByAddress',\n account,\n );\n const intent = intents.find((candidate) =>\n equalsIgnoreCase(candidate.delegationHash, delegationHash),\n );\n if (intent?.status !== 'active') {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ChompIntentNotActive,\n );\n }\n }\n\n async #verifySignedPaymentDelegation(\n signedDelegation: SignedSubscriptionDelegation,\n expectedDelegationHash: Hex,\n chainId: Hex,\n ): Promise<void> {\n const localHash = hashDelegation({\n ...signedDelegation,\n salt: BigInt(signedDelegation.salt),\n });\n if (!equalsIgnoreCase(localHash, expectedDelegationHash)) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ReusableDelegationInvalid,\n );\n }\n\n const verifyResult = await this.#messenger.call(\n 'ChompApiService:verifyDelegation',\n { signedDelegation, chainId },\n );\n if (!verifyResult.valid) {\n throw new Error(\n `${SubscriptionDelegationServiceErrorMessage.ChompRejectedDelegation}: ${\n verifyResult.errors?.join(', ') ?? 'unknown error'\n }`,\n );\n }\n if (!verifyResult.delegationHash) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ChompMissingDelegationHash,\n );\n }\n if (\n !equalsIgnoreCase(verifyResult.delegationHash, expectedDelegationHash)\n ) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ChompDelegationHashMismatch,\n );\n }\n }\n\n /**\n * Prepares a cash-subscription delegation and returns its hash.\n *\n * Reuses a stored AUS delegation that matches the semantic fingerprint when\n * one exists (ensuring a CHOMP intent is active for its hash, unless\n * `skipChompInteractions` is true). Reuse classifies period `startDate` as\n * trial-deferred (`> now`) vs immediately redeemable, matching creation.\n * When several records match, the latest period `startDate` is reused\n * so a `forceNew` replacement is preferred over an older equivalent\n * permission.\n * If there is no match, builds, signs, optionally verifies with CHOMP,\n * persists, and optionally registers a new delegation.\n *\n * When `skipChompInteractions` is true, CHOMP verify and intent calls are\n * skipped; the returned hash is computed locally.\n *\n * @param request - Authoritative pricing and payer details for the delegation.\n * @param forceNew - Whether to create a replacement instead of reusing a\n * matching stored delegation.\n * @returns The delegation hash (CHOMP-verified unless skipped) and whether it\n * was created or reused.\n */\n async prepareDelegation(\n request: PrepareSubscriptionDelegationRequest,\n forceNew = false,\n ): Promise<PreparedSubscriptionDelegation> {\n if (request.product !== PRODUCT_TYPES.MONEY_ACCOUNT_PLUS) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.UnsupportedProduct,\n );\n }\n\n const skipChomp = Boolean(request.skipChompInteractions);\n\n const {\n chainId,\n delegateAddress,\n paymentAddress,\n enforcers,\n price,\n token,\n } = await this.#resolveConfiguration(\n request.product,\n request.recurringInterval,\n );\n\n if (request.checkBalance) {\n const { hasSufficientBalance } = await this.#compareMoneyAccountBalance(\n request.payerAddress,\n price,\n );\n if (!hasSufficientBalance) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.InsufficientBalance,\n );\n }\n }\n\n const periodAmount = calculatePeriodAmount({\n unitAmount: price.unitAmount,\n unitDecimals: price.unitDecimals,\n tokenDecimals: token.decimals,\n });\n const periodDuration = getPeriodDuration(request.recurringInterval);\n const nowSeconds = Math.floor(Date.now() / 1000);\n const startDate = getDelegationStartDate({\n nowSeconds,\n trialPeriodDays: request.isTrialRequested\n ? price.trialPeriodDays\n : undefined,\n });\n const isTrialDeferred = startDate > nowSeconds;\n\n const reusable = forceNew\n ? undefined\n : await this.#findReusableDelegation({\n request,\n chainId,\n delegateAddress,\n paymentAddress,\n tokenAddress: token.address,\n periodAmount,\n periodDuration,\n nowSeconds,\n isTrialDeferred,\n enforcers,\n });\n if (reusable) {\n if (!skipChomp) {\n await this.#ensureIntent({\n account: request.payerAddress,\n chainId,\n delegationHash: reusable.metadata.delegationHash,\n allowance: reusable.metadata.allowance,\n tokenSymbol: reusable.metadata.tokenSymbol,\n tokenAddress: reusable.metadata.tokenAddress,\n });\n }\n return {\n delegationHash: reusable.metadata.delegationHash,\n disposition: 'reused',\n };\n }\n\n const unsigned = buildUnsignedSubscriptionDelegation({\n delegateAddress,\n delegatorAddress: request.payerAddress,\n recipientAddress: paymentAddress,\n enforcers,\n tokenAddress: token.address,\n periodAmount,\n periodDuration,\n startDate,\n });\n\n const signature = (await this.#messenger.call(\n 'DelegationController:signDelegation',\n { delegation: unsigned, chainId },\n )) as Hex;\n\n const signedDelegation = { ...unsigned, signature };\n\n const delegationHash = hashDelegation({\n ...unsigned,\n salt: BigInt(unsigned.salt),\n signature,\n });\n\n if (!skipChomp) {\n const verifyResult = await this.#messenger.call(\n 'ChompApiService:verifyDelegation',\n {\n signedDelegation,\n chainId,\n },\n );\n\n if (!verifyResult.valid) {\n throw new Error(\n `${SubscriptionDelegationServiceErrorMessage.ChompRejectedDelegation}: ${\n verifyResult.errors?.join(', ') ?? 'unknown error'\n }`,\n );\n }\n\n if (!verifyResult.delegationHash) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ChompMissingDelegationHash,\n );\n }\n if (!equalsIgnoreCase(verifyResult.delegationHash, delegationHash)) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.ChompDelegationHashMismatch,\n );\n }\n }\n\n const allowance: Hex = add0x(periodAmount.toString(16));\n\n await this.#messenger.call(\n 'AuthenticatedUserStorageService:createDelegation',\n {\n signedDelegation,\n metadata: {\n delegationHash,\n chainIdHex: chainId,\n allowance,\n tokenSymbol: token.symbol,\n tokenAddress: token.address,\n type: CASH_SUBSCRIPTION_DELEGATION_TYPE,\n },\n },\n );\n\n if (!skipChomp) {\n await this.#createIntent({\n account: request.payerAddress,\n chainId,\n delegationHash,\n allowance,\n tokenSymbol: token.symbol,\n tokenAddress: token.address,\n });\n }\n\n return {\n delegationHash,\n disposition: 'created',\n };\n }\n\n async #findReusableDelegation({\n request,\n chainId,\n delegateAddress,\n paymentAddress,\n tokenAddress,\n periodAmount,\n periodDuration,\n nowSeconds,\n isTrialDeferred,\n enforcers,\n }: {\n request: PrepareSubscriptionDelegationRequest;\n chainId: Hex;\n delegateAddress: Hex;\n paymentAddress: Hex;\n tokenAddress: Hex;\n periodAmount: bigint;\n periodDuration: number;\n nowSeconds: number;\n isTrialDeferred: boolean;\n enforcers: SubscriptionDelegationEnforcers;\n }): Promise<DelegationResponse | undefined> {\n const matches = makeMatchesSubscriptionDelegation({\n delegatorAddress: request.payerAddress,\n delegateAddress,\n recipientAddress: paymentAddress,\n chainId,\n tokenAddress,\n periodAmount,\n periodDuration,\n nowSeconds,\n isTrialDeferred,\n enforcers,\n });\n\n const existingDelegations = await this.#messenger.call(\n 'AuthenticatedUserStorageService:listDelegations',\n );\n\n return pickLatestMatchingSubscriptionDelegation(\n existingDelegations.filter(matches),\n enforcers,\n );\n }\n\n async #resolveConfiguration(\n product: ProductType,\n recurringInterval: RecurringInterval,\n ): Promise<ResolvedSubscriptionDelegationConfig> {\n const { remoteFeatureFlags } = this.#messenger.call(\n 'RemoteFeatureFlagController:getState',\n );\n const vaultConfig = getMoneyAccountVaultConfig(remoteFeatureFlags);\n if (!vaultConfig) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.MissingMoneyAccountVaultConfig,\n );\n }\n\n const { chainId } = vaultConfig;\n const enforcers = resolveEnforcers(chainId);\n const pricing = await this.#messenger.call(\n 'SubscriptionController:getPricing',\n );\n const price = pricing.products\n .find((entry) => entry.name === product)\n ?.prices?.find((entry) => entry.interval === recurringInterval);\n const paymentMethod = pricing.paymentMethods.find(\n (entry): entry is PricingCryptoPaymentMethod =>\n entry.type === PAYMENT_TYPES.byCrypto &&\n entry.cryptoAuthMethod === CRYPTO_AUTH_METHODS.DELEGATION &&\n entry.products?.includes(product) === true,\n );\n const chain = paymentMethod?.chains?.find(\n (entry) => entry.chainId === chainId,\n );\n const token = chain?.tokens[0];\n if (!price || !chain?.delegateAddress || !token) {\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.PricingConfigurationNotFound,\n );\n }\n\n return {\n chainId,\n delegateAddress: chain.delegateAddress,\n delegationManager:\n DELEGATOR_CONTRACTS[DELEGATION_FRAMEWORK_VERSION][hexToNumber(chainId)]\n .DelegationManager,\n paymentAddress: chain.paymentAddress,\n enforcers,\n price,\n token,\n };\n }\n\n /**\n * Ensures an active CHOMP intent exists for the given delegation hash,\n * registering one when missing or revoked.\n *\n * @param params - Intent identity and metadata.\n * @param params.account - Delegator / payer address.\n * @param params.chainId - Chain ID of the delegation.\n * @param params.delegationHash - Hash of the stored delegation.\n * @param params.allowance - Period allowance stored with the delegation.\n * @param params.tokenSymbol - Payment token symbol.\n * @param params.tokenAddress - Payment token address.\n */\n async #ensureIntent(params: SubscriptionIntentParams): Promise<void> {\n const existingIntents = await this.#messenger.call(\n 'ChompApiService:getIntentsByAddress',\n params.account,\n );\n\n const hasActiveIntent = existingIntents.some(\n (intent) =>\n equalsIgnoreCase(intent.delegationHash, params.delegationHash) &&\n intent.status === 'active',\n );\n\n if (hasActiveIntent) {\n return;\n }\n\n await this.#createIntent(params);\n }\n\n async #createIntent(params: SubscriptionIntentParams): Promise<void> {\n await this.#messenger.call('ChompApiService:createIntents', [\n {\n account: params.account,\n delegationHash: params.delegationHash,\n chainId: params.chainId,\n metadata: {\n allowance: params.allowance,\n tokenSymbol: params.tokenSymbol,\n tokenAddress: params.tokenAddress,\n type: CASH_SUBSCRIPTION_DELEGATION_TYPE,\n },\n },\n ]);\n }\n}\n"]}
@@ -9,7 +9,6 @@ export type { ChompIntentType };
9
9
  * The `'cash-subscription'` member of {@link ChompIntentType}.
10
10
  */
11
11
  export declare const CASH_SUBSCRIPTION_DELEGATION_TYPE: "cash-subscription";
12
- export declare const SUBSCRIPTION_DELEGATION_APPROVAL_TYPE: 'subscription_delegation';
13
12
  export declare const SUBSCRIPTION_DELEGATION_POLICY_VERSION: '1';
14
13
  export type SubscriptionPermissionId = ChompIntentType;
15
14
  export type MoneyAccountAuthorizationReason = 'controller-not-ready' | 'address-not-associated' | 'eip7702-not-active' | 'monitoring-list-missing' | 'configuration-changed';
@@ -64,31 +63,11 @@ export type PreparedSubscriptionDelegationBundle = {
64
63
  chainId: Hex;
65
64
  permissions: PreparedSubscriptionPermission[];
66
65
  };
67
- export type SubscriptionFundingRequest = {
68
- useCase: 'subscription';
69
- destinationAccount: Hex;
70
- chainId: Hex;
71
- targetToken: {
72
- symbol: 'mUSD';
73
- address: Hex;
74
- };
75
- targetAmount: string;
76
- };
77
- export type SubscriptionDelegationApprovalResult = {
78
- fundingTransactionHash: Hex;
79
- };
80
66
  export type StartSubscriptionWithDelegationRequest = {
81
67
  product: ProductType;
82
68
  recurringInterval: RecurringInterval;
83
69
  chainId: Hex;
84
70
  payerAddress: Hex;
85
- /**
86
- * When `true`, skips the `ApprovalController:addRequest` consent and
87
- * funding step and proceeds directly to signing, committing, and starting
88
- * the subscription. Callers must have already obtained user consent and
89
- * ensured the Money Account is funded.
90
- */
91
- skipApproval?: boolean;
92
71
  };
93
72
  export type PrepareAuthorizationBundleResult = {
94
73
  status: 'prepared';
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/subscription-delegation/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/subscription-delegation/types.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,5 @@
4
4
  * The `'cash-subscription'` member of {@link ChompIntentType}.
5
5
  */
6
6
  export const CASH_SUBSCRIPTION_DELEGATION_TYPE = 'cash-subscription';
7
- export const SUBSCRIPTION_DELEGATION_APPROVAL_TYPE = 'subscription_delegation';
8
7
  export const SUBSCRIPTION_DELEGATION_POLICY_VERSION = '1';
9
8
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/subscription-delegation/types.ts"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAC5C,mBAAsD,CAAC;AAEzD,MAAM,CAAC,MAAM,qCAAqC,GAChD,yBAAkC,CAAC;AAErC,MAAM,CAAC,MAAM,sCAAsC,GAAG,GAAY,CAAC","sourcesContent":["import type { ChompIntentType } from '@metamask/chomp-api-service';\nimport type { Hex, Json } from '@metamask/utils';\n\nimport { PRODUCT_TYPES } from '../types.js';\nimport type {\n ProductType,\n RecurringInterval,\n StartCryptoSubscriptionResponse,\n} from '../types.js';\n\nexport type { ChompIntentType };\n\n/**\n * Storage / CHOMP metadata type for cash-subscription delegations.\n *\n * The `'cash-subscription'` member of {@link ChompIntentType}.\n */\nexport const CASH_SUBSCRIPTION_DELEGATION_TYPE =\n 'cash-subscription' as const satisfies ChompIntentType;\n\nexport const SUBSCRIPTION_DELEGATION_APPROVAL_TYPE =\n 'subscription_delegation' as const;\n\nexport const SUBSCRIPTION_DELEGATION_POLICY_VERSION = '1' as const;\n\nexport type SubscriptionPermissionId = ChompIntentType;\n\nexport type MoneyAccountAuthorizationReason =\n | 'controller-not-ready'\n | 'address-not-associated'\n | 'eip7702-not-active'\n | 'monitoring-list-missing'\n | 'configuration-changed';\n\nexport type UnsignedSubscriptionDelegation = {\n delegate: Hex;\n delegator: Hex;\n authority: Hex;\n caveats: {\n enforcer: Hex;\n terms: Hex;\n args: Hex;\n }[];\n salt: Hex;\n};\n\nexport type SignedSubscriptionDelegation = UnsignedSubscriptionDelegation & {\n signature: Hex;\n};\n\nexport type SubscriptionDelegationTypedData = {\n types: Record<string, { name: string; type: string }[]>;\n primaryType: string;\n domain: {\n chainId: number;\n name: string;\n version: string;\n verifyingContract: Hex;\n };\n message: Json;\n};\n\nexport type DecodedPermission = {\n tokenAddress: Hex;\n delegateAddress: Hex;\n periodAmount: string;\n periodDuration: number;\n startDate: number;\n maxNativeValue: '0';\n};\n\nexport type PreparedSubscriptionPermission = {\n id: SubscriptionPermissionId;\n owner: 'money-account' | 'subscription';\n disposition: 'new' | 'reused';\n delegation: UnsignedSubscriptionDelegation;\n typedData: SubscriptionDelegationTypedData;\n decodedAuthority: DecodedPermission;\n existingDelegationHash?: Hex;\n};\n\nexport type PreparedSubscriptionDelegationBundle = {\n policyVersion: string;\n account: Hex;\n chainId: Hex;\n permissions: PreparedSubscriptionPermission[];\n};\n\nexport type SubscriptionFundingRequest = {\n useCase: 'subscription';\n destinationAccount: Hex;\n chainId: Hex;\n targetToken: {\n symbol: 'mUSD';\n address: Hex;\n };\n targetAmount: string;\n};\n\nexport type SubscriptionDelegationApprovalResult = {\n fundingTransactionHash: Hex;\n};\n\nexport type StartSubscriptionWithDelegationRequest = {\n product: ProductType;\n recurringInterval: RecurringInterval;\n chainId: Hex;\n payerAddress: Hex;\n /**\n * When `true`, skips the `ApprovalController:addRequest` consent and\n * funding step and proceeds directly to signing, committing, and starting\n * the subscription. Callers must have already obtained user consent and\n * ensured the Money Account is funded.\n */\n skipApproval?: boolean;\n};\n\nexport type PrepareAuthorizationBundleResult =\n | {\n status: 'prepared';\n bundle: PreparedSubscriptionDelegationBundle;\n }\n | {\n status: 'money-account-authorization-required';\n reasons: MoneyAccountAuthorizationReason[];\n };\n\nexport type CommitAuthorizationBundleRequest = {\n bundle: PreparedSubscriptionDelegationBundle;\n signedPaymentDelegation: SignedSubscriptionDelegation;\n};\n\nexport type CommitAuthorizationBundleResult = {\n paymentDelegationHash: Hex;\n};\n\nexport type StartSubscriptionWithDelegationResult =\n StartCryptoSubscriptionResponse;\n\n/**\n * Request to prepare a cash-subscription delegation.\n *\n * The service resolves all amount, token, delegate, and trial-duration fields\n * from authoritative pricing held by `SubscriptionController`.\n *\n * Only Money Account Plus is supported; Shield continues to use ERC-20\n * approval rather than delegation.\n */\nexport type PrepareSubscriptionDelegationRequest = {\n product: typeof PRODUCT_TYPES.MONEY_ACCOUNT_PLUS;\n recurringInterval: RecurringInterval;\n payerAddress: Hex;\n /**\n * Whether the user selected the pricing trial. Pricing `trialPeriodDays`\n * only affects the delegation start date when this is true.\n */\n isTrialRequested: boolean;\n /**\n * When true, gates preparation on a sufficient Money Account balance\n * (`unitAmount × minBillingCyclesForBalance` in mUSD) before side effects.\n */\n checkBalance?: boolean;\n /**\n * When true, skips CHOMP verify and intent registration. The returned\n * delegation hash is computed locally. Defaults to false.\n */\n skipChompInteractions?: boolean;\n};\n\n/**\n * Result of {@link SubscriptionDelegationService.prepareDelegation}.\n */\nexport type PreparedSubscriptionDelegation = {\n delegationHash: Hex;\n disposition: 'created' | 'reused';\n};\n\n/**\n * Request to check whether a Money Account holds enough convertible mUSD value\n * to cover the subscription funding requirement.\n */\nexport type MoneyAccountBalanceCheckRequest = Pick<\n PrepareSubscriptionDelegationRequest,\n 'product' | 'recurringInterval' | 'payerAddress'\n>;\n\n/**\n * Result of {@link SubscriptionDelegationService.checkMoneyAccountBalance}.\n * `balance` and `requiredBalance` are mUSD base units (6 decimals).\n */\nexport type MoneyAccountBalanceCheckResult = {\n hasSufficientBalance: boolean;\n balance: string;\n requiredBalance: string;\n};\n\n/**\n * Delegation Framework enforcers used by cash-subscription delegations.\n */\nexport type SubscriptionDelegationEnforcers = {\n erc20TokenPeriodTransfer: Hex;\n allowedCalldata: Hex;\n};\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/subscription-delegation/types.ts"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAC5C,mBAAsD,CAAC;AAEzD,MAAM,CAAC,MAAM,sCAAsC,GAAG,GAAY,CAAC","sourcesContent":["import type { ChompIntentType } from '@metamask/chomp-api-service';\nimport type { Hex, Json } from '@metamask/utils';\n\nimport { PRODUCT_TYPES } from '../types.js';\nimport type {\n ProductType,\n RecurringInterval,\n StartCryptoSubscriptionResponse,\n} from '../types.js';\n\nexport type { ChompIntentType };\n\n/**\n * Storage / CHOMP metadata type for cash-subscription delegations.\n *\n * The `'cash-subscription'` member of {@link ChompIntentType}.\n */\nexport const CASH_SUBSCRIPTION_DELEGATION_TYPE =\n 'cash-subscription' as const satisfies ChompIntentType;\n\nexport const SUBSCRIPTION_DELEGATION_POLICY_VERSION = '1' as const;\n\nexport type SubscriptionPermissionId = ChompIntentType;\n\nexport type MoneyAccountAuthorizationReason =\n | 'controller-not-ready'\n | 'address-not-associated'\n | 'eip7702-not-active'\n | 'monitoring-list-missing'\n | 'configuration-changed';\n\nexport type UnsignedSubscriptionDelegation = {\n delegate: Hex;\n delegator: Hex;\n authority: Hex;\n caveats: {\n enforcer: Hex;\n terms: Hex;\n args: Hex;\n }[];\n salt: Hex;\n};\n\nexport type SignedSubscriptionDelegation = UnsignedSubscriptionDelegation & {\n signature: Hex;\n};\n\nexport type SubscriptionDelegationTypedData = {\n types: Record<string, { name: string; type: string }[]>;\n primaryType: string;\n domain: {\n chainId: number;\n name: string;\n version: string;\n verifyingContract: Hex;\n };\n message: Json;\n};\n\nexport type DecodedPermission = {\n tokenAddress: Hex;\n delegateAddress: Hex;\n periodAmount: string;\n periodDuration: number;\n startDate: number;\n maxNativeValue: '0';\n};\n\nexport type PreparedSubscriptionPermission = {\n id: SubscriptionPermissionId;\n owner: 'money-account' | 'subscription';\n disposition: 'new' | 'reused';\n delegation: UnsignedSubscriptionDelegation;\n typedData: SubscriptionDelegationTypedData;\n decodedAuthority: DecodedPermission;\n existingDelegationHash?: Hex;\n};\n\nexport type PreparedSubscriptionDelegationBundle = {\n policyVersion: string;\n account: Hex;\n chainId: Hex;\n permissions: PreparedSubscriptionPermission[];\n};\n\nexport type StartSubscriptionWithDelegationRequest = {\n product: ProductType;\n recurringInterval: RecurringInterval;\n chainId: Hex;\n payerAddress: Hex;\n};\n\nexport type PrepareAuthorizationBundleResult =\n | {\n status: 'prepared';\n bundle: PreparedSubscriptionDelegationBundle;\n }\n | {\n status: 'money-account-authorization-required';\n reasons: MoneyAccountAuthorizationReason[];\n };\n\nexport type CommitAuthorizationBundleRequest = {\n bundle: PreparedSubscriptionDelegationBundle;\n signedPaymentDelegation: SignedSubscriptionDelegation;\n};\n\nexport type CommitAuthorizationBundleResult = {\n paymentDelegationHash: Hex;\n};\n\nexport type StartSubscriptionWithDelegationResult =\n StartCryptoSubscriptionResponse;\n\n/**\n * Request to prepare a cash-subscription delegation.\n *\n * The service resolves all amount, token, delegate, and trial-duration fields\n * from authoritative pricing held by `SubscriptionController`.\n *\n * Only Money Account Plus is supported; Shield continues to use ERC-20\n * approval rather than delegation.\n */\nexport type PrepareSubscriptionDelegationRequest = {\n product: typeof PRODUCT_TYPES.MONEY_ACCOUNT_PLUS;\n recurringInterval: RecurringInterval;\n payerAddress: Hex;\n /**\n * Whether the user selected the pricing trial. Pricing `trialPeriodDays`\n * only affects the delegation start date when this is true.\n */\n isTrialRequested: boolean;\n /**\n * When true, gates preparation on a sufficient Money Account balance\n * (`unitAmount × minBillingCyclesForBalance` in mUSD) before side effects.\n */\n checkBalance?: boolean;\n /**\n * When true, skips CHOMP verify and intent registration. The returned\n * delegation hash is computed locally. Defaults to false.\n */\n skipChompInteractions?: boolean;\n};\n\n/**\n * Result of {@link SubscriptionDelegationService.prepareDelegation}.\n */\nexport type PreparedSubscriptionDelegation = {\n delegationHash: Hex;\n disposition: 'created' | 'reused';\n};\n\n/**\n * Request to check whether a Money Account holds enough convertible mUSD value\n * to cover the subscription funding requirement.\n */\nexport type MoneyAccountBalanceCheckRequest = Pick<\n PrepareSubscriptionDelegationRequest,\n 'product' | 'recurringInterval' | 'payerAddress'\n>;\n\n/**\n * Result of {@link SubscriptionDelegationService.checkMoneyAccountBalance}.\n * `balance` and `requiredBalance` are mUSD base units (6 decimals).\n */\nexport type MoneyAccountBalanceCheckResult = {\n hasSufficientBalance: boolean;\n balance: string;\n requiredBalance: string;\n};\n\n/**\n * Delegation Framework enforcers used by cash-subscription delegations.\n */\nexport type SubscriptionDelegationEnforcers = {\n erc20TokenPeriodTransfer: Hex;\n allowedCalldata: Hex;\n};\n"]}
package/dist/types.d.ts CHANGED
@@ -147,8 +147,8 @@ export type Product = {
147
147
  export type Subscription = {
148
148
  id: string;
149
149
  products: Product[];
150
- currentPeriodStart?: string;
151
- currentPeriodEnd?: string;
150
+ currentPeriodStart: string;
151
+ currentPeriodEnd: string;
152
152
  /** is subscription scheduled for cancellation */
153
153
  cancelAtPeriodEnd?: boolean;
154
154
  status: SubscriptionStatus;
@@ -162,11 +162,11 @@ export type Subscription = {
162
162
  /** The date the subscription was canceled. */
163
163
  canceledAt?: string;
164
164
  /** The cancellation type indicating what cancellation options are available for this subscription. */
165
- cancelType?: CancelType;
165
+ cancelType: CancelType;
166
166
  /** The date the subscription was marked as inactive (paused/past_due/canceled). */
167
167
  inactiveAt?: string;
168
168
  /** Whether the user is eligible for support features (priority support and filing claims). True for active subscriptions and inactive subscriptions within grace period. */
169
- isEligibleForSupport?: boolean;
169
+ isEligibleForSupport: boolean;
170
170
  billingCycles?: number;
171
171
  /** The most recent invoice associated with the subscription. */
172
172
  lastInvoice?: SubscriptionInvoice;
@@ -254,6 +254,13 @@ export type StartSubscriptionRequest = {
254
254
  successUrl?: string;
255
255
  cancelUrl?: string;
256
256
  useTestClock?: boolean;
257
+ /**
258
+ * Whether the user is eligible for a refund (e.g. EU/EEA withdrawal rights).
259
+ *
260
+ * When provided, this value is sent as-is and the geolocation check is
261
+ * skipped. When omitted, the controller resolves it from geolocation.
262
+ */
263
+ isEligibleForRefund?: boolean;
257
264
  /**
258
265
  * Optional CAIP account ID of the rewards account to opt in alongside this
259
266
  * subscription. Required when the user wants to link rewards during
@@ -285,6 +292,13 @@ type StartCryptoSubscriptionRequestBase = {
285
292
  assertTrialEligibility?: boolean;
286
293
  isSponsored?: boolean;
287
294
  useTestClock?: boolean;
295
+ /**
296
+ * Whether the user is eligible for a refund (e.g. EU/EEA withdrawal rights).
297
+ *
298
+ * When provided, this value is sent as-is and the geolocation check is
299
+ * skipped. When omitted, the controller resolves it from geolocation.
300
+ */
301
+ isEligibleForRefund?: boolean;
288
302
  /**
289
303
  * Optional CAIP account ID of the rewards account to opt in alongside this
290
304
  * subscription. Required when the user wants to link rewards during