@metamask-previews/subscription-controller 9.0.1-preview-e8a256c39 → 9.0.1-preview-429f77222

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 (43) hide show
  1. package/CHANGELOG.md +2 -11
  2. package/dist/SubscriptionController.d.ts.map +1 -1
  3. package/dist/SubscriptionController.js +9 -1
  4. package/dist/SubscriptionController.js.map +1 -1
  5. package/dist/SubscriptionService.d.ts.map +1 -1
  6. package/dist/SubscriptionService.js +7 -1
  7. package/dist/SubscriptionService.js.map +1 -1
  8. package/dist/constants.d.ts +11 -16
  9. package/dist/constants.d.ts.map +1 -1
  10. package/dist/constants.js +17 -17
  11. package/dist/constants.js.map +1 -1
  12. package/dist/index.d.ts +3 -8
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +2 -3
  15. package/dist/index.js.map +1 -1
  16. package/dist/types.d.ts +6 -0
  17. package/dist/types.d.ts.map +1 -1
  18. package/dist/types.js.map +1 -1
  19. package/package.json +1 -10
  20. package/dist/subscription-delegation/SubscriptionDelegationService-method-action-types.d.ts +0 -44
  21. package/dist/subscription-delegation/SubscriptionDelegationService-method-action-types.d.ts.map +0 -1
  22. package/dist/subscription-delegation/SubscriptionDelegationService-method-action-types.js +0 -6
  23. package/dist/subscription-delegation/SubscriptionDelegationService-method-action-types.js.map +0 -1
  24. package/dist/subscription-delegation/SubscriptionDelegationService.d.ts +0 -93
  25. package/dist/subscription-delegation/SubscriptionDelegationService.d.ts.map +0 -1
  26. package/dist/subscription-delegation/SubscriptionDelegationService.js +0 -290
  27. package/dist/subscription-delegation/SubscriptionDelegationService.js.map +0 -1
  28. package/dist/subscription-delegation/amount.d.ts +0 -49
  29. package/dist/subscription-delegation/amount.d.ts.map +0 -1
  30. package/dist/subscription-delegation/amount.js +0 -84
  31. package/dist/subscription-delegation/amount.js.map +0 -1
  32. package/dist/subscription-delegation/caveats.d.ts +0 -41
  33. package/dist/subscription-delegation/caveats.d.ts.map +0 -1
  34. package/dist/subscription-delegation/caveats.js +0 -59
  35. package/dist/subscription-delegation/caveats.js.map +0 -1
  36. package/dist/subscription-delegation/fingerprint.d.ts +0 -42
  37. package/dist/subscription-delegation/fingerprint.d.ts.map +0 -1
  38. package/dist/subscription-delegation/fingerprint.js +0 -80
  39. package/dist/subscription-delegation/fingerprint.js.map +0 -1
  40. package/dist/subscription-delegation/types.d.ts +0 -73
  41. package/dist/subscription-delegation/types.d.ts.map +0 -1
  42. package/dist/subscription-delegation/types.js +0 -10
  43. package/dist/subscription-delegation/types.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"SubscriptionDelegationService.js","sourceRoot":"","sources":["../../src/subscription-delegation/SubscriptionDelegationService.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\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 {\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 { SubscriptionDelegationServiceErrorMessage } from '../constants.js';\nimport type { SubscriptionControllerGetPricingAction } from '../SubscriptionController-method-action-types.js';\nimport { CRYPTO_AUTH_METHODS, PAYMENT_TYPES, PRODUCT_TYPES } from '../types.js';\nimport type {\n ProductPrice,\n ProductType,\n PricingCryptoPaymentMethod,\n RecurringInterval,\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} from './fingerprint.js';\nimport type { SubscriptionDelegationServiceMethodActions } from './SubscriptionDelegationService-method-action-types.js';\nimport type {\n MoneyAccountBalanceCheckRequest,\n MoneyAccountBalanceCheckResult,\n PrepareSubscriptionDelegationRequest,\n PreparedSubscriptionDelegation,\n SubscriptionDelegationEnforcers,\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] 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?.ValueLteEnforcer ||\n !contracts.ERC20PeriodTransferEnforcer ||\n !contracts.RedeemerEnforcer\n ) {\n throw new Error(\n `${SubscriptionDelegationServiceErrorMessage.DelegationContractsNotFound}: ${chainId}`,\n );\n }\n\n return {\n valueLte: contracts.ValueLteEnforcer,\n erc20TokenPeriodTransfer: contracts.ERC20PeriodTransferEnforcer,\n redeemer: contracts.RedeemerEnforcer,\n };\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 | MoneyAccountBalanceServiceFetchBalanceWithFallbackAction\n | RemoteFeatureFlagControllerGetStateAction\n | SubscriptionControllerGetPricingAction;\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 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 * Alpha callers must pass `skipChompInteractions: true` until a follow-up\n * `@metamask/chomp-api-service` release accepts `'cash-subscription'` intent\n * metadata. The CHOMP-enabled path (`skipChompInteractions` unset/false)\n * remains dormant and is not production-ready without that package support.\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 both the delegation\n * `delegate` and the RedeemerEnforcer redeemer.\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 * 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 * 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 (required for alpha), CHOMP verify\n * and intent calls are skipped; the returned hash is computed locally. The\n * default CHOMP-enabled path requires a follow-up chomp-api-service release\n * that accepts `'cash-subscription'` intent metadata.\n *\n * @param request - Authoritative pricing and payer details for the 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 ): 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 { chainId, delegateAddress, enforcers, price, 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 matches = makeMatchesSubscriptionDelegation({\n delegatorAddress: request.payerAddress,\n delegateAddress,\n chainId,\n tokenAddress: token.address,\n periodAmount,\n periodDuration,\n nowSeconds,\n isTrialDeferred,\n enforcers,\n });\n\n const existingDelegations = await this.#messenger.call(\n 'AuthenticatedUserStorageService:listDelegations',\n );\n const reusable = existingDelegations.find(matches);\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 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 #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 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 // Published `@metamask/chomp-api-service` only types intent metadata as\n // `'cash-deposit' | 'cash-withdrawal'`. The dormant production path still\n // passes `'cash-subscription'`; a follow-up chomp-api-service release must\n // accept that discriminator before this path is production-ready. Alpha\n // callers must use `skipChompInteractions: true` so this method is not\n // reached.\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 as\n | 'cash-deposit'\n | 'cash-withdrawal',\n },\n },\n ]);\n }\n}\n"]}
