feat: update notification-services-controller to support new Segment schema#8944
feat: update notification-services-controller to support new Segment schema#8944zelkibuilds wants to merge 9 commits into
Conversation
9dbca22 to
9811cb9
Compare
e51bf05 to
16656ed
Compare
| export function getNotificationSubtype(notification: INotification): string { | ||
| switch (notification.type) { | ||
| case TRIGGER_TYPES.FEATURES_ANNOUNCEMENT: | ||
| // §5.3 calls for a stable per-campaign id here, pending confirmation from |
| if (notification.notification_type === 'on-chain') { | ||
| return notification.payload.data.kind; | ||
| } | ||
| // Platform: §5.3 wants the server-set `notification_subtype`. It is |
zelkibuilds
left a comment
There was a problem hiding this comment.
Left some open questions in PR description + code
| // re-fetch the inbox from the API to surface the new notification. | ||
| // eslint-disable-next-line @typescript-eslint/no-floating-promises | ||
| this.updateMetamaskNotificationsList(notification); | ||
| this.fetchAndUpdateMetamaskNotifications(); |
There was a problem hiding this comment.
Snap subtype not backfilled
Medium Severity
fetchAndUpdateMetamaskNotifications reuses existing snap rows from state as-is, so persisted snap notifications never gain the new required notification_subtype field unless they are replaced by a fresh processSnapNotification path.
Reviewed by Cursor Bugbot for commit b1c77d8. Configure here.
| notification_type: data.notification_type, | ||
| notification_subtype: data.notification_subtype ?? '', | ||
| profile_id: data.profile_id || undefined, | ||
| chain_id: data.chain_id ? Number(data.chain_id) : undefined, |
There was a problem hiding this comment.
Invalid chain_id becomes NaN
Low Severity
toPushAnalyticsPayload sets chain_id with Number(data.chain_id) whenever the string is truthy, so malformed FCM values can produce NaN on the analytics payload instead of omitting the field.
Reviewed by Cursor Bugbot for commit b1c77d8. Configure here.
b1c77d8 to
81b5f29
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 3 total unresolved issues (including 2 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 81b5f29. Configure here.
| notification_type: data.notification_type, | ||
| notification_subtype: data.notification_subtype ?? '', | ||
| profile_id: data.profile_id || undefined, | ||
| chain_id: data.chain_id ? Number(data.chain_id) : undefined, |
There was a problem hiding this comment.
Invalid chain_id becomes NaN
Low Severity
toPushAnalyticsPayload sets chain_id with Number(data.chain_id) whenever the FCM string is truthy, without checking the result. A non-numeric chain_id value becomes NaN, which still satisfies the optional number type but breaks downstream analytics or routing that expect a valid chain id.
Reviewed by Cursor Bugbot for commit 81b5f29. Configure here.


Explanation
Implements the
notification-services-controllerportion of the notifications-analytics rework (PLAN §5): push events expose first-class analytics fields, and the in-app model gains anotification_subtype.web/push-utils.tsnow reads the top-level FCM fields viatoPushAnalyticsPayloadinstead of JSON-parsingdata["data"]behind theisOnChainRawNotificationgate. All push kinds (on-chain/platform/snap/feature-announcement) flow through one path; the §5.5 banner-display gap goes away.PushAnalyticsPayload(notification_id,notification_type,notification_subtype,profile_id?,chain_id?,deeplink?). Both push events (onNewNotifications,pushNotificationClicked) now carry[PushAnalyticsPayload];createSubscribeToPushNotificationshandler signatures updated to match.notification_subtypefield toBaseNotification/INotification, populated in the processors via a newgetNotificationSubtype(n)helper (on-chain kind /snap/features_announcement/ platform fallback). Type-checking guarantees every processed notification carries it.id/typeareunchanged.
metadataparsing path and the nested blob.onNewNotificationssubscriber now re-fetches viafetchAndUpdateMetamaskNotifications()instead of inserting the payload.Open questions
PushAnalyticsPayloadinstead ofINotification— a breaking change. Confirm a flat replacement was intended (not the 3notification_*fields added onto the notification object).notification_subtypetoBaseNotification. Deferred: renamingid → notification_id(redundant withid) and adding a first-classnotification_type(collides with the existing structuralnotification_typeon API variants, and its value is unresolved — §2 sayswallet_activity, §6.6 usesitem.type). Confirmthe desired end-state.
uuid()inprocessSnapNotification— keep client-side or move upstream?notification_subtypenot returned by the inbox API (§4.3). The backend stores/stamps it (PR Enable and fix require-unicode-regexp issues #275 merged) but/api/v3/notificationsdoesn't expose it (verified againstnotify-notification-services@main), so the helper falls back totype(platform). Needs a follow-up to add it to the v3 response, then we regenerateschema.tsand flipthe TODO.
features_announcementas the single value; per-campaign id pending the announcements team.References
metamask-extension— §7 (feat: new segment schema support metamask-extension#43132)metamask-mobile— §6 (PR TBD)va-mmcx-notify-push-servicesfor the top-level FCM keys (PR TBD)Checklist
Note
High Risk
Breaking messenger and handler contracts require coordinated extension/mobile updates; push-driven inbox behavior now depends on API refetch instead of inline payload insertion.
Overview
Aligns notification-services-controller with the notifications analytics rework: push paths expose first-class Segment fields, and in-app notifications carry a normalized
notification_subtype.Push (breaking).
onNewNotificationsandpushNotificationClicked(andcreateSubscribeToPushNotificationshandlers) now emitPushAnalyticsPayload(notification_id,notification_type,notification_subtype, optionalprofile_id,chain_id,deeplink) instead ofINotification. Web push reads top-level FCMdataviatoPushAnalyticsPayload; the nesteddata["data"]/ on-chain JSON parsing path is removed. Because FCM no longer includes the full body, the inbox subscriber re-fetches withfetchAndUpdateMetamaskNotifications()instead of inserting from the push payload.In-app model.
notification_subtypeis required onBaseNotification/INotification, set in API, feature-announcement, and snap processors via sharedgetNotificationSubtype.getNotificationSubtypeandtoPushAnalyticsPayloadare exported for clients.Reviewed by Cursor Bugbot for commit 81b5f29. Bugbot is set up for automated code reviews on this repo. Configure here.