Skip to content

Commit 0a22e1d

Browse files
authored
feat: add rewardAccountId to GetSubscriptionsResponse data (#7319)
## Explanation <!-- Thanks for your contribution! Take a moment to answer these questions so that reviewers have the information they need to properly understand your changes: * What is the current state of things and why does it need to change? * What is the solution your changes offer and how does it work? * Are there any changes whose purpose might not obvious to those unfamiliar with the domain? * If your primary goal was to update one package but you found you had to update another one along the way, why did you do so? * If you had to upgrade a dependency, why did you do so? --> Subscription controller add `rewardAccountId` property to `GetSubscriptionsResponse` ## References <!-- Are there any issues that this pull request is tied to? Are there other links that reviewers should consult to understand these changes better? Are there client or consumer pull requests to adopt any breaking changes? For example: * Fixes #12345 * Related to #67890 --> ## Checklist - [x] I've updated the test suite for new or updated code as appropriate - [x] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [x] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/contributing.md#updating-changelogs) - [x] I've introduced [breaking changes](https://github.com/MetaMask/core/tree/main/docs/breaking-changes.md) in this PR and have prepared draft pull requests for clients and consumer packages to resolve them <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds `rewardAccountId` to `GetSubscriptionsResponse` and controller state, updating `getSubscriptions` logic and tests. > > - **Types**: > - Extend `GetSubscriptionsResponse` with `rewardAccountId` and propagate CAIP account type. > - **Controller**: > - Add `rewardAccountId` to `SubscriptionControllerState` and state metadata. > - Update `getSubscriptions` to read, compare, and persist `rewardAccountId` alongside existing fields. > - **Tests**: > - Add tests verifying state update when `rewardAccountId` changes and no-op when unchanged. > - **Docs**: > - Update `CHANGELOG.md` to note inclusion of `rewardAccountId`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 8db5494. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 68f93e7 commit 0a22e1d

File tree

4 files changed

+82
-2
lines changed

4 files changed

+82
-2
lines changed

packages/subscription-controller/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- Updated `GetSubscriptionsResponse` and controller state to include `rewardAccountId` property ([#7319](https://github.com/MetaMask/core/pull/7319))
13+
1014
## [5.3.1]
1115

1216
### Changed

packages/subscription-controller/src/SubscriptionController.test.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,66 @@ describe('SubscriptionController', () => {
594594
},
595595
);
596596
});
597+
598+
it('should update state when rewardAccountId changes from undefined to defined', async () => {
599+
await withController(
600+
{
601+
state: {
602+
rewardAccountId: undefined,
603+
},
604+
},
605+
async ({ controller, mockService }) => {
606+
mockService.getSubscriptions.mockResolvedValue({
607+
customerId: 'cus_1',
608+
subscriptions: [],
609+
trialedProducts: [],
610+
rewardAccountId:
611+
'eip155:1:0x1234567890123456789012345678901234567890',
612+
});
613+
614+
await controller.getSubscriptions();
615+
616+
expect(controller.state.rewardAccountId).toBe(
617+
'eip155:1:0x1234567890123456789012345678901234567890',
618+
);
619+
},
620+
);
621+
});
622+
623+
it('should not update state when rewardAccountId is the same', async () => {
624+
const mockRewardAccountId =
625+
'eip155:1:0x1234567890123456789012345678901234567890';
626+
627+
await withController(
628+
{
629+
state: {
630+
customerId: 'cus_1',
631+
subscriptions: [],
632+
trialedProducts: [],
633+
rewardAccountId: mockRewardAccountId,
634+
},
635+
},
636+
async ({ controller, mockService, rootMessenger }) => {
637+
mockService.getSubscriptions.mockResolvedValue({
638+
customerId: 'cus_1',
639+
subscriptions: [],
640+
trialedProducts: [],
641+
rewardAccountId: mockRewardAccountId,
642+
});
643+
644+
const stateChangeListener = jest.fn();
645+
rootMessenger.subscribe(
646+
'SubscriptionController:stateChange',
647+
stateChangeListener,
648+
);
649+
650+
await controller.getSubscriptions();
651+
652+
// State should not have changed since rewardAccountId is the same
653+
expect(stateChangeListener).not.toHaveBeenCalled();
654+
},
655+
);
656+
});
597657
});
598658

599659
describe('getSubscriptionByProduct', () => {

packages/subscription-controller/src/SubscriptionController.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ export type SubscriptionControllerState = {
5252
pricing?: PricingResponse;
5353
/** The last subscription that user has subscribed to if any. */
5454
lastSubscription?: Subscription;
55+
/** The reward account ID if user has linked rewards to the subscription. */
56+
rewardAccountId?: CaipAccountId;
5557
/**
5658
* The last selected payment method for the user.
5759
* This is used to display the last selected payment method in the UI.
@@ -221,6 +223,12 @@ const subscriptionControllerMetadata: StateMetadata<SubscriptionControllerState>
221223
includeInDebugSnapshot: false,
222224
usedInUi: true,
223225
},
226+
rewardAccountId: {
227+
includeInStateLogs: true,
228+
persist: true,
229+
includeInDebugSnapshot: false,
230+
usedInUi: true,
231+
},
224232
trialedProducts: {
225233
includeInStateLogs: true,
226234
persist: true,
@@ -362,11 +370,14 @@ export class SubscriptionController extends StaticIntervalPollingController()<
362370
const currentTrialedProducts = this.state.trialedProducts;
363371
const currentCustomerId = this.state.customerId;
364372
const currentLastSubscription = this.state.lastSubscription;
373+
const currentRewardAccountId = this.state.rewardAccountId;
374+
365375
const {
366376
customerId: newCustomerId,
367377
subscriptions: newSubscriptions,
368378
trialedProducts: newTrialedProducts,
369379
lastSubscription: newLastSubscription,
380+
rewardAccountId: newRewardAccountId,
370381
} = await this.#subscriptionService.getSubscriptions();
371382

372383
// check if the new subscriptions are different from the current subscriptions
@@ -386,20 +397,23 @@ export class SubscriptionController extends StaticIntervalPollingController()<
386397
);
387398

388399
const areCustomerIdsEqual = currentCustomerId === newCustomerId;
389-
400+
const areRewardAccountIdsEqual =
401+
currentRewardAccountId === newRewardAccountId;
390402
// only update the state if the subscriptions or trialed products are different
391403
// this prevents unnecessary state updates events, easier for the clients to handle
392404
if (
393405
!areSubscriptionsEqual ||
394406
!isLastSubscriptionEqual ||
395407
!areTrialedProductsEqual ||
396-
!areCustomerIdsEqual
408+
!areCustomerIdsEqual ||
409+
!areRewardAccountIdsEqual
397410
) {
398411
this.update((state) => {
399412
state.subscriptions = newSubscriptions;
400413
state.customerId = newCustomerId;
401414
state.trialedProducts = newTrialedProducts;
402415
state.lastSubscription = newLastSubscription;
416+
state.rewardAccountId = newRewardAccountId;
403417
});
404418
// trigger access token refresh to ensure the user has the latest access token if subscription state change
405419
this.triggerAccessTokenRefresh();

packages/subscription-controller/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ export type GetSubscriptionsResponse = {
125125
trialedProducts: ProductType[];
126126
/** The last subscription that user has subscribed to if any. */
127127
lastSubscription?: Subscription;
128+
/** The reward account ID if user has linked rewards to the subscription. */
129+
rewardAccountId?: CaipAccountId;
128130
};
129131

130132
export type StartSubscriptionRequest = {

0 commit comments

Comments
 (0)