@@ -1,49 +0,0 @@
1
- import type { RecurringInterval } from '../types.js';
2
- /**
3
- * Rescales a plan fee from pricing `unitDecimals` into token base units.
4
- *
5
- * Uses a 1:1 numeric mapping (ADR 0057): the period amount is one billing
6
- * interval's fee, not `fee × minimumFundingCycles`.
7
- *
8
- * @param params - Amount and decimal inputs.
9
- * @param params.unitAmount - Fee in pricing minor units (non-negative integer).
10
- * @param params.unitDecimals - Decimals of `unitAmount`.
11
- * @param params.tokenDecimals - Decimals of the payment token.
12
- * @returns The period amount in token base units.
13
- * @throws If inputs are not non-negative integers, or downscaling would lose precision.
14
- */
15
- export declare function calculatePeriodAmount({ unitAmount, unitDecimals, tokenDecimals, }: {
16
- unitAmount: number;
17
- unitDecimals: number;
18
- tokenDecimals: number;
19
- }): bigint;
20
- /**
21
- * Plan-scoped ERC-20 period duration in seconds (ADR 0057).
22
- *
23
- * - Monthly: 28 days (minimum Stripe monthly invoice gap).
24
- * - Yearly: 365 days.
25
- *
26
- * @param recurringInterval - Subscription billing interval.
27
- * @returns Period duration in seconds.
28
- */
29
- export declare function getPeriodDuration(recurringInterval: RecurringInterval): number;
30
- /**
31
- * Computes the ERC20TokenPeriodTransfer `startDate` for a subscription
32
- * delegation, optionally deferred by a pricing trial.
33
- *
34
- * @param params - Clock and optional trial length.
35
- * @param params.nowSeconds - Current unix timestamp in seconds.
36
- * @param params.trialPeriodDays - Optional non-negative trial length in days.
37
- * Defaults to `0` (no offset) when omitted.
38
- * @returns Unix timestamp when the first period transfer may begin.
39
- */
40
- export declare function getDelegationStartDate({ nowSeconds, trialPeriodDays, }: {
41
- nowSeconds: number;
42
- trialPeriodDays?: number;
43
- }): number;
44
- /**
45
- * @param value - Candidate number.
46
- * @param message - Error message when invalid.
47
- */
48
- export declare function assertPositiveInteger(value: number, message: string): void;
49
- //# sourceMappingURL=amount.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"amount.d.ts","sourceRoot":"","sources":["../../src/subscription-delegation/amount.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,YAAY,EACZ,aAAa,GACd,EAAE;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,MAAM,CA6BT;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,iBAAiB,EAAE,iBAAiB,GACnC,MAAM,CAUR;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,UAAU,EACV,eAAmB,GACpB,EAAE;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,MAAM,CAMT;AAYD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAI1E"}
@@ -1,84 +0,0 @@
1
- import { SubscriptionDelegationServiceErrorMessage } from '../constants.js';
2
- import { RECURRING_INTERVALS } from '../types.js';
3
- const SECONDS_PER_DAY = 86_400;
4
- /**
5
- * Rescales a plan fee from pricing `unitDecimals` into token base units.
6
- *
7
- * Uses a 1:1 numeric mapping (ADR 0057): the period amount is one billing
8
- * interval's fee, not `fee × minimumFundingCycles`.
9
- *
10
- * @param params - Amount and decimal inputs.
11
- * @param params.unitAmount - Fee in pricing minor units (non-negative integer).
12
- * @param params.unitDecimals - Decimals of `unitAmount`.
13
- * @param params.tokenDecimals - Decimals of the payment token.
14
- * @returns The period amount in token base units.
15
- * @throws If inputs are not non-negative integers, or downscaling would lose precision.
16
- */
17
- export function calculatePeriodAmount({ unitAmount, unitDecimals, tokenDecimals, }) {
18
- assertNonNegativeInteger(unitAmount, SubscriptionDelegationServiceErrorMessage.InvalidAmount);
19
- assertNonNegativeInteger(unitDecimals, SubscriptionDelegationServiceErrorMessage.InvalidDecimals);
20
- assertNonNegativeInteger(tokenDecimals, SubscriptionDelegationServiceErrorMessage.InvalidDecimals);
21
- const amount = BigInt(unitAmount);
22
- if (tokenDecimals === unitDecimals) {
23
- return amount;
24
- }
25
- if (tokenDecimals > unitDecimals) {
26
- return amount * 10n ** BigInt(tokenDecimals - unitDecimals);
27
- }
28
- const divisor = 10n ** BigInt(unitDecimals - tokenDecimals);
29
- if (amount % divisor !== 0n) {
30
- throw new Error(SubscriptionDelegationServiceErrorMessage.LossyAmountScale);
31
- }
32
- return amount / divisor;
33
- }
34
- /**
35
- * Plan-scoped ERC-20 period duration in seconds (ADR 0057).
36
- *
37
- * - Monthly: 28 days (minimum Stripe monthly invoice gap).
38
- * - Yearly: 365 days.
39
- *
40
- * @param recurringInterval - Subscription billing interval.
41
- * @returns Period duration in seconds.
42
- */
43
- export function getPeriodDuration(recurringInterval) {
44
- if (recurringInterval === RECURRING_INTERVALS.month) {
45
- return 28 * SECONDS_PER_DAY;
46
- }
47
- if (recurringInterval === RECURRING_INTERVALS.year) {
48
- return 365 * SECONDS_PER_DAY;
49
- }
50
- throw new Error(SubscriptionDelegationServiceErrorMessage.UnsupportedRecurringInterval);
51
- }
52
- /**
53
- * Computes the ERC20TokenPeriodTransfer `startDate` for a subscription
54
- * delegation, optionally deferred by a pricing trial.
55
- *
56
- * @param params - Clock and optional trial length.
57
- * @param params.nowSeconds - Current unix timestamp in seconds.
58
- * @param params.trialPeriodDays - Optional non-negative trial length in days.
59
- * Defaults to `0` (no offset) when omitted.
60
- * @returns Unix timestamp when the first period transfer may begin.
61
- */
62
- export function getDelegationStartDate({ nowSeconds, trialPeriodDays = 0, }) {
63
- assertNonNegativeInteger(trialPeriodDays, SubscriptionDelegationServiceErrorMessage.InvalidTrialPeriodDays);
64
- return nowSeconds + trialPeriodDays * SECONDS_PER_DAY;
65
- }
66
- /**
67
- * @param value - Candidate number.
68
- * @param message - Error message when invalid.
69
- */
70
- function assertNonNegativeInteger(value, message) {
71
- if (!Number.isInteger(value) || value < 0) {
72
- throw new Error(message);
73
- }
74
- }
75
- /**
76
- * @param value - Candidate number.
77
- * @param message - Error message when invalid.
78
- */
79
- export function assertPositiveInteger(value, message) {
80
- if (!Number.isInteger(value) || value <= 0) {
81
- throw new Error(message);
82
- }
83
- }
84
- //# sourceMappingURL=amount.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"amount.js","sourceRoot":"","sources":["../../src/subscription-delegation/amount.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yCAAyC,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGlD,MAAM,eAAe,GAAG,MAAM,CAAC;AAE/B;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CAAC,EACpC,UAAU,EACV,YAAY,EACZ,aAAa,GAKd;IACC,wBAAwB,CACtB,UAAU,EACV,yCAAyC,CAAC,aAAa,CACxD,CAAC;IACF,wBAAwB,CACtB,YAAY,EACZ,yCAAyC,CAAC,eAAe,CAC1D,CAAC;IACF,wBAAwB,CACtB,aAAa,EACb,yCAAyC,CAAC,eAAe,CAC1D,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAElC,IAAI,aAAa,KAAK,YAAY,EAAE,CAAC;QACnC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,aAAa,GAAG,YAAY,EAAE,CAAC;QACjC,OAAO,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,aAAa,GAAG,YAAY,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,IAAI,MAAM,CAAC,YAAY,GAAG,aAAa,CAAC,CAAC;IAC5D,IAAI,MAAM,GAAG,OAAO,KAAK,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,gBAAgB,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,MAAM,GAAG,OAAO,CAAC;AAC1B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,iBAAoC;IAEpC,IAAI,iBAAiB,KAAK,mBAAmB,CAAC,KAAK,EAAE,CAAC;QACpD,OAAO,EAAE,GAAG,eAAe,CAAC;IAC9B,CAAC;IACD,IAAI,iBAAiB,KAAK,mBAAmB,CAAC,IAAI,EAAE,CAAC;QACnD,OAAO,GAAG,GAAG,eAAe,CAAC;IAC/B,CAAC;IACD,MAAM,IAAI,KAAK,CACb,yCAAyC,CAAC,4BAA4B,CACvE,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,sBAAsB,CAAC,EACrC,UAAU,EACV,eAAe,GAAG,CAAC,GAIpB;IACC,wBAAwB,CACtB,eAAe,EACf,yCAAyC,CAAC,sBAAsB,CACjE,CAAC;IACF,OAAO,UAAU,GAAG,eAAe,GAAG,eAAe,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,SAAS,wBAAwB,CAAC,KAAa,EAAE,OAAe;IAC9D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,OAAe;IAClE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC","sourcesContent":["import { SubscriptionDelegationServiceErrorMessage } from '../constants.js';\nimport { RECURRING_INTERVALS } from '../types.js';\nimport type { RecurringInterval } from '../types.js';\n\nconst SECONDS_PER_DAY = 86_400;\n\n/**\n * Rescales a plan fee from pricing `unitDecimals` into token base units.\n *\n * Uses a 1:1 numeric mapping (ADR 0057): the period amount is one billing\n * interval's fee, not `fee × minimumFundingCycles`.\n *\n * @param params - Amount and decimal inputs.\n * @param params.unitAmount - Fee in pricing minor units (non-negative integer).\n * @param params.unitDecimals - Decimals of `unitAmount`.\n * @param params.tokenDecimals - Decimals of the payment token.\n * @returns The period amount in token base units.\n * @throws If inputs are not non-negative integers, or downscaling would lose precision.\n */\nexport function calculatePeriodAmount({\n unitAmount,\n unitDecimals,\n tokenDecimals,\n}: {\n unitAmount: number;\n unitDecimals: number;\n tokenDecimals: number;\n}): bigint {\n assertNonNegativeInteger(\n unitAmount,\n SubscriptionDelegationServiceErrorMessage.InvalidAmount,\n );\n assertNonNegativeInteger(\n unitDecimals,\n SubscriptionDelegationServiceErrorMessage.InvalidDecimals,\n );\n assertNonNegativeInteger(\n tokenDecimals,\n SubscriptionDelegationServiceErrorMessage.InvalidDecimals,\n );\n\n const amount = BigInt(unitAmount);\n\n if (tokenDecimals === unitDecimals) {\n return amount;\n }\n\n if (tokenDecimals > unitDecimals) {\n return amount * 10n ** BigInt(tokenDecimals - unitDecimals);\n }\n\n const divisor = 10n ** BigInt(unitDecimals - tokenDecimals);\n if (amount % divisor !== 0n) {\n throw new Error(SubscriptionDelegationServiceErrorMessage.LossyAmountScale);\n }\n return amount / divisor;\n}\n\n/**\n * Plan-scoped ERC-20 period duration in seconds (ADR 0057).\n *\n * - Monthly: 28 days (minimum Stripe monthly invoice gap).\n * - Yearly: 365 days.\n *\n * @param recurringInterval - Subscription billing interval.\n * @returns Period duration in seconds.\n */\nexport function getPeriodDuration(\n recurringInterval: RecurringInterval,\n): number {\n if (recurringInterval === RECURRING_INTERVALS.month) {\n return 28 * SECONDS_PER_DAY;\n }\n if (recurringInterval === RECURRING_INTERVALS.year) {\n return 365 * SECONDS_PER_DAY;\n }\n throw new Error(\n SubscriptionDelegationServiceErrorMessage.UnsupportedRecurringInterval,\n );\n}\n\n/**\n * Computes the ERC20TokenPeriodTransfer `startDate` for a subscription\n * delegation, optionally deferred by a pricing trial.\n *\n * @param params - Clock and optional trial length.\n * @param params.nowSeconds - Current unix timestamp in seconds.\n * @param params.trialPeriodDays - Optional non-negative trial length in days.\n * Defaults to `0` (no offset) when omitted.\n * @returns Unix timestamp when the first period transfer may begin.\n */\nexport function getDelegationStartDate({\n nowSeconds,\n trialPeriodDays = 0,\n}: {\n nowSeconds: number;\n trialPeriodDays?: number;\n}): number {\n assertNonNegativeInteger(\n trialPeriodDays,\n SubscriptionDelegationServiceErrorMessage.InvalidTrialPeriodDays,\n );\n return nowSeconds + trialPeriodDays * SECONDS_PER_DAY;\n}\n\n/**\n * @param value - Candidate number.\n * @param message - Error message when invalid.\n */\nfunction assertNonNegativeInteger(value: number, message: string): void {\n if (!Number.isInteger(value) || value < 0) {\n throw new Error(message);\n }\n}\n\n/**\n * @param value - Candidate number.\n * @param message - Error message when invalid.\n */\nexport function assertPositiveInteger(value: number, message: string): void {\n if (!Number.isInteger(value) || value <= 0) {\n throw new Error(message);\n }\n}\n"]}
@@ -1,41 +0,0 @@
1
- import type { SignedDelegation } from '@metamask/authenticated-user-storage';
2
- import type { Hex } from '@metamask/utils';
3
- import type { SubscriptionDelegationEnforcers } from './types.js';
4
- export type UnsignedSubscriptionDelegation = Omit<SignedDelegation, 'signature'>;
5
- export type BuildSubscriptionCaveatsParams = {
6
- enforcers: SubscriptionDelegationEnforcers;
7
- delegateAddress: Hex;
8
- tokenAddress: Hex;
9
- periodAmount: bigint;
10
- periodDuration: number;
11
- startDate: number;
12
- };
13
- /**
14
- * Builds the caveat list for a cash-subscription delegation:
15
- * `ValueLte(0)` then `ERC20TokenPeriodTransfer(...)`.
16
- * RedeemerEnforcer is temporarily omitted pending CHOMP guidance.
17
- *
18
- * @param params - Enforcer addresses, parties, and period terms.
19
- * @param params.enforcers - Delegation Framework enforcer addresses.
20
- * @param params.tokenAddress - Subscription settlement token.
21
- * @param params.periodAmount - Maximum token amount per period.
22
- * @param params.periodDuration - Period length in seconds.
23
- * @param params.startDate - Unix timestamp when transfers may begin.
24
- * @returns Caveats in enforcer order.
25
- */
26
- export declare function buildSubscriptionCaveats({ enforcers, tokenAddress, periodAmount, periodDuration, startDate, }: BuildSubscriptionCaveatsParams): SignedDelegation['caveats'];
27
- export type BuildUnsignedSubscriptionDelegationParams = BuildSubscriptionCaveatsParams & {
28
- delegatorAddress: Hex;
29
- /**
30
- * Optional salt for tests. When omitted, a random 32-byte salt is generated.
31
- */
32
- salt?: Hex;
33
- };
34
- /**
35
- * Builds an unsigned root cash-subscription delegation.
36
- *
37
- * @param params - Delegation parties, enforcers, and period terms.
38
- * @returns An unsigned delegation ready for signing.
39
- */
40
- export declare function buildUnsignedSubscriptionDelegation(params: BuildUnsignedSubscriptionDelegationParams): UnsignedSubscriptionDelegation;
41
- //# sourceMappingURL=caveats.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"caveats.d.ts","sourceRoot":"","sources":["../../src/subscription-delegation/caveats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAO7E,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAE3C,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,YAAY,CAAC;AAElE,MAAM,MAAM,8BAA8B,GAAG,IAAI,CAC/C,gBAAgB,EAChB,WAAW,CACZ,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,SAAS,EAAE,+BAA+B,CAAC;IAC3C,eAAe,EAAE,GAAG,CAAC;IACrB,YAAY,EAAE,GAAG,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,SAAS,GACV,EAAE,8BAA8B,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAyB9D;AAED,MAAM,MAAM,yCAAyC,GACnD,8BAA8B,GAAG;IAC/B,gBAAgB,EAAE,GAAG,CAAC;IACtB;;OAEG;IACH,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ,CAAC;AAEJ;;;;;GAKG;AACH,wBAAgB,mCAAmC,CACjD,MAAM,EAAE,yCAAyC,GAChD,8BAA8B,CAYhC"}
@@ -1,59 +0,0 @@
1
- import { ROOT_AUTHORITY, createERC20TokenPeriodTransferTerms, createValueLteTerms, } from '@metamask/delegation-core';
2
- import { bytesToHex } from '@metamask/utils';
3
- /**
4
- * Builds the caveat list for a cash-subscription delegation:
5
- * `ValueLte(0)` then `ERC20TokenPeriodTransfer(...)`.
6
- * RedeemerEnforcer is temporarily omitted pending CHOMP guidance.
7
- *
8
- * @param params - Enforcer addresses, parties, and period terms.
9
- * @param params.enforcers - Delegation Framework enforcer addresses.
10
- * @param params.tokenAddress - Subscription settlement token.
11
- * @param params.periodAmount - Maximum token amount per period.
12
- * @param params.periodDuration - Period length in seconds.
13
- * @param params.startDate - Unix timestamp when transfers may begin.
14
- * @returns Caveats in enforcer order.
15
- */
16
- export function buildSubscriptionCaveats({ enforcers, tokenAddress, periodAmount, periodDuration, startDate, }) {
17
- return [
18
- {
19
- enforcer: enforcers.valueLte,
20
- terms: createValueLteTerms({ maxValue: 0n }),
21
- args: '0x',
22
- },
23
- {
24
- enforcer: enforcers.erc20TokenPeriodTransfer,
25
- terms: createERC20TokenPeriodTransferTerms({
26
- tokenAddress,
27
- periodAmount,
28
- periodDuration,
29
- startDate,
30
- }),
31
- args: '0x',
32
- },
33
- // TODO: recheck with CHOMP team if we should set redeemer to subscription payment address
34
- // or use allowed call data
35
- // {
36
- // enforcer: enforcers.redeemer,
37
- // terms: createRedeemerTerms({ redeemers: [delegateAddress] }),
38
- // args: '0x',
39
- // },
40
- ];
41
- }
42
- /**
43
- * Builds an unsigned root cash-subscription delegation.
44
- *
45
- * @param params - Delegation parties, enforcers, and period terms.
46
- * @returns An unsigned delegation ready for signing.
47
- */
48
- export function buildUnsignedSubscriptionDelegation(params) {
49
- const salt = params.salt ??
50
- bytesToHex(globalThis.crypto.getRandomValues(new Uint8Array(32)));
51
- return {
52
- delegate: params.delegateAddress,
53
- delegator: params.delegatorAddress,
54
- authority: ROOT_AUTHORITY,
55
- caveats: buildSubscriptionCaveats(params),
56
- salt,
57
- };
58
- }
59
- //# sourceMappingURL=caveats.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"caveats.js","sourceRoot":"","sources":["../../src/subscription-delegation/caveats.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,mCAAmC,EACnC,mBAAmB,GACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAmB7C;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,wBAAwB,CAAC,EACvC,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,SAAS,GACsB;IAC/B,OAAO;QACL;YACE,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,KAAK,EAAE,mBAAmB,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;YAC5C,IAAI,EAAE,IAAI;SACX;QACD;YACE,QAAQ,EAAE,SAAS,CAAC,wBAAwB;YAC5C,KAAK,EAAE,mCAAmC,CAAC;gBACzC,YAAY;gBACZ,YAAY;gBACZ,cAAc;gBACd,SAAS;aACV,CAAC;YACF,IAAI,EAAE,IAAI;SACX;QACD,0FAA0F;QAC1F,2BAA2B;QAC3B,IAAI;QACJ,kCAAkC;QAClC,kEAAkE;QAClE,gBAAgB;QAChB,KAAK;KACN,CAAC;AACJ,CAAC;AAWD;;;;;GAKG;AACH,MAAM,UAAU,mCAAmC,CACjD,MAAiD;IAEjD,MAAM,IAAI,GACR,MAAM,CAAC,IAAI;QACX,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAEpE,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,eAAe;QAChC,SAAS,EAAE,MAAM,CAAC,gBAAgB;QAClC,SAAS,EAAE,cAAc;QACzB,OAAO,EAAE,wBAAwB,CAAC,MAAM,CAAC;QACzC,IAAI;KACL,CAAC;AACJ,CAAC","sourcesContent":["import type { SignedDelegation } from '@metamask/authenticated-user-storage';\nimport {\n ROOT_AUTHORITY,\n createERC20TokenPeriodTransferTerms,\n createValueLteTerms,\n} from '@metamask/delegation-core';\nimport { bytesToHex } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport type { SubscriptionDelegationEnforcers } from './types.js';\n\nexport type UnsignedSubscriptionDelegation = Omit<\n SignedDelegation,\n 'signature'\n>;\n\nexport type BuildSubscriptionCaveatsParams = {\n enforcers: SubscriptionDelegationEnforcers;\n delegateAddress: Hex;\n tokenAddress: Hex;\n periodAmount: bigint;\n periodDuration: number;\n startDate: number;\n};\n\n/**\n * Builds the caveat list for a cash-subscription delegation:\n * `ValueLte(0)` then `ERC20TokenPeriodTransfer(...)`.\n * RedeemerEnforcer is temporarily omitted pending CHOMP guidance.\n *\n * @param params - Enforcer addresses, parties, and period terms.\n * @param params.enforcers - Delegation Framework enforcer addresses.\n * @param params.tokenAddress - Subscription settlement token.\n * @param params.periodAmount - Maximum token amount per period.\n * @param params.periodDuration - Period length in seconds.\n * @param params.startDate - Unix timestamp when transfers may begin.\n * @returns Caveats in enforcer order.\n */\nexport function buildSubscriptionCaveats({\n enforcers,\n tokenAddress,\n periodAmount,\n periodDuration,\n startDate,\n}: BuildSubscriptionCaveatsParams): SignedDelegation['caveats'] {\n return [\n {\n enforcer: enforcers.valueLte,\n terms: createValueLteTerms({ maxValue: 0n }),\n args: '0x',\n },\n {\n enforcer: enforcers.erc20TokenPeriodTransfer,\n terms: createERC20TokenPeriodTransferTerms({\n tokenAddress,\n periodAmount,\n periodDuration,\n startDate,\n }),\n args: '0x',\n },\n // TODO: recheck with CHOMP team if we should set redeemer to subscription payment address\n // or use allowed call data\n // {\n // enforcer: enforcers.redeemer,\n // terms: createRedeemerTerms({ redeemers: [delegateAddress] }),\n // args: '0x',\n // },\n ];\n}\n\nexport type BuildUnsignedSubscriptionDelegationParams =\n BuildSubscriptionCaveatsParams & {\n delegatorAddress: Hex;\n /**\n * Optional salt for tests. When omitted, a random 32-byte salt is generated.\n */\n salt?: Hex;\n };\n\n/**\n * Builds an unsigned root cash-subscription delegation.\n *\n * @param params - Delegation parties, enforcers, and period terms.\n * @returns An unsigned delegation ready for signing.\n */\nexport function buildUnsignedSubscriptionDelegation(\n params: BuildUnsignedSubscriptionDelegationParams,\n): UnsignedSubscriptionDelegation {\n const salt =\n params.salt ??\n bytesToHex(globalThis.crypto.getRandomValues(new Uint8Array(32)));\n\n return {\n delegate: params.delegateAddress,\n delegator: params.delegatorAddress,\n authority: ROOT_AUTHORITY,\n caveats: buildSubscriptionCaveats(params),\n salt,\n };\n}\n"]}
@@ -1,42 +0,0 @@
1
- import type { DelegationResponse } from '@metamask/authenticated-user-storage';
2
- import type { Hex } from '@metamask/utils';
3
- import type { SubscriptionDelegationEnforcers } from './types.js';
4
- export type SubscriptionDelegationFingerprint = {
5
- delegatorAddress: Hex;
6
- delegateAddress: Hex;
7
- chainId: Hex;
8
- tokenAddress: Hex;
9
- periodAmount: bigint;
10
- periodDuration: number;
11
- /**
12
- * Current unix timestamp in seconds. Used to classify a stored period
13
- * `startDate` as immediately redeemable (`<= now`) vs trial-deferred (`> now`).
14
- */
15
- nowSeconds: number;
16
- /**
17
- * When true, only a still-deferred period start (`> nowSeconds`) matches.
18
- * When false, only an immediately redeemable start (`<= nowSeconds`) matches.
19
- */
20
- isTrialDeferred: boolean;
21
- enforcers: SubscriptionDelegationEnforcers;
22
- };
23
- /**
24
- * Case-insensitive hex equality.
25
- *
26
- * @param left - First hex value.
27
- * @param right - Second hex value.
28
- * @returns Whether the values are equal ignoring case.
29
- */
30
- export declare function equalsIgnoreCase(left: string, right: string): boolean;
31
- /**
32
- * Builds a predicate that matches a stored AUS delegation to the semantic
33
- * cash-subscription fingerprint. Salt is ignored so a previously signed
34
- * equivalent permission can be reused. Period `startDate` is compared only
35
- * as trial-deferred (`> nowSeconds`) vs immediately redeemable (`<= nowSeconds`)
36
- * so a positive-length trial cannot reuse a live permission and vice versa.
37
- *
38
- * @param expected - Semantic fields that must match.
39
- * @returns Predicate over {@link DelegationResponse}.
40
- */
41
- export declare function makeMatchesSubscriptionDelegation(expected: SubscriptionDelegationFingerprint): (entry: DelegationResponse) => boolean;
42
- //# sourceMappingURL=fingerprint.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/subscription-delegation/fingerprint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAK/E,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAE3C,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,YAAY,CAAC;AAGlE,MAAM,MAAM,iCAAiC,GAAG;IAC9C,gBAAgB,EAAE,GAAG,CAAC;IACtB,eAAe,EAAE,GAAG,CAAC;IACrB,OAAO,EAAE,GAAG,CAAC;IACb,YAAY,EAAE,GAAG,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,+BAA+B,CAAC;CAC5C,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAErE;AAED;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,iCAAiC,GAC1C,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAkFxC"}
@@ -1,80 +0,0 @@
1
- import { decodeERC20TokenPeriodTransferTerms, decodeValueLteTerms, } from '@metamask/delegation-core';
2
- import { CASH_SUBSCRIPTION_DELEGATION_TYPE } from './types.js';
3
- /**
4
- * Case-insensitive hex equality.
5
- *
6
- * @param left - First hex value.
7
- * @param right - Second hex value.
8
- * @returns Whether the values are equal ignoring case.
9
- */
10
- export function equalsIgnoreCase(left, right) {
11
- return left.toLowerCase() === right.toLowerCase();
12
- }
13
- /**
14
- * Builds a predicate that matches a stored AUS delegation to the semantic
15
- * cash-subscription fingerprint. Salt is ignored so a previously signed
16
- * equivalent permission can be reused. Period `startDate` is compared only
17
- * as trial-deferred (`> nowSeconds`) vs immediately redeemable (`<= nowSeconds`)
18
- * so a positive-length trial cannot reuse a live permission and vice versa.
19
- *
20
- * @param expected - Semantic fields that must match.
21
- * @returns Predicate over {@link DelegationResponse}.
22
- */
23
- export function makeMatchesSubscriptionDelegation(expected) {
24
- // const expectedRedeemerTerms = createRedeemerTerms({
25
- // redeemers: [expected.delegateAddress],
26
- // });
27
- return (entry) => {
28
- if (entry.metadata.type !== CASH_SUBSCRIPTION_DELEGATION_TYPE) {
29
- return false;
30
- }
31
- if (!equalsIgnoreCase(entry.signedDelegation.delegator, expected.delegatorAddress)) {
32
- return false;
33
- }
34
- if (!equalsIgnoreCase(entry.signedDelegation.delegate, expected.delegateAddress)) {
35
- return false;
36
- }
37
- if (!equalsIgnoreCase(entry.metadata.chainIdHex, expected.chainId)) {
38
- return false;
39
- }
40
- if (!equalsIgnoreCase(entry.metadata.tokenAddress, expected.tokenAddress)) {
41
- return false;
42
- }
43
- const { caveats } = entry.signedDelegation;
44
- if (caveats.length < 2) {
45
- return false;
46
- }
47
- const valueLteCaveat = caveats.find((caveat) => equalsIgnoreCase(caveat.enforcer, expected.enforcers.valueLte));
48
- const periodCaveat = caveats.find((caveat) => equalsIgnoreCase(caveat.enforcer, expected.enforcers.erc20TokenPeriodTransfer));
49
- // TODO: recheck with CHOMP team if we should set redeemer to subscirption payment address
50
- // or use allowed call data
51
- // const redeemerCaveat = caveats.find((caveat) =>
52
- // equalsIgnoreCase(caveat.enforcer, expected.enforcers.redeemer),
53
- // );
54
- if (!valueLteCaveat || !periodCaveat) {
55
- return false;
56
- }
57
- // if (!equalsIgnoreCase(redeemerCaveat.terms, expectedRedeemerTerms)) {
58
- // return false;
59
- // }
60
- try {
61
- const valueTerms = decodeValueLteTerms(valueLteCaveat.terms);
62
- if (valueTerms.maxValue !== 0n) {
63
- return false;
64
- }
65
- const periodTerms = decodeERC20TokenPeriodTransferTerms(periodCaveat.terms);
66
- const storedStartDate = Number(periodTerms.startDate);
67
- const isStoredDeferred = storedStartDate > expected.nowSeconds;
68
- if (expected.isTrialDeferred !== isStoredDeferred) {
69
- return false;
70
- }
71
- return (equalsIgnoreCase(periodTerms.tokenAddress, expected.tokenAddress) &&
72
- periodTerms.periodAmount === expected.periodAmount &&
73
- Number(periodTerms.periodDuration) === expected.periodDuration);
74
- }
75
- catch {
76
- return false;
77
- }
78
- };
79
- }
80
- //# sourceMappingURL=fingerprint.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/subscription-delegation/fingerprint.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DelegationResponse } from '@metamask/authenticated-user-storage';\nimport {\n decodeERC20TokenPeriodTransferTerms,\n decodeValueLteTerms,\n} from '@metamask/delegation-core';\nimport type { Hex } from '@metamask/utils';\n\nimport type { SubscriptionDelegationEnforcers } from './types.js';\nimport { CASH_SUBSCRIPTION_DELEGATION_TYPE } from './types.js';\n\nexport type SubscriptionDelegationFingerprint = {\n delegatorAddress: Hex;\n delegateAddress: Hex;\n chainId: Hex;\n tokenAddress: Hex;\n periodAmount: bigint;\n periodDuration: number;\n /**\n * Current unix timestamp in seconds. Used to classify a stored period\n * `startDate` as immediately redeemable (`<= now`) vs trial-deferred (`> now`).\n */\n nowSeconds: number;\n /**\n * When true, only a still-deferred period start (`> nowSeconds`) matches.\n * When false, only an immediately redeemable start (`<= nowSeconds`) matches.\n */\n isTrialDeferred: boolean;\n enforcers: SubscriptionDelegationEnforcers;\n};\n\n/**\n * Case-insensitive hex equality.\n *\n * @param left - First hex value.\n * @param right - Second hex value.\n * @returns Whether the values are equal ignoring case.\n */\nexport function equalsIgnoreCase(left: string, right: string): boolean {\n return left.toLowerCase() === right.toLowerCase();\n}\n\n/**\n * Builds a predicate that matches a stored AUS delegation to the semantic\n * cash-subscription fingerprint. Salt is ignored so a previously signed\n * equivalent permission can be reused. Period `startDate` is compared only\n * as trial-deferred (`> nowSeconds`) vs immediately redeemable (`<= nowSeconds`)\n * so a positive-length trial cannot reuse a live permission and vice versa.\n *\n * @param expected - Semantic fields that must match.\n * @returns Predicate over {@link DelegationResponse}.\n */\nexport function makeMatchesSubscriptionDelegation(\n expected: SubscriptionDelegationFingerprint,\n): (entry: DelegationResponse) => boolean {\n // const expectedRedeemerTerms = createRedeemerTerms({\n // redeemers: [expected.delegateAddress],\n // });\n\n return (entry) => {\n if (entry.metadata.type !== CASH_SUBSCRIPTION_DELEGATION_TYPE) {\n return false;\n }\n if (\n !equalsIgnoreCase(\n entry.signedDelegation.delegator,\n expected.delegatorAddress,\n )\n ) {\n return false;\n }\n if (\n !equalsIgnoreCase(\n entry.signedDelegation.delegate,\n expected.delegateAddress,\n )\n ) {\n return false;\n }\n if (!equalsIgnoreCase(entry.metadata.chainIdHex, expected.chainId)) {\n return false;\n }\n if (!equalsIgnoreCase(entry.metadata.tokenAddress, expected.tokenAddress)) {\n return false;\n }\n\n const { caveats } = entry.signedDelegation;\n if (caveats.length < 2) {\n return false;\n }\n\n const valueLteCaveat = caveats.find((caveat) =>\n equalsIgnoreCase(caveat.enforcer, expected.enforcers.valueLte),\n );\n const periodCaveat = caveats.find((caveat) =>\n equalsIgnoreCase(\n caveat.enforcer,\n expected.enforcers.erc20TokenPeriodTransfer,\n ),\n );\n // TODO: recheck with CHOMP team if we should set redeemer to subscirption payment address\n // or use allowed call data\n // const redeemerCaveat = caveats.find((caveat) =>\n // equalsIgnoreCase(caveat.enforcer, expected.enforcers.redeemer),\n // );\n if (!valueLteCaveat || !periodCaveat) {\n return false;\n }\n // if (!equalsIgnoreCase(redeemerCaveat.terms, expectedRedeemerTerms)) {\n // return false;\n // }\n\n try {\n const valueTerms = decodeValueLteTerms(valueLteCaveat.terms);\n if (valueTerms.maxValue !== 0n) {\n return false;\n }\n\n const periodTerms = decodeERC20TokenPeriodTransferTerms(\n periodCaveat.terms,\n );\n const storedStartDate = Number(periodTerms.startDate);\n const isStoredDeferred = storedStartDate > expected.nowSeconds;\n if (expected.isTrialDeferred !== isStoredDeferred) {\n return false;\n }\n\n return (\n equalsIgnoreCase(periodTerms.tokenAddress, expected.tokenAddress) &&\n periodTerms.periodAmount === expected.periodAmount &&\n Number(periodTerms.periodDuration) === expected.periodDuration\n );\n } catch {\n return false;\n }\n };\n}\n"]}
@@ -1,73 +0,0 @@
1
- import type { Hex } from '@metamask/utils';
2
- import { PRODUCT_TYPES } from '../types.js';
3
- import type { RecurringInterval } from '../types.js';
4
- /**
5
- * Storage / CHOMP metadata type for cash-subscription delegations.
6
- *
7
- * Defined locally so this package does not depend on an unreleased
8
- * `@metamask/chomp-api-service` intent type. Production CHOMP intent
9
- * registration still requires a follow-up chomp-api-service release that
10
- * accepts `'cash-subscription'`.
11
- */
12
- export declare const CASH_SUBSCRIPTION_DELEGATION_TYPE: 'cash-subscription';
13
- /**
14
- * Request to prepare a cash-subscription delegation.
15
- *
16
- * The service resolves all amount, token, delegate, and trial-duration fields
17
- * from authoritative pricing held by `SubscriptionController`.
18
- *
19
- * Only Money Account Plus is supported; Shield continues to use ERC-20
20
- * approval rather than delegation.
21
- */
22
- export type PrepareSubscriptionDelegationRequest = {
23
- product: typeof PRODUCT_TYPES.MONEY_ACCOUNT_PLUS;
24
- recurringInterval: RecurringInterval;
25
- payerAddress: Hex;
26
- /**
27
- * Whether the user selected the pricing trial. Pricing `trialPeriodDays`
28
- * only affects the delegation start date when this is true.
29
- */
30
- isTrialRequested: boolean;
31
- /**
32
- * When true, gates preparation on a sufficient Money Account balance
33
- * (`unitAmount × minBillingCyclesForBalance` in mUSD) before side effects.
34
- */
35
- checkBalance?: boolean;
36
- /**
37
- * When true, skips CHOMP verify/intent interactions. Required for alpha
38
- * until `@metamask/chomp-api-service` accepts `'cash-subscription'` intent
39
- * metadata. Defaults to false (production path; unsupported until that
40
- * follow-up release).
41
- */
42
- skipChompInteractions?: boolean;
43
- };
44
- /**
45
- * Result of {@link SubscriptionDelegationService.prepareDelegation}.
46
- */
47
- export type PreparedSubscriptionDelegation = {
48
- delegationHash: Hex;
49
- disposition: 'created' | 'reused';
50
- };
51
- /**
52
- * Request to check whether a Money Account holds enough convertible mUSD value
53
- * to cover the subscription funding requirement.
54
- */
55
- export type MoneyAccountBalanceCheckRequest = Pick<PrepareSubscriptionDelegationRequest, 'product' | 'recurringInterval' | 'payerAddress'>;
56
- /**
57
- * Result of {@link SubscriptionDelegationService.checkMoneyAccountBalance}.
58
- * `balance` and `requiredBalance` are mUSD base units (6 decimals).
59
- */
60
- export type MoneyAccountBalanceCheckResult = {
61
- hasSufficientBalance: boolean;
62
- balance: string;
63
- requiredBalance: string;
64
- };
65
- /**
66
- * Delegation Framework enforcers used by cash-subscription delegations.
67
- */
68
- export type SubscriptionDelegationEnforcers = {
69
- valueLte: Hex;
70
- erc20TokenPeriodTransfer: Hex;
71
- redeemer: Hex;
72
- };
73
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/subscription-delegation/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;;GAOG;AACH,eAAO,MAAM,iCAAiC,EAAG,mBAA4B,CAAC;AAE9E;;;;;;;;GAQG;AACH,MAAM,MAAM,oCAAoC,GAAG;IACjD,OAAO,EAAE,OAAO,aAAa,CAAC,kBAAkB,CAAC;IACjD,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,YAAY,EAAE,GAAG,CAAC;IAClB;;;OAGG;IACH,gBAAgB,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C,cAAc,EAAE,GAAG,CAAC;IACpB,WAAW,EAAE,SAAS,GAAG,QAAQ,CAAC;CACnC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,+BAA+B,GAAG,IAAI,CAChD,oCAAoC,EACpC,SAAS,GAAG,mBAAmB,GAAG,cAAc,CACjD,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,+BAA+B,GAAG;IAC5C,QAAQ,EAAE,GAAG,CAAC;IACd,wBAAwB,EAAE,GAAG,CAAC;IAC9B,QAAQ,EAAE,GAAG,CAAC;CACf,CAAC"}
@@ -1,10 +0,0 @@
1
- /**
2
- * Storage / CHOMP metadata type for cash-subscription delegations.
3
- *
4
- * Defined locally so this package does not depend on an unreleased
5
- * `@metamask/chomp-api-service` intent type. Production CHOMP intent
6
- * registration still requires a follow-up chomp-api-service release that
7
- * accepts `'cash-subscription'`.
8
- */
9
- export const CASH_SUBSCRIPTION_DELEGATION_TYPE = 'cash-subscription';
10
- //# sourceMappingURL=types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/subscription-delegation/types.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,mBAA4B,CAAC","sourcesContent":["import type { Hex } from '@metamask/utils';\n\nimport { PRODUCT_TYPES } from '../types.js';\nimport type { RecurringInterval } from '../types.js';\n\n/**\n * Storage / CHOMP metadata type for cash-subscription delegations.\n *\n * Defined locally so this package does not depend on an unreleased\n * `@metamask/chomp-api-service` intent type. Production CHOMP intent\n * registration still requires a follow-up chomp-api-service release that\n * accepts `'cash-subscription'`.\n */\nexport const CASH_SUBSCRIPTION_DELEGATION_TYPE = 'cash-subscription' as const;\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/intent interactions. Required for alpha\n * until `@metamask/chomp-api-service` accepts `'cash-subscription'` intent\n * metadata. Defaults to false (production path; unsupported until that\n * follow-up release).\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 valueLte: Hex;\n erc20TokenPeriodTransfer: Hex;\n redeemer: Hex;\n};\n"]